##// END OF EJS Templates
exchange: stop advertising rev-branch-cache bundle capability...
Joerg Sonnenberger -
r47378:7015b023 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,2561 +1,2563 b''
1 1 # bundle2.py - generic container format to transmit arbitrary data.
2 2 #
3 3 # Copyright 2013 Facebook, Inc.
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 """Handling of the new bundle2 format
8 8
9 9 The goal of bundle2 is to act as an atomically packet to transmit a set of
10 10 payloads in an application agnostic way. It consist in a sequence of "parts"
11 11 that will be handed to and processed by the application layer.
12 12
13 13
14 14 General format architecture
15 15 ===========================
16 16
17 17 The format is architectured as follow
18 18
19 19 - magic string
20 20 - stream level parameters
21 21 - payload parts (any number)
22 22 - end of stream marker.
23 23
24 24 the Binary format
25 25 ============================
26 26
27 27 All numbers are unsigned and big-endian.
28 28
29 29 stream level parameters
30 30 ------------------------
31 31
32 32 Binary format is as follow
33 33
34 34 :params size: int32
35 35
36 36 The total number of Bytes used by the parameters
37 37
38 38 :params value: arbitrary number of Bytes
39 39
40 40 A blob of `params size` containing the serialized version of all stream level
41 41 parameters.
42 42
43 43 The blob contains a space separated list of parameters. Parameters with value
44 44 are stored in the form `<name>=<value>`. Both name and value are urlquoted.
45 45
46 46 Empty name are obviously forbidden.
47 47
48 48 Name MUST start with a letter. If this first letter is lower case, the
49 49 parameter is advisory and can be safely ignored. However when the first
50 50 letter is capital, the parameter is mandatory and the bundling process MUST
51 51 stop if he is not able to proceed it.
52 52
53 53 Stream parameters use a simple textual format for two main reasons:
54 54
55 55 - Stream level parameters should remain simple and we want to discourage any
56 56 crazy usage.
57 57 - Textual data allow easy human inspection of a bundle2 header in case of
58 58 troubles.
59 59
60 60 Any Applicative level options MUST go into a bundle2 part instead.
61 61
62 62 Payload part
63 63 ------------------------
64 64
65 65 Binary format is as follow
66 66
67 67 :header size: int32
68 68
69 69 The total number of Bytes used by the part header. When the header is empty
70 70 (size = 0) this is interpreted as the end of stream marker.
71 71
72 72 :header:
73 73
74 74 The header defines how to interpret the part. It contains two piece of
75 75 data: the part type, and the part parameters.
76 76
77 77 The part type is used to route an application level handler, that can
78 78 interpret payload.
79 79
80 80 Part parameters are passed to the application level handler. They are
81 81 meant to convey information that will help the application level object to
82 82 interpret the part payload.
83 83
84 84 The binary format of the header is has follow
85 85
86 86 :typesize: (one byte)
87 87
88 88 :parttype: alphanumerical part name (restricted to [a-zA-Z0-9_:-]*)
89 89
90 90 :partid: A 32bits integer (unique in the bundle) that can be used to refer
91 91 to this part.
92 92
93 93 :parameters:
94 94
95 95 Part's parameter may have arbitrary content, the binary structure is::
96 96
97 97 <mandatory-count><advisory-count><param-sizes><param-data>
98 98
99 99 :mandatory-count: 1 byte, number of mandatory parameters
100 100
101 101 :advisory-count: 1 byte, number of advisory parameters
102 102
103 103 :param-sizes:
104 104
105 105 N couple of bytes, where N is the total number of parameters. Each
106 106 couple contains (<size-of-key>, <size-of-value) for one parameter.
107 107
108 108 :param-data:
109 109
110 110 A blob of bytes from which each parameter key and value can be
111 111 retrieved using the list of size couples stored in the previous
112 112 field.
113 113
114 114 Mandatory parameters comes first, then the advisory ones.
115 115
116 116 Each parameter's key MUST be unique within the part.
117 117
118 118 :payload:
119 119
120 120 payload is a series of `<chunksize><chunkdata>`.
121 121
122 122 `chunksize` is an int32, `chunkdata` are plain bytes (as much as
123 123 `chunksize` says)` The payload part is concluded by a zero size chunk.
124 124
125 125 The current implementation always produces either zero or one chunk.
126 126 This is an implementation limitation that will ultimately be lifted.
127 127
128 128 `chunksize` can be negative to trigger special case processing. No such
129 129 processing is in place yet.
130 130
131 131 Bundle processing
132 132 ============================
133 133
134 134 Each part is processed in order using a "part handler". Handler are registered
135 135 for a certain part type.
136 136
137 137 The matching of a part to its handler is case insensitive. The case of the
138 138 part type is used to know if a part is mandatory or advisory. If the Part type
139 139 contains any uppercase char it is considered mandatory. When no handler is
140 140 known for a Mandatory part, the process is aborted and an exception is raised.
141 141 If the part is advisory and no handler is known, the part is ignored. When the
142 142 process is aborted, the full bundle is still read from the stream to keep the
143 143 channel usable. But none of the part read from an abort are processed. In the
144 144 future, dropping the stream may become an option for channel we do not care to
145 145 preserve.
146 146 """
147 147
148 148 from __future__ import absolute_import, division
149 149
150 150 import collections
151 151 import errno
152 152 import os
153 153 import re
154 154 import string
155 155 import struct
156 156 import sys
157 157
158 158 from .i18n import _
159 159 from .node import (
160 160 hex,
161 161 nullid,
162 162 short,
163 163 )
164 164 from . import (
165 165 bookmarks,
166 166 changegroup,
167 167 encoding,
168 168 error,
169 169 obsolete,
170 170 phases,
171 171 pushkey,
172 172 pycompat,
173 173 requirements,
174 174 scmutil,
175 175 streamclone,
176 176 tags,
177 177 url,
178 178 util,
179 179 )
180 180 from .utils import stringutil
181 181
182 182 urlerr = util.urlerr
183 183 urlreq = util.urlreq
184 184
185 185 _pack = struct.pack
186 186 _unpack = struct.unpack
187 187
188 188 _fstreamparamsize = b'>i'
189 189 _fpartheadersize = b'>i'
190 190 _fparttypesize = b'>B'
191 191 _fpartid = b'>I'
192 192 _fpayloadsize = b'>i'
193 193 _fpartparamcount = b'>BB'
194 194
195 195 preferedchunksize = 32768
196 196
197 197 _parttypeforbidden = re.compile(b'[^a-zA-Z0-9_:-]')
198 198
199 199
200 200 def outdebug(ui, message):
201 201 """debug regarding output stream (bundling)"""
202 202 if ui.configbool(b'devel', b'bundle2.debug'):
203 203 ui.debug(b'bundle2-output: %s\n' % message)
204 204
205 205
206 206 def indebug(ui, message):
207 207 """debug on input stream (unbundling)"""
208 208 if ui.configbool(b'devel', b'bundle2.debug'):
209 209 ui.debug(b'bundle2-input: %s\n' % message)
210 210
211 211
212 212 def validateparttype(parttype):
213 213 """raise ValueError if a parttype contains invalid character"""
214 214 if _parttypeforbidden.search(parttype):
215 215 raise ValueError(parttype)
216 216
217 217
218 218 def _makefpartparamsizes(nbparams):
219 219 """return a struct format to read part parameter sizes
220 220
221 221 The number parameters is variable so we need to build that format
222 222 dynamically.
223 223 """
224 224 return b'>' + (b'BB' * nbparams)
225 225
226 226
227 227 parthandlermapping = {}
228 228
229 229
230 230 def parthandler(parttype, params=()):
231 231 """decorator that register a function as a bundle2 part handler
232 232
233 233 eg::
234 234
235 235 @parthandler('myparttype', ('mandatory', 'param', 'handled'))
236 236 def myparttypehandler(...):
237 237 '''process a part of type "my part".'''
238 238 ...
239 239 """
240 240 validateparttype(parttype)
241 241
242 242 def _decorator(func):
243 243 lparttype = parttype.lower() # enforce lower case matching.
244 244 assert lparttype not in parthandlermapping
245 245 parthandlermapping[lparttype] = func
246 246 func.params = frozenset(params)
247 247 return func
248 248
249 249 return _decorator
250 250
251 251
252 252 class unbundlerecords(object):
253 253 """keep record of what happens during and unbundle
254 254
255 255 New records are added using `records.add('cat', obj)`. Where 'cat' is a
256 256 category of record and obj is an arbitrary object.
257 257
258 258 `records['cat']` will return all entries of this category 'cat'.
259 259
260 260 Iterating on the object itself will yield `('category', obj)` tuples
261 261 for all entries.
262 262
263 263 All iterations happens in chronological order.
264 264 """
265 265
266 266 def __init__(self):
267 267 self._categories = {}
268 268 self._sequences = []
269 269 self._replies = {}
270 270
271 271 def add(self, category, entry, inreplyto=None):
272 272 """add a new record of a given category.
273 273
274 274 The entry can then be retrieved in the list returned by
275 275 self['category']."""
276 276 self._categories.setdefault(category, []).append(entry)
277 277 self._sequences.append((category, entry))
278 278 if inreplyto is not None:
279 279 self.getreplies(inreplyto).add(category, entry)
280 280
281 281 def getreplies(self, partid):
282 282 """get the records that are replies to a specific part"""
283 283 return self._replies.setdefault(partid, unbundlerecords())
284 284
285 285 def __getitem__(self, cat):
286 286 return tuple(self._categories.get(cat, ()))
287 287
288 288 def __iter__(self):
289 289 return iter(self._sequences)
290 290
291 291 def __len__(self):
292 292 return len(self._sequences)
293 293
294 294 def __nonzero__(self):
295 295 return bool(self._sequences)
296 296
297 297 __bool__ = __nonzero__
298 298
299 299
300 300 class bundleoperation(object):
301 301 """an object that represents a single bundling process
302 302
303 303 Its purpose is to carry unbundle-related objects and states.
304 304
305 305 A new object should be created at the beginning of each bundle processing.
306 306 The object is to be returned by the processing function.
307 307
308 308 The object has very little content now it will ultimately contain:
309 309 * an access to the repo the bundle is applied to,
310 310 * a ui object,
311 311 * a way to retrieve a transaction to add changes to the repo,
312 312 * a way to record the result of processing each part,
313 313 * a way to construct a bundle response when applicable.
314 314 """
315 315
316 316 def __init__(self, repo, transactiongetter, captureoutput=True, source=b''):
317 317 self.repo = repo
318 318 self.ui = repo.ui
319 319 self.records = unbundlerecords()
320 320 self.reply = None
321 321 self.captureoutput = captureoutput
322 322 self.hookargs = {}
323 323 self._gettransaction = transactiongetter
324 324 # carries value that can modify part behavior
325 325 self.modes = {}
326 326 self.source = source
327 327
328 328 def gettransaction(self):
329 329 transaction = self._gettransaction()
330 330
331 331 if self.hookargs:
332 332 # the ones added to the transaction supercede those added
333 333 # to the operation.
334 334 self.hookargs.update(transaction.hookargs)
335 335 transaction.hookargs = self.hookargs
336 336
337 337 # mark the hookargs as flushed. further attempts to add to
338 338 # hookargs will result in an abort.
339 339 self.hookargs = None
340 340
341 341 return transaction
342 342
343 343 def addhookargs(self, hookargs):
344 344 if self.hookargs is None:
345 345 raise error.ProgrammingError(
346 346 b'attempted to add hookargs to '
347 347 b'operation after transaction started'
348 348 )
349 349 self.hookargs.update(hookargs)
350 350
351 351
352 352 class TransactionUnavailable(RuntimeError):
353 353 pass
354 354
355 355
356 356 def _notransaction():
357 357 """default method to get a transaction while processing a bundle
358 358
359 359 Raise an exception to highlight the fact that no transaction was expected
360 360 to be created"""
361 361 raise TransactionUnavailable()
362 362
363 363
364 364 def applybundle(repo, unbundler, tr, source, url=None, **kwargs):
365 365 # transform me into unbundler.apply() as soon as the freeze is lifted
366 366 if isinstance(unbundler, unbundle20):
367 367 tr.hookargs[b'bundle2'] = b'1'
368 368 if source is not None and b'source' not in tr.hookargs:
369 369 tr.hookargs[b'source'] = source
370 370 if url is not None and b'url' not in tr.hookargs:
371 371 tr.hookargs[b'url'] = url
372 372 return processbundle(repo, unbundler, lambda: tr, source=source)
373 373 else:
374 374 # the transactiongetter won't be used, but we might as well set it
375 375 op = bundleoperation(repo, lambda: tr, source=source)
376 376 _processchangegroup(op, unbundler, tr, source, url, **kwargs)
377 377 return op
378 378
379 379
380 380 class partiterator(object):
381 381 def __init__(self, repo, op, unbundler):
382 382 self.repo = repo
383 383 self.op = op
384 384 self.unbundler = unbundler
385 385 self.iterator = None
386 386 self.count = 0
387 387 self.current = None
388 388
389 389 def __enter__(self):
390 390 def func():
391 391 itr = enumerate(self.unbundler.iterparts(), 1)
392 392 for count, p in itr:
393 393 self.count = count
394 394 self.current = p
395 395 yield p
396 396 p.consume()
397 397 self.current = None
398 398
399 399 self.iterator = func()
400 400 return self.iterator
401 401
402 402 def __exit__(self, type, exc, tb):
403 403 if not self.iterator:
404 404 return
405 405
406 406 # Only gracefully abort in a normal exception situation. User aborts
407 407 # like Ctrl+C throw a KeyboardInterrupt which is not a base Exception,
408 408 # and should not gracefully cleanup.
409 409 if isinstance(exc, Exception):
410 410 # Any exceptions seeking to the end of the bundle at this point are
411 411 # almost certainly related to the underlying stream being bad.
412 412 # And, chances are that the exception we're handling is related to
413 413 # getting in that bad state. So, we swallow the seeking error and
414 414 # re-raise the original error.
415 415 seekerror = False
416 416 try:
417 417 if self.current:
418 418 # consume the part content to not corrupt the stream.
419 419 self.current.consume()
420 420
421 421 for part in self.iterator:
422 422 # consume the bundle content
423 423 part.consume()
424 424 except Exception:
425 425 seekerror = True
426 426
427 427 # Small hack to let caller code distinguish exceptions from bundle2
428 428 # processing from processing the old format. This is mostly needed
429 429 # to handle different return codes to unbundle according to the type
430 430 # of bundle. We should probably clean up or drop this return code
431 431 # craziness in a future version.
432 432 exc.duringunbundle2 = True
433 433 salvaged = []
434 434 replycaps = None
435 435 if self.op.reply is not None:
436 436 salvaged = self.op.reply.salvageoutput()
437 437 replycaps = self.op.reply.capabilities
438 438 exc._replycaps = replycaps
439 439 exc._bundle2salvagedoutput = salvaged
440 440
441 441 # Re-raising from a variable loses the original stack. So only use
442 442 # that form if we need to.
443 443 if seekerror:
444 444 raise exc
445 445
446 446 self.repo.ui.debug(
447 447 b'bundle2-input-bundle: %i parts total\n' % self.count
448 448 )
449 449
450 450
451 451 def processbundle(repo, unbundler, transactiongetter=None, op=None, source=b''):
452 452 """This function process a bundle, apply effect to/from a repo
453 453
454 454 It iterates over each part then searches for and uses the proper handling
455 455 code to process the part. Parts are processed in order.
456 456
457 457 Unknown Mandatory part will abort the process.
458 458
459 459 It is temporarily possible to provide a prebuilt bundleoperation to the
460 460 function. This is used to ensure output is properly propagated in case of
461 461 an error during the unbundling. This output capturing part will likely be
462 462 reworked and this ability will probably go away in the process.
463 463 """
464 464 if op is None:
465 465 if transactiongetter is None:
466 466 transactiongetter = _notransaction
467 467 op = bundleoperation(repo, transactiongetter, source=source)
468 468 # todo:
469 469 # - replace this is a init function soon.
470 470 # - exception catching
471 471 unbundler.params
472 472 if repo.ui.debugflag:
473 473 msg = [b'bundle2-input-bundle:']
474 474 if unbundler.params:
475 475 msg.append(b' %i params' % len(unbundler.params))
476 476 if op._gettransaction is None or op._gettransaction is _notransaction:
477 477 msg.append(b' no-transaction')
478 478 else:
479 479 msg.append(b' with-transaction')
480 480 msg.append(b'\n')
481 481 repo.ui.debug(b''.join(msg))
482 482
483 483 processparts(repo, op, unbundler)
484 484
485 485 return op
486 486
487 487
488 488 def processparts(repo, op, unbundler):
489 489 with partiterator(repo, op, unbundler) as parts:
490 490 for part in parts:
491 491 _processpart(op, part)
492 492
493 493
494 494 def _processchangegroup(op, cg, tr, source, url, **kwargs):
495 495 ret = cg.apply(op.repo, tr, source, url, **kwargs)
496 496 op.records.add(
497 497 b'changegroup',
498 498 {
499 499 b'return': ret,
500 500 },
501 501 )
502 502 return ret
503 503
504 504
505 505 def _gethandler(op, part):
506 506 status = b'unknown' # used by debug output
507 507 try:
508 508 handler = parthandlermapping.get(part.type)
509 509 if handler is None:
510 510 status = b'unsupported-type'
511 511 raise error.BundleUnknownFeatureError(parttype=part.type)
512 512 indebug(op.ui, b'found a handler for part %s' % part.type)
513 513 unknownparams = part.mandatorykeys - handler.params
514 514 if unknownparams:
515 515 unknownparams = list(unknownparams)
516 516 unknownparams.sort()
517 517 status = b'unsupported-params (%s)' % b', '.join(unknownparams)
518 518 raise error.BundleUnknownFeatureError(
519 519 parttype=part.type, params=unknownparams
520 520 )
521 521 status = b'supported'
522 522 except error.BundleUnknownFeatureError as exc:
523 523 if part.mandatory: # mandatory parts
524 524 raise
525 525 indebug(op.ui, b'ignoring unsupported advisory part %s' % exc)
526 526 return # skip to part processing
527 527 finally:
528 528 if op.ui.debugflag:
529 529 msg = [b'bundle2-input-part: "%s"' % part.type]
530 530 if not part.mandatory:
531 531 msg.append(b' (advisory)')
532 532 nbmp = len(part.mandatorykeys)
533 533 nbap = len(part.params) - nbmp
534 534 if nbmp or nbap:
535 535 msg.append(b' (params:')
536 536 if nbmp:
537 537 msg.append(b' %i mandatory' % nbmp)
538 538 if nbap:
539 539 msg.append(b' %i advisory' % nbmp)
540 540 msg.append(b')')
541 541 msg.append(b' %s\n' % status)
542 542 op.ui.debug(b''.join(msg))
543 543
544 544 return handler
545 545
546 546
547 547 def _processpart(op, part):
548 548 """process a single part from a bundle
549 549
550 550 The part is guaranteed to have been fully consumed when the function exits
551 551 (even if an exception is raised)."""
552 552 handler = _gethandler(op, part)
553 553 if handler is None:
554 554 return
555 555
556 556 # handler is called outside the above try block so that we don't
557 557 # risk catching KeyErrors from anything other than the
558 558 # parthandlermapping lookup (any KeyError raised by handler()
559 559 # itself represents a defect of a different variety).
560 560 output = None
561 561 if op.captureoutput and op.reply is not None:
562 562 op.ui.pushbuffer(error=True, subproc=True)
563 563 output = b''
564 564 try:
565 565 handler(op, part)
566 566 finally:
567 567 if output is not None:
568 568 output = op.ui.popbuffer()
569 569 if output:
570 570 outpart = op.reply.newpart(b'output', data=output, mandatory=False)
571 571 outpart.addparam(
572 572 b'in-reply-to', pycompat.bytestr(part.id), mandatory=False
573 573 )
574 574
575 575
576 576 def decodecaps(blob):
577 577 """decode a bundle2 caps bytes blob into a dictionary
578 578
579 579 The blob is a list of capabilities (one per line)
580 580 Capabilities may have values using a line of the form::
581 581
582 582 capability=value1,value2,value3
583 583
584 584 The values are always a list."""
585 585 caps = {}
586 586 for line in blob.splitlines():
587 587 if not line:
588 588 continue
589 589 if b'=' not in line:
590 590 key, vals = line, ()
591 591 else:
592 592 key, vals = line.split(b'=', 1)
593 593 vals = vals.split(b',')
594 594 key = urlreq.unquote(key)
595 595 vals = [urlreq.unquote(v) for v in vals]
596 596 caps[key] = vals
597 597 return caps
598 598
599 599
600 600 def encodecaps(caps):
601 601 """encode a bundle2 caps dictionary into a bytes blob"""
602 602 chunks = []
603 603 for ca in sorted(caps):
604 604 vals = caps[ca]
605 605 ca = urlreq.quote(ca)
606 606 vals = [urlreq.quote(v) for v in vals]
607 607 if vals:
608 608 ca = b"%s=%s" % (ca, b','.join(vals))
609 609 chunks.append(ca)
610 610 return b'\n'.join(chunks)
611 611
612 612
613 613 bundletypes = {
614 614 b"": (b"", b'UN'), # only when using unbundle on ssh and old http servers
615 615 # since the unification ssh accepts a header but there
616 616 # is no capability signaling it.
617 617 b"HG20": (), # special-cased below
618 618 b"HG10UN": (b"HG10UN", b'UN'),
619 619 b"HG10BZ": (b"HG10", b'BZ'),
620 620 b"HG10GZ": (b"HG10GZ", b'GZ'),
621 621 }
622 622
623 623 # hgweb uses this list to communicate its preferred type
624 624 bundlepriority = [b'HG10GZ', b'HG10BZ', b'HG10UN']
625 625
626 626
627 627 class bundle20(object):
628 628 """represent an outgoing bundle2 container
629 629
630 630 Use the `addparam` method to add stream level parameter. and `newpart` to
631 631 populate it. Then call `getchunks` to retrieve all the binary chunks of
632 632 data that compose the bundle2 container."""
633 633
634 634 _magicstring = b'HG20'
635 635
636 636 def __init__(self, ui, capabilities=()):
637 637 self.ui = ui
638 638 self._params = []
639 639 self._parts = []
640 640 self.capabilities = dict(capabilities)
641 641 self._compengine = util.compengines.forbundletype(b'UN')
642 642 self._compopts = None
643 643 # If compression is being handled by a consumer of the raw
644 644 # data (e.g. the wire protocol), unsetting this flag tells
645 645 # consumers that the bundle is best left uncompressed.
646 646 self.prefercompressed = True
647 647
648 648 def setcompression(self, alg, compopts=None):
649 649 """setup core part compression to <alg>"""
650 650 if alg in (None, b'UN'):
651 651 return
652 652 assert not any(n.lower() == b'compression' for n, v in self._params)
653 653 self.addparam(b'Compression', alg)
654 654 self._compengine = util.compengines.forbundletype(alg)
655 655 self._compopts = compopts
656 656
657 657 @property
658 658 def nbparts(self):
659 659 """total number of parts added to the bundler"""
660 660 return len(self._parts)
661 661
662 662 # methods used to defines the bundle2 content
663 663 def addparam(self, name, value=None):
664 664 """add a stream level parameter"""
665 665 if not name:
666 666 raise error.ProgrammingError(b'empty parameter name')
667 667 if name[0:1] not in pycompat.bytestr(
668 668 string.ascii_letters # pytype: disable=wrong-arg-types
669 669 ):
670 670 raise error.ProgrammingError(
671 671 b'non letter first character: %s' % name
672 672 )
673 673 self._params.append((name, value))
674 674
675 675 def addpart(self, part):
676 676 """add a new part to the bundle2 container
677 677
678 678 Parts contains the actual applicative payload."""
679 679 assert part.id is None
680 680 part.id = len(self._parts) # very cheap counter
681 681 self._parts.append(part)
682 682
683 683 def newpart(self, typeid, *args, **kwargs):
684 684 """create a new part and add it to the containers
685 685
686 686 As the part is directly added to the containers. For now, this means
687 687 that any failure to properly initialize the part after calling
688 688 ``newpart`` should result in a failure of the whole bundling process.
689 689
690 690 You can still fall back to manually create and add if you need better
691 691 control."""
692 692 part = bundlepart(typeid, *args, **kwargs)
693 693 self.addpart(part)
694 694 return part
695 695
696 696 # methods used to generate the bundle2 stream
697 697 def getchunks(self):
698 698 if self.ui.debugflag:
699 699 msg = [b'bundle2-output-bundle: "%s",' % self._magicstring]
700 700 if self._params:
701 701 msg.append(b' (%i params)' % len(self._params))
702 702 msg.append(b' %i parts total\n' % len(self._parts))
703 703 self.ui.debug(b''.join(msg))
704 704 outdebug(self.ui, b'start emission of %s stream' % self._magicstring)
705 705 yield self._magicstring
706 706 param = self._paramchunk()
707 707 outdebug(self.ui, b'bundle parameter: %s' % param)
708 708 yield _pack(_fstreamparamsize, len(param))
709 709 if param:
710 710 yield param
711 711 for chunk in self._compengine.compressstream(
712 712 self._getcorechunk(), self._compopts
713 713 ):
714 714 yield chunk
715 715
716 716 def _paramchunk(self):
717 717 """return a encoded version of all stream parameters"""
718 718 blocks = []
719 719 for par, value in self._params:
720 720 par = urlreq.quote(par)
721 721 if value is not None:
722 722 value = urlreq.quote(value)
723 723 par = b'%s=%s' % (par, value)
724 724 blocks.append(par)
725 725 return b' '.join(blocks)
726 726
727 727 def _getcorechunk(self):
728 728 """yield chunk for the core part of the bundle
729 729
730 730 (all but headers and parameters)"""
731 731 outdebug(self.ui, b'start of parts')
732 732 for part in self._parts:
733 733 outdebug(self.ui, b'bundle part: "%s"' % part.type)
734 734 for chunk in part.getchunks(ui=self.ui):
735 735 yield chunk
736 736 outdebug(self.ui, b'end of bundle')
737 737 yield _pack(_fpartheadersize, 0)
738 738
739 739 def salvageoutput(self):
740 740 """return a list with a copy of all output parts in the bundle
741 741
742 742 This is meant to be used during error handling to make sure we preserve
743 743 server output"""
744 744 salvaged = []
745 745 for part in self._parts:
746 746 if part.type.startswith(b'output'):
747 747 salvaged.append(part.copy())
748 748 return salvaged
749 749
750 750
751 751 class unpackermixin(object):
752 752 """A mixin to extract bytes and struct data from a stream"""
753 753
754 754 def __init__(self, fp):
755 755 self._fp = fp
756 756
757 757 def _unpack(self, format):
758 758 """unpack this struct format from the stream
759 759
760 760 This method is meant for internal usage by the bundle2 protocol only.
761 761 They directly manipulate the low level stream including bundle2 level
762 762 instruction.
763 763
764 764 Do not use it to implement higher-level logic or methods."""
765 765 data = self._readexact(struct.calcsize(format))
766 766 return _unpack(format, data)
767 767
768 768 def _readexact(self, size):
769 769 """read exactly <size> bytes from the stream
770 770
771 771 This method is meant for internal usage by the bundle2 protocol only.
772 772 They directly manipulate the low level stream including bundle2 level
773 773 instruction.
774 774
775 775 Do not use it to implement higher-level logic or methods."""
776 776 return changegroup.readexactly(self._fp, size)
777 777
778 778
779 779 def getunbundler(ui, fp, magicstring=None):
780 780 """return a valid unbundler object for a given magicstring"""
781 781 if magicstring is None:
782 782 magicstring = changegroup.readexactly(fp, 4)
783 783 magic, version = magicstring[0:2], magicstring[2:4]
784 784 if magic != b'HG':
785 785 ui.debug(
786 786 b"error: invalid magic: %r (version %r), should be 'HG'\n"
787 787 % (magic, version)
788 788 )
789 789 raise error.Abort(_(b'not a Mercurial bundle'))
790 790 unbundlerclass = formatmap.get(version)
791 791 if unbundlerclass is None:
792 792 raise error.Abort(_(b'unknown bundle version %s') % version)
793 793 unbundler = unbundlerclass(ui, fp)
794 794 indebug(ui, b'start processing of %s stream' % magicstring)
795 795 return unbundler
796 796
797 797
798 798 class unbundle20(unpackermixin):
799 799 """interpret a bundle2 stream
800 800
801 801 This class is fed with a binary stream and yields parts through its
802 802 `iterparts` methods."""
803 803
804 804 _magicstring = b'HG20'
805 805
806 806 def __init__(self, ui, fp):
807 807 """If header is specified, we do not read it out of the stream."""
808 808 self.ui = ui
809 809 self._compengine = util.compengines.forbundletype(b'UN')
810 810 self._compressed = None
811 811 super(unbundle20, self).__init__(fp)
812 812
813 813 @util.propertycache
814 814 def params(self):
815 815 """dictionary of stream level parameters"""
816 816 indebug(self.ui, b'reading bundle2 stream parameters')
817 817 params = {}
818 818 paramssize = self._unpack(_fstreamparamsize)[0]
819 819 if paramssize < 0:
820 820 raise error.BundleValueError(
821 821 b'negative bundle param size: %i' % paramssize
822 822 )
823 823 if paramssize:
824 824 params = self._readexact(paramssize)
825 825 params = self._processallparams(params)
826 826 return params
827 827
828 828 def _processallparams(self, paramsblock):
829 829 """"""
830 830 params = util.sortdict()
831 831 for p in paramsblock.split(b' '):
832 832 p = p.split(b'=', 1)
833 833 p = [urlreq.unquote(i) for i in p]
834 834 if len(p) < 2:
835 835 p.append(None)
836 836 self._processparam(*p)
837 837 params[p[0]] = p[1]
838 838 return params
839 839
840 840 def _processparam(self, name, value):
841 841 """process a parameter, applying its effect if needed
842 842
843 843 Parameter starting with a lower case letter are advisory and will be
844 844 ignored when unknown. Those starting with an upper case letter are
845 845 mandatory and will this function will raise a KeyError when unknown.
846 846
847 847 Note: no option are currently supported. Any input will be either
848 848 ignored or failing.
849 849 """
850 850 if not name:
851 851 raise ValueError('empty parameter name')
852 852 if name[0:1] not in pycompat.bytestr(
853 853 string.ascii_letters # pytype: disable=wrong-arg-types
854 854 ):
855 855 raise ValueError('non letter first character: %s' % name)
856 856 try:
857 857 handler = b2streamparamsmap[name.lower()]
858 858 except KeyError:
859 859 if name[0:1].islower():
860 860 indebug(self.ui, b"ignoring unknown parameter %s" % name)
861 861 else:
862 862 raise error.BundleUnknownFeatureError(params=(name,))
863 863 else:
864 864 handler(self, name, value)
865 865
866 866 def _forwardchunks(self):
867 867 """utility to transfer a bundle2 as binary
868 868
869 869 This is made necessary by the fact the 'getbundle' command over 'ssh'
870 870 have no way to know then the reply end, relying on the bundle to be
871 871 interpreted to know its end. This is terrible and we are sorry, but we
872 872 needed to move forward to get general delta enabled.
873 873 """
874 874 yield self._magicstring
875 875 assert 'params' not in vars(self)
876 876 paramssize = self._unpack(_fstreamparamsize)[0]
877 877 if paramssize < 0:
878 878 raise error.BundleValueError(
879 879 b'negative bundle param size: %i' % paramssize
880 880 )
881 881 if paramssize:
882 882 params = self._readexact(paramssize)
883 883 self._processallparams(params)
884 884 # The payload itself is decompressed below, so drop
885 885 # the compression parameter passed down to compensate.
886 886 outparams = []
887 887 for p in params.split(b' '):
888 888 k, v = p.split(b'=', 1)
889 889 if k.lower() != b'compression':
890 890 outparams.append(p)
891 891 outparams = b' '.join(outparams)
892 892 yield _pack(_fstreamparamsize, len(outparams))
893 893 yield outparams
894 894 else:
895 895 yield _pack(_fstreamparamsize, paramssize)
896 896 # From there, payload might need to be decompressed
897 897 self._fp = self._compengine.decompressorreader(self._fp)
898 898 emptycount = 0
899 899 while emptycount < 2:
900 900 # so we can brainlessly loop
901 901 assert _fpartheadersize == _fpayloadsize
902 902 size = self._unpack(_fpartheadersize)[0]
903 903 yield _pack(_fpartheadersize, size)
904 904 if size:
905 905 emptycount = 0
906 906 else:
907 907 emptycount += 1
908 908 continue
909 909 if size == flaginterrupt:
910 910 continue
911 911 elif size < 0:
912 912 raise error.BundleValueError(b'negative chunk size: %i')
913 913 yield self._readexact(size)
914 914
915 915 def iterparts(self, seekable=False):
916 916 """yield all parts contained in the stream"""
917 917 cls = seekableunbundlepart if seekable else unbundlepart
918 918 # make sure param have been loaded
919 919 self.params
920 920 # From there, payload need to be decompressed
921 921 self._fp = self._compengine.decompressorreader(self._fp)
922 922 indebug(self.ui, b'start extraction of bundle2 parts')
923 923 headerblock = self._readpartheader()
924 924 while headerblock is not None:
925 925 part = cls(self.ui, headerblock, self._fp)
926 926 yield part
927 927 # Ensure part is fully consumed so we can start reading the next
928 928 # part.
929 929 part.consume()
930 930
931 931 headerblock = self._readpartheader()
932 932 indebug(self.ui, b'end of bundle2 stream')
933 933
934 934 def _readpartheader(self):
935 935 """reads a part header size and return the bytes blob
936 936
937 937 returns None if empty"""
938 938 headersize = self._unpack(_fpartheadersize)[0]
939 939 if headersize < 0:
940 940 raise error.BundleValueError(
941 941 b'negative part header size: %i' % headersize
942 942 )
943 943 indebug(self.ui, b'part header size: %i' % headersize)
944 944 if headersize:
945 945 return self._readexact(headersize)
946 946 return None
947 947
948 948 def compressed(self):
949 949 self.params # load params
950 950 return self._compressed
951 951
952 952 def close(self):
953 953 """close underlying file"""
954 954 if util.safehasattr(self._fp, 'close'):
955 955 return self._fp.close()
956 956
957 957
958 958 formatmap = {b'20': unbundle20}
959 959
960 960 b2streamparamsmap = {}
961 961
962 962
963 963 def b2streamparamhandler(name):
964 964 """register a handler for a stream level parameter"""
965 965
966 966 def decorator(func):
967 967 assert name not in formatmap
968 968 b2streamparamsmap[name] = func
969 969 return func
970 970
971 971 return decorator
972 972
973 973
974 974 @b2streamparamhandler(b'compression')
975 975 def processcompression(unbundler, param, value):
976 976 """read compression parameter and install payload decompression"""
977 977 if value not in util.compengines.supportedbundletypes:
978 978 raise error.BundleUnknownFeatureError(params=(param,), values=(value,))
979 979 unbundler._compengine = util.compengines.forbundletype(value)
980 980 if value is not None:
981 981 unbundler._compressed = True
982 982
983 983
984 984 class bundlepart(object):
985 985 """A bundle2 part contains application level payload
986 986
987 987 The part `type` is used to route the part to the application level
988 988 handler.
989 989
990 990 The part payload is contained in ``part.data``. It could be raw bytes or a
991 991 generator of byte chunks.
992 992
993 993 You can add parameters to the part using the ``addparam`` method.
994 994 Parameters can be either mandatory (default) or advisory. Remote side
995 995 should be able to safely ignore the advisory ones.
996 996
997 997 Both data and parameters cannot be modified after the generation has begun.
998 998 """
999 999
1000 1000 def __init__(
1001 1001 self,
1002 1002 parttype,
1003 1003 mandatoryparams=(),
1004 1004 advisoryparams=(),
1005 1005 data=b'',
1006 1006 mandatory=True,
1007 1007 ):
1008 1008 validateparttype(parttype)
1009 1009 self.id = None
1010 1010 self.type = parttype
1011 1011 self._data = data
1012 1012 self._mandatoryparams = list(mandatoryparams)
1013 1013 self._advisoryparams = list(advisoryparams)
1014 1014 # checking for duplicated entries
1015 1015 self._seenparams = set()
1016 1016 for pname, __ in self._mandatoryparams + self._advisoryparams:
1017 1017 if pname in self._seenparams:
1018 1018 raise error.ProgrammingError(b'duplicated params: %s' % pname)
1019 1019 self._seenparams.add(pname)
1020 1020 # status of the part's generation:
1021 1021 # - None: not started,
1022 1022 # - False: currently generated,
1023 1023 # - True: generation done.
1024 1024 self._generated = None
1025 1025 self.mandatory = mandatory
1026 1026
1027 1027 def __repr__(self):
1028 1028 cls = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
1029 1029 return '<%s object at %x; id: %s; type: %s; mandatory: %s>' % (
1030 1030 cls,
1031 1031 id(self),
1032 1032 self.id,
1033 1033 self.type,
1034 1034 self.mandatory,
1035 1035 )
1036 1036
1037 1037 def copy(self):
1038 1038 """return a copy of the part
1039 1039
1040 1040 The new part have the very same content but no partid assigned yet.
1041 1041 Parts with generated data cannot be copied."""
1042 1042 assert not util.safehasattr(self.data, 'next')
1043 1043 return self.__class__(
1044 1044 self.type,
1045 1045 self._mandatoryparams,
1046 1046 self._advisoryparams,
1047 1047 self._data,
1048 1048 self.mandatory,
1049 1049 )
1050 1050
1051 1051 # methods used to defines the part content
1052 1052 @property
1053 1053 def data(self):
1054 1054 return self._data
1055 1055
1056 1056 @data.setter
1057 1057 def data(self, data):
1058 1058 if self._generated is not None:
1059 1059 raise error.ReadOnlyPartError(b'part is being generated')
1060 1060 self._data = data
1061 1061
1062 1062 @property
1063 1063 def mandatoryparams(self):
1064 1064 # make it an immutable tuple to force people through ``addparam``
1065 1065 return tuple(self._mandatoryparams)
1066 1066
1067 1067 @property
1068 1068 def advisoryparams(self):
1069 1069 # make it an immutable tuple to force people through ``addparam``
1070 1070 return tuple(self._advisoryparams)
1071 1071
1072 1072 def addparam(self, name, value=b'', mandatory=True):
1073 1073 """add a parameter to the part
1074 1074
1075 1075 If 'mandatory' is set to True, the remote handler must claim support
1076 1076 for this parameter or the unbundling will be aborted.
1077 1077
1078 1078 The 'name' and 'value' cannot exceed 255 bytes each.
1079 1079 """
1080 1080 if self._generated is not None:
1081 1081 raise error.ReadOnlyPartError(b'part is being generated')
1082 1082 if name in self._seenparams:
1083 1083 raise ValueError(b'duplicated params: %s' % name)
1084 1084 self._seenparams.add(name)
1085 1085 params = self._advisoryparams
1086 1086 if mandatory:
1087 1087 params = self._mandatoryparams
1088 1088 params.append((name, value))
1089 1089
1090 1090 # methods used to generates the bundle2 stream
1091 1091 def getchunks(self, ui):
1092 1092 if self._generated is not None:
1093 1093 raise error.ProgrammingError(b'part can only be consumed once')
1094 1094 self._generated = False
1095 1095
1096 1096 if ui.debugflag:
1097 1097 msg = [b'bundle2-output-part: "%s"' % self.type]
1098 1098 if not self.mandatory:
1099 1099 msg.append(b' (advisory)')
1100 1100 nbmp = len(self.mandatoryparams)
1101 1101 nbap = len(self.advisoryparams)
1102 1102 if nbmp or nbap:
1103 1103 msg.append(b' (params:')
1104 1104 if nbmp:
1105 1105 msg.append(b' %i mandatory' % nbmp)
1106 1106 if nbap:
1107 1107 msg.append(b' %i advisory' % nbmp)
1108 1108 msg.append(b')')
1109 1109 if not self.data:
1110 1110 msg.append(b' empty payload')
1111 1111 elif util.safehasattr(self.data, 'next') or util.safehasattr(
1112 1112 self.data, b'__next__'
1113 1113 ):
1114 1114 msg.append(b' streamed payload')
1115 1115 else:
1116 1116 msg.append(b' %i bytes payload' % len(self.data))
1117 1117 msg.append(b'\n')
1118 1118 ui.debug(b''.join(msg))
1119 1119
1120 1120 #### header
1121 1121 if self.mandatory:
1122 1122 parttype = self.type.upper()
1123 1123 else:
1124 1124 parttype = self.type.lower()
1125 1125 outdebug(ui, b'part %s: "%s"' % (pycompat.bytestr(self.id), parttype))
1126 1126 ## parttype
1127 1127 header = [
1128 1128 _pack(_fparttypesize, len(parttype)),
1129 1129 parttype,
1130 1130 _pack(_fpartid, self.id),
1131 1131 ]
1132 1132 ## parameters
1133 1133 # count
1134 1134 manpar = self.mandatoryparams
1135 1135 advpar = self.advisoryparams
1136 1136 header.append(_pack(_fpartparamcount, len(manpar), len(advpar)))
1137 1137 # size
1138 1138 parsizes = []
1139 1139 for key, value in manpar:
1140 1140 parsizes.append(len(key))
1141 1141 parsizes.append(len(value))
1142 1142 for key, value in advpar:
1143 1143 parsizes.append(len(key))
1144 1144 parsizes.append(len(value))
1145 1145 paramsizes = _pack(_makefpartparamsizes(len(parsizes) // 2), *parsizes)
1146 1146 header.append(paramsizes)
1147 1147 # key, value
1148 1148 for key, value in manpar:
1149 1149 header.append(key)
1150 1150 header.append(value)
1151 1151 for key, value in advpar:
1152 1152 header.append(key)
1153 1153 header.append(value)
1154 1154 ## finalize header
1155 1155 try:
1156 1156 headerchunk = b''.join(header)
1157 1157 except TypeError:
1158 1158 raise TypeError(
1159 1159 'Found a non-bytes trying to '
1160 1160 'build bundle part header: %r' % header
1161 1161 )
1162 1162 outdebug(ui, b'header chunk size: %i' % len(headerchunk))
1163 1163 yield _pack(_fpartheadersize, len(headerchunk))
1164 1164 yield headerchunk
1165 1165 ## payload
1166 1166 try:
1167 1167 for chunk in self._payloadchunks():
1168 1168 outdebug(ui, b'payload chunk size: %i' % len(chunk))
1169 1169 yield _pack(_fpayloadsize, len(chunk))
1170 1170 yield chunk
1171 1171 except GeneratorExit:
1172 1172 # GeneratorExit means that nobody is listening for our
1173 1173 # results anyway, so just bail quickly rather than trying
1174 1174 # to produce an error part.
1175 1175 ui.debug(b'bundle2-generatorexit\n')
1176 1176 raise
1177 1177 except BaseException as exc:
1178 1178 bexc = stringutil.forcebytestr(exc)
1179 1179 # backup exception data for later
1180 1180 ui.debug(
1181 1181 b'bundle2-input-stream-interrupt: encoding exception %s' % bexc
1182 1182 )
1183 1183 tb = sys.exc_info()[2]
1184 1184 msg = b'unexpected error: %s' % bexc
1185 1185 interpart = bundlepart(
1186 1186 b'error:abort', [(b'message', msg)], mandatory=False
1187 1187 )
1188 1188 interpart.id = 0
1189 1189 yield _pack(_fpayloadsize, -1)
1190 1190 for chunk in interpart.getchunks(ui=ui):
1191 1191 yield chunk
1192 1192 outdebug(ui, b'closing payload chunk')
1193 1193 # abort current part payload
1194 1194 yield _pack(_fpayloadsize, 0)
1195 1195 pycompat.raisewithtb(exc, tb)
1196 1196 # end of payload
1197 1197 outdebug(ui, b'closing payload chunk')
1198 1198 yield _pack(_fpayloadsize, 0)
1199 1199 self._generated = True
1200 1200
1201 1201 def _payloadchunks(self):
1202 1202 """yield chunks of a the part payload
1203 1203
1204 1204 Exists to handle the different methods to provide data to a part."""
1205 1205 # we only support fixed size data now.
1206 1206 # This will be improved in the future.
1207 1207 if util.safehasattr(self.data, 'next') or util.safehasattr(
1208 1208 self.data, b'__next__'
1209 1209 ):
1210 1210 buff = util.chunkbuffer(self.data)
1211 1211 chunk = buff.read(preferedchunksize)
1212 1212 while chunk:
1213 1213 yield chunk
1214 1214 chunk = buff.read(preferedchunksize)
1215 1215 elif len(self.data):
1216 1216 yield self.data
1217 1217
1218 1218
1219 1219 flaginterrupt = -1
1220 1220
1221 1221
1222 1222 class interrupthandler(unpackermixin):
1223 1223 """read one part and process it with restricted capability
1224 1224
1225 1225 This allows to transmit exception raised on the producer size during part
1226 1226 iteration while the consumer is reading a part.
1227 1227
1228 1228 Part processed in this manner only have access to a ui object,"""
1229 1229
1230 1230 def __init__(self, ui, fp):
1231 1231 super(interrupthandler, self).__init__(fp)
1232 1232 self.ui = ui
1233 1233
1234 1234 def _readpartheader(self):
1235 1235 """reads a part header size and return the bytes blob
1236 1236
1237 1237 returns None if empty"""
1238 1238 headersize = self._unpack(_fpartheadersize)[0]
1239 1239 if headersize < 0:
1240 1240 raise error.BundleValueError(
1241 1241 b'negative part header size: %i' % headersize
1242 1242 )
1243 1243 indebug(self.ui, b'part header size: %i\n' % headersize)
1244 1244 if headersize:
1245 1245 return self._readexact(headersize)
1246 1246 return None
1247 1247
1248 1248 def __call__(self):
1249 1249
1250 1250 self.ui.debug(
1251 1251 b'bundle2-input-stream-interrupt: opening out of band context\n'
1252 1252 )
1253 1253 indebug(self.ui, b'bundle2 stream interruption, looking for a part.')
1254 1254 headerblock = self._readpartheader()
1255 1255 if headerblock is None:
1256 1256 indebug(self.ui, b'no part found during interruption.')
1257 1257 return
1258 1258 part = unbundlepart(self.ui, headerblock, self._fp)
1259 1259 op = interruptoperation(self.ui)
1260 1260 hardabort = False
1261 1261 try:
1262 1262 _processpart(op, part)
1263 1263 except (SystemExit, KeyboardInterrupt):
1264 1264 hardabort = True
1265 1265 raise
1266 1266 finally:
1267 1267 if not hardabort:
1268 1268 part.consume()
1269 1269 self.ui.debug(
1270 1270 b'bundle2-input-stream-interrupt: closing out of band context\n'
1271 1271 )
1272 1272
1273 1273
1274 1274 class interruptoperation(object):
1275 1275 """A limited operation to be use by part handler during interruption
1276 1276
1277 1277 It only have access to an ui object.
1278 1278 """
1279 1279
1280 1280 def __init__(self, ui):
1281 1281 self.ui = ui
1282 1282 self.reply = None
1283 1283 self.captureoutput = False
1284 1284
1285 1285 @property
1286 1286 def repo(self):
1287 1287 raise error.ProgrammingError(b'no repo access from stream interruption')
1288 1288
1289 1289 def gettransaction(self):
1290 1290 raise TransactionUnavailable(b'no repo access from stream interruption')
1291 1291
1292 1292
1293 1293 def decodepayloadchunks(ui, fh):
1294 1294 """Reads bundle2 part payload data into chunks.
1295 1295
1296 1296 Part payload data consists of framed chunks. This function takes
1297 1297 a file handle and emits those chunks.
1298 1298 """
1299 1299 dolog = ui.configbool(b'devel', b'bundle2.debug')
1300 1300 debug = ui.debug
1301 1301
1302 1302 headerstruct = struct.Struct(_fpayloadsize)
1303 1303 headersize = headerstruct.size
1304 1304 unpack = headerstruct.unpack
1305 1305
1306 1306 readexactly = changegroup.readexactly
1307 1307 read = fh.read
1308 1308
1309 1309 chunksize = unpack(readexactly(fh, headersize))[0]
1310 1310 indebug(ui, b'payload chunk size: %i' % chunksize)
1311 1311
1312 1312 # changegroup.readexactly() is inlined below for performance.
1313 1313 while chunksize:
1314 1314 if chunksize >= 0:
1315 1315 s = read(chunksize)
1316 1316 if len(s) < chunksize:
1317 1317 raise error.Abort(
1318 1318 _(
1319 1319 b'stream ended unexpectedly '
1320 1320 b' (got %d bytes, expected %d)'
1321 1321 )
1322 1322 % (len(s), chunksize)
1323 1323 )
1324 1324
1325 1325 yield s
1326 1326 elif chunksize == flaginterrupt:
1327 1327 # Interrupt "signal" detected. The regular stream is interrupted
1328 1328 # and a bundle2 part follows. Consume it.
1329 1329 interrupthandler(ui, fh)()
1330 1330 else:
1331 1331 raise error.BundleValueError(
1332 1332 b'negative payload chunk size: %s' % chunksize
1333 1333 )
1334 1334
1335 1335 s = read(headersize)
1336 1336 if len(s) < headersize:
1337 1337 raise error.Abort(
1338 1338 _(b'stream ended unexpectedly (got %d bytes, expected %d)')
1339 1339 % (len(s), chunksize)
1340 1340 )
1341 1341
1342 1342 chunksize = unpack(s)[0]
1343 1343
1344 1344 # indebug() inlined for performance.
1345 1345 if dolog:
1346 1346 debug(b'bundle2-input: payload chunk size: %i\n' % chunksize)
1347 1347
1348 1348
1349 1349 class unbundlepart(unpackermixin):
1350 1350 """a bundle part read from a bundle"""
1351 1351
1352 1352 def __init__(self, ui, header, fp):
1353 1353 super(unbundlepart, self).__init__(fp)
1354 1354 self._seekable = util.safehasattr(fp, 'seek') and util.safehasattr(
1355 1355 fp, b'tell'
1356 1356 )
1357 1357 self.ui = ui
1358 1358 # unbundle state attr
1359 1359 self._headerdata = header
1360 1360 self._headeroffset = 0
1361 1361 self._initialized = False
1362 1362 self.consumed = False
1363 1363 # part data
1364 1364 self.id = None
1365 1365 self.type = None
1366 1366 self.mandatoryparams = None
1367 1367 self.advisoryparams = None
1368 1368 self.params = None
1369 1369 self.mandatorykeys = ()
1370 1370 self._readheader()
1371 1371 self._mandatory = None
1372 1372 self._pos = 0
1373 1373
1374 1374 def _fromheader(self, size):
1375 1375 """return the next <size> byte from the header"""
1376 1376 offset = self._headeroffset
1377 1377 data = self._headerdata[offset : (offset + size)]
1378 1378 self._headeroffset = offset + size
1379 1379 return data
1380 1380
1381 1381 def _unpackheader(self, format):
1382 1382 """read given format from header
1383 1383
1384 1384 This automatically compute the size of the format to read."""
1385 1385 data = self._fromheader(struct.calcsize(format))
1386 1386 return _unpack(format, data)
1387 1387
1388 1388 def _initparams(self, mandatoryparams, advisoryparams):
1389 1389 """internal function to setup all logic related parameters"""
1390 1390 # make it read only to prevent people touching it by mistake.
1391 1391 self.mandatoryparams = tuple(mandatoryparams)
1392 1392 self.advisoryparams = tuple(advisoryparams)
1393 1393 # user friendly UI
1394 1394 self.params = util.sortdict(self.mandatoryparams)
1395 1395 self.params.update(self.advisoryparams)
1396 1396 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams)
1397 1397
1398 1398 def _readheader(self):
1399 1399 """read the header and setup the object"""
1400 1400 typesize = self._unpackheader(_fparttypesize)[0]
1401 1401 self.type = self._fromheader(typesize)
1402 1402 indebug(self.ui, b'part type: "%s"' % self.type)
1403 1403 self.id = self._unpackheader(_fpartid)[0]
1404 1404 indebug(self.ui, b'part id: "%s"' % pycompat.bytestr(self.id))
1405 1405 # extract mandatory bit from type
1406 1406 self.mandatory = self.type != self.type.lower()
1407 1407 self.type = self.type.lower()
1408 1408 ## reading parameters
1409 1409 # param count
1410 1410 mancount, advcount = self._unpackheader(_fpartparamcount)
1411 1411 indebug(self.ui, b'part parameters: %i' % (mancount + advcount))
1412 1412 # param size
1413 1413 fparamsizes = _makefpartparamsizes(mancount + advcount)
1414 1414 paramsizes = self._unpackheader(fparamsizes)
1415 1415 # make it a list of couple again
1416 1416 paramsizes = list(zip(paramsizes[::2], paramsizes[1::2]))
1417 1417 # split mandatory from advisory
1418 1418 mansizes = paramsizes[:mancount]
1419 1419 advsizes = paramsizes[mancount:]
1420 1420 # retrieve param value
1421 1421 manparams = []
1422 1422 for key, value in mansizes:
1423 1423 manparams.append((self._fromheader(key), self._fromheader(value)))
1424 1424 advparams = []
1425 1425 for key, value in advsizes:
1426 1426 advparams.append((self._fromheader(key), self._fromheader(value)))
1427 1427 self._initparams(manparams, advparams)
1428 1428 ## part payload
1429 1429 self._payloadstream = util.chunkbuffer(self._payloadchunks())
1430 1430 # we read the data, tell it
1431 1431 self._initialized = True
1432 1432
1433 1433 def _payloadchunks(self):
1434 1434 """Generator of decoded chunks in the payload."""
1435 1435 return decodepayloadchunks(self.ui, self._fp)
1436 1436
1437 1437 def consume(self):
1438 1438 """Read the part payload until completion.
1439 1439
1440 1440 By consuming the part data, the underlying stream read offset will
1441 1441 be advanced to the next part (or end of stream).
1442 1442 """
1443 1443 if self.consumed:
1444 1444 return
1445 1445
1446 1446 chunk = self.read(32768)
1447 1447 while chunk:
1448 1448 self._pos += len(chunk)
1449 1449 chunk = self.read(32768)
1450 1450
1451 1451 def read(self, size=None):
1452 1452 """read payload data"""
1453 1453 if not self._initialized:
1454 1454 self._readheader()
1455 1455 if size is None:
1456 1456 data = self._payloadstream.read()
1457 1457 else:
1458 1458 data = self._payloadstream.read(size)
1459 1459 self._pos += len(data)
1460 1460 if size is None or len(data) < size:
1461 1461 if not self.consumed and self._pos:
1462 1462 self.ui.debug(
1463 1463 b'bundle2-input-part: total payload size %i\n' % self._pos
1464 1464 )
1465 1465 self.consumed = True
1466 1466 return data
1467 1467
1468 1468
1469 1469 class seekableunbundlepart(unbundlepart):
1470 1470 """A bundle2 part in a bundle that is seekable.
1471 1471
1472 1472 Regular ``unbundlepart`` instances can only be read once. This class
1473 1473 extends ``unbundlepart`` to enable bi-directional seeking within the
1474 1474 part.
1475 1475
1476 1476 Bundle2 part data consists of framed chunks. Offsets when seeking
1477 1477 refer to the decoded data, not the offsets in the underlying bundle2
1478 1478 stream.
1479 1479
1480 1480 To facilitate quickly seeking within the decoded data, instances of this
1481 1481 class maintain a mapping between offsets in the underlying stream and
1482 1482 the decoded payload. This mapping will consume memory in proportion
1483 1483 to the number of chunks within the payload (which almost certainly
1484 1484 increases in proportion with the size of the part).
1485 1485 """
1486 1486
1487 1487 def __init__(self, ui, header, fp):
1488 1488 # (payload, file) offsets for chunk starts.
1489 1489 self._chunkindex = []
1490 1490
1491 1491 super(seekableunbundlepart, self).__init__(ui, header, fp)
1492 1492
1493 1493 def _payloadchunks(self, chunknum=0):
1494 1494 '''seek to specified chunk and start yielding data'''
1495 1495 if len(self._chunkindex) == 0:
1496 1496 assert chunknum == 0, b'Must start with chunk 0'
1497 1497 self._chunkindex.append((0, self._tellfp()))
1498 1498 else:
1499 1499 assert chunknum < len(self._chunkindex), (
1500 1500 b'Unknown chunk %d' % chunknum
1501 1501 )
1502 1502 self._seekfp(self._chunkindex[chunknum][1])
1503 1503
1504 1504 pos = self._chunkindex[chunknum][0]
1505 1505
1506 1506 for chunk in decodepayloadchunks(self.ui, self._fp):
1507 1507 chunknum += 1
1508 1508 pos += len(chunk)
1509 1509 if chunknum == len(self._chunkindex):
1510 1510 self._chunkindex.append((pos, self._tellfp()))
1511 1511
1512 1512 yield chunk
1513 1513
1514 1514 def _findchunk(self, pos):
1515 1515 '''for a given payload position, return a chunk number and offset'''
1516 1516 for chunk, (ppos, fpos) in enumerate(self._chunkindex):
1517 1517 if ppos == pos:
1518 1518 return chunk, 0
1519 1519 elif ppos > pos:
1520 1520 return chunk - 1, pos - self._chunkindex[chunk - 1][0]
1521 1521 raise ValueError(b'Unknown chunk')
1522 1522
1523 1523 def tell(self):
1524 1524 return self._pos
1525 1525
1526 1526 def seek(self, offset, whence=os.SEEK_SET):
1527 1527 if whence == os.SEEK_SET:
1528 1528 newpos = offset
1529 1529 elif whence == os.SEEK_CUR:
1530 1530 newpos = self._pos + offset
1531 1531 elif whence == os.SEEK_END:
1532 1532 if not self.consumed:
1533 1533 # Can't use self.consume() here because it advances self._pos.
1534 1534 chunk = self.read(32768)
1535 1535 while chunk:
1536 1536 chunk = self.read(32768)
1537 1537 newpos = self._chunkindex[-1][0] - offset
1538 1538 else:
1539 1539 raise ValueError(b'Unknown whence value: %r' % (whence,))
1540 1540
1541 1541 if newpos > self._chunkindex[-1][0] and not self.consumed:
1542 1542 # Can't use self.consume() here because it advances self._pos.
1543 1543 chunk = self.read(32768)
1544 1544 while chunk:
1545 1545 chunk = self.read(32668)
1546 1546
1547 1547 if not 0 <= newpos <= self._chunkindex[-1][0]:
1548 1548 raise ValueError(b'Offset out of range')
1549 1549
1550 1550 if self._pos != newpos:
1551 1551 chunk, internaloffset = self._findchunk(newpos)
1552 1552 self._payloadstream = util.chunkbuffer(self._payloadchunks(chunk))
1553 1553 adjust = self.read(internaloffset)
1554 1554 if len(adjust) != internaloffset:
1555 1555 raise error.Abort(_(b'Seek failed\n'))
1556 1556 self._pos = newpos
1557 1557
1558 1558 def _seekfp(self, offset, whence=0):
1559 1559 """move the underlying file pointer
1560 1560
1561 1561 This method is meant for internal usage by the bundle2 protocol only.
1562 1562 They directly manipulate the low level stream including bundle2 level
1563 1563 instruction.
1564 1564
1565 1565 Do not use it to implement higher-level logic or methods."""
1566 1566 if self._seekable:
1567 1567 return self._fp.seek(offset, whence)
1568 1568 else:
1569 1569 raise NotImplementedError(_(b'File pointer is not seekable'))
1570 1570
1571 1571 def _tellfp(self):
1572 1572 """return the file offset, or None if file is not seekable
1573 1573
1574 1574 This method is meant for internal usage by the bundle2 protocol only.
1575 1575 They directly manipulate the low level stream including bundle2 level
1576 1576 instruction.
1577 1577
1578 1578 Do not use it to implement higher-level logic or methods."""
1579 1579 if self._seekable:
1580 1580 try:
1581 1581 return self._fp.tell()
1582 1582 except IOError as e:
1583 1583 if e.errno == errno.ESPIPE:
1584 1584 self._seekable = False
1585 1585 else:
1586 1586 raise
1587 1587 return None
1588 1588
1589 1589
1590 1590 # These are only the static capabilities.
1591 1591 # Check the 'getrepocaps' function for the rest.
1592 1592 capabilities = {
1593 1593 b'HG20': (),
1594 1594 b'bookmarks': (),
1595 1595 b'error': (b'abort', b'unsupportedcontent', b'pushraced', b'pushkey'),
1596 1596 b'listkeys': (),
1597 1597 b'pushkey': (),
1598 1598 b'digests': tuple(sorted(util.DIGESTS.keys())),
1599 1599 b'remote-changegroup': (b'http', b'https'),
1600 1600 b'hgtagsfnodes': (),
1601 b'rev-branch-cache': (),
1602 1601 b'phases': (b'heads',),
1603 1602 b'stream': (b'v2',),
1604 1603 }
1605 1604
1606 1605
1607 1606 def getrepocaps(repo, allowpushback=False, role=None):
1608 1607 """return the bundle2 capabilities for a given repo
1609 1608
1610 1609 Exists to allow extensions (like evolution) to mutate the capabilities.
1611 1610
1612 1611 The returned value is used for servers advertising their capabilities as
1613 1612 well as clients advertising their capabilities to servers as part of
1614 1613 bundle2 requests. The ``role`` argument specifies which is which.
1615 1614 """
1616 1615 if role not in (b'client', b'server'):
1617 1616 raise error.ProgrammingError(b'role argument must be client or server')
1618 1617
1619 1618 caps = capabilities.copy()
1620 1619 caps[b'changegroup'] = tuple(
1621 1620 sorted(changegroup.supportedincomingversions(repo))
1622 1621 )
1623 1622 if obsolete.isenabled(repo, obsolete.exchangeopt):
1624 1623 supportedformat = tuple(b'V%i' % v for v in obsolete.formats)
1625 1624 caps[b'obsmarkers'] = supportedformat
1626 1625 if allowpushback:
1627 1626 caps[b'pushback'] = ()
1628 1627 cpmode = repo.ui.config(b'server', b'concurrent-push-mode')
1629 1628 if cpmode == b'check-related':
1630 1629 caps[b'checkheads'] = (b'related',)
1631 1630 if b'phases' in repo.ui.configlist(b'devel', b'legacy.exchange'):
1632 1631 caps.pop(b'phases')
1633 1632
1634 1633 # Don't advertise stream clone support in server mode if not configured.
1635 1634 if role == b'server':
1636 1635 streamsupported = repo.ui.configbool(
1637 1636 b'server', b'uncompressed', untrusted=True
1638 1637 )
1639 1638 featuresupported = repo.ui.configbool(b'server', b'bundle2.stream')
1640 1639
1641 1640 if not streamsupported or not featuresupported:
1642 1641 caps.pop(b'stream')
1643 1642 # Else always advertise support on client, because payload support
1644 1643 # should always be advertised.
1645 1644
1645 # b'rev-branch-cache is no longer advertised, but still supported
1646 # for legacy clients.
1647
1646 1648 return caps
1647 1649
1648 1650
1649 1651 def bundle2caps(remote):
1650 1652 """return the bundle capabilities of a peer as dict"""
1651 1653 raw = remote.capable(b'bundle2')
1652 1654 if not raw and raw != b'':
1653 1655 return {}
1654 1656 capsblob = urlreq.unquote(remote.capable(b'bundle2'))
1655 1657 return decodecaps(capsblob)
1656 1658
1657 1659
1658 1660 def obsmarkersversion(caps):
1659 1661 """extract the list of supported obsmarkers versions from a bundle2caps dict"""
1660 1662 obscaps = caps.get(b'obsmarkers', ())
1661 1663 return [int(c[1:]) for c in obscaps if c.startswith(b'V')]
1662 1664
1663 1665
1664 1666 def writenewbundle(
1665 1667 ui,
1666 1668 repo,
1667 1669 source,
1668 1670 filename,
1669 1671 bundletype,
1670 1672 outgoing,
1671 1673 opts,
1672 1674 vfs=None,
1673 1675 compression=None,
1674 1676 compopts=None,
1675 1677 ):
1676 1678 if bundletype.startswith(b'HG10'):
1677 1679 cg = changegroup.makechangegroup(repo, outgoing, b'01', source)
1678 1680 return writebundle(
1679 1681 ui,
1680 1682 cg,
1681 1683 filename,
1682 1684 bundletype,
1683 1685 vfs=vfs,
1684 1686 compression=compression,
1685 1687 compopts=compopts,
1686 1688 )
1687 1689 elif not bundletype.startswith(b'HG20'):
1688 1690 raise error.ProgrammingError(b'unknown bundle type: %s' % bundletype)
1689 1691
1690 1692 caps = {}
1691 1693 if b'obsolescence' in opts:
1692 1694 caps[b'obsmarkers'] = (b'V1',)
1693 1695 bundle = bundle20(ui, caps)
1694 1696 bundle.setcompression(compression, compopts)
1695 1697 _addpartsfromopts(ui, repo, bundle, source, outgoing, opts)
1696 1698 chunkiter = bundle.getchunks()
1697 1699
1698 1700 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1699 1701
1700 1702
1701 1703 def _addpartsfromopts(ui, repo, bundler, source, outgoing, opts):
1702 1704 # We should eventually reconcile this logic with the one behind
1703 1705 # 'exchange.getbundle2partsgenerator'.
1704 1706 #
1705 1707 # The type of input from 'getbundle' and 'writenewbundle' are a bit
1706 1708 # different right now. So we keep them separated for now for the sake of
1707 1709 # simplicity.
1708 1710
1709 1711 # we might not always want a changegroup in such bundle, for example in
1710 1712 # stream bundles
1711 1713 if opts.get(b'changegroup', True):
1712 1714 cgversion = opts.get(b'cg.version')
1713 1715 if cgversion is None:
1714 1716 cgversion = changegroup.safeversion(repo)
1715 1717 cg = changegroup.makechangegroup(repo, outgoing, cgversion, source)
1716 1718 part = bundler.newpart(b'changegroup', data=cg.getchunks())
1717 1719 part.addparam(b'version', cg.version)
1718 1720 if b'clcount' in cg.extras:
1719 1721 part.addparam(
1720 1722 b'nbchanges', b'%d' % cg.extras[b'clcount'], mandatory=False
1721 1723 )
1722 1724 if opts.get(b'phases') and repo.revs(
1723 1725 b'%ln and secret()', outgoing.ancestorsof
1724 1726 ):
1725 1727 part.addparam(
1726 1728 b'targetphase', b'%d' % phases.secret, mandatory=False
1727 1729 )
1728 1730 if b'exp-sidedata-flag' in repo.requirements:
1729 1731 part.addparam(b'exp-sidedata', b'1')
1730 1732
1731 1733 if opts.get(b'streamv2', False):
1732 1734 addpartbundlestream2(bundler, repo, stream=True)
1733 1735
1734 1736 if opts.get(b'tagsfnodescache', True):
1735 1737 addparttagsfnodescache(repo, bundler, outgoing)
1736 1738
1737 1739 if opts.get(b'revbranchcache', True):
1738 1740 addpartrevbranchcache(repo, bundler, outgoing)
1739 1741
1740 1742 if opts.get(b'obsolescence', False):
1741 1743 obsmarkers = repo.obsstore.relevantmarkers(outgoing.missing)
1742 1744 buildobsmarkerspart(
1743 1745 bundler,
1744 1746 obsmarkers,
1745 1747 mandatory=opts.get(b'obsolescence-mandatory', True),
1746 1748 )
1747 1749
1748 1750 if opts.get(b'phases', False):
1749 1751 headsbyphase = phases.subsetphaseheads(repo, outgoing.missing)
1750 1752 phasedata = phases.binaryencode(headsbyphase)
1751 1753 bundler.newpart(b'phase-heads', data=phasedata)
1752 1754
1753 1755
1754 1756 def addparttagsfnodescache(repo, bundler, outgoing):
1755 1757 # we include the tags fnode cache for the bundle changeset
1756 1758 # (as an optional parts)
1757 1759 cache = tags.hgtagsfnodescache(repo.unfiltered())
1758 1760 chunks = []
1759 1761
1760 1762 # .hgtags fnodes are only relevant for head changesets. While we could
1761 1763 # transfer values for all known nodes, there will likely be little to
1762 1764 # no benefit.
1763 1765 #
1764 1766 # We don't bother using a generator to produce output data because
1765 1767 # a) we only have 40 bytes per head and even esoteric numbers of heads
1766 1768 # consume little memory (1M heads is 40MB) b) we don't want to send the
1767 1769 # part if we don't have entries and knowing if we have entries requires
1768 1770 # cache lookups.
1769 1771 for node in outgoing.ancestorsof:
1770 1772 # Don't compute missing, as this may slow down serving.
1771 1773 fnode = cache.getfnode(node, computemissing=False)
1772 1774 if fnode:
1773 1775 chunks.extend([node, fnode])
1774 1776
1775 1777 if chunks:
1776 1778 bundler.newpart(b'hgtagsfnodes', data=b''.join(chunks))
1777 1779
1778 1780
1779 1781 def addpartrevbranchcache(repo, bundler, outgoing):
1780 1782 # we include the rev branch cache for the bundle changeset
1781 1783 # (as an optional parts)
1782 1784 cache = repo.revbranchcache()
1783 1785 cl = repo.unfiltered().changelog
1784 1786 branchesdata = collections.defaultdict(lambda: (set(), set()))
1785 1787 for node in outgoing.missing:
1786 1788 branch, close = cache.branchinfo(cl.rev(node))
1787 1789 branchesdata[branch][close].add(node)
1788 1790
1789 1791 def generate():
1790 1792 for branch, (nodes, closed) in sorted(branchesdata.items()):
1791 1793 utf8branch = encoding.fromlocal(branch)
1792 1794 yield rbcstruct.pack(len(utf8branch), len(nodes), len(closed))
1793 1795 yield utf8branch
1794 1796 for n in sorted(nodes):
1795 1797 yield n
1796 1798 for n in sorted(closed):
1797 1799 yield n
1798 1800
1799 1801 bundler.newpart(b'cache:rev-branch-cache', data=generate(), mandatory=False)
1800 1802
1801 1803
1802 1804 def _formatrequirementsspec(requirements):
1803 1805 requirements = [req for req in requirements if req != b"shared"]
1804 1806 return urlreq.quote(b','.join(sorted(requirements)))
1805 1807
1806 1808
1807 1809 def _formatrequirementsparams(requirements):
1808 1810 requirements = _formatrequirementsspec(requirements)
1809 1811 params = b"%s%s" % (urlreq.quote(b"requirements="), requirements)
1810 1812 return params
1811 1813
1812 1814
1813 1815 def addpartbundlestream2(bundler, repo, **kwargs):
1814 1816 if not kwargs.get('stream', False):
1815 1817 return
1816 1818
1817 1819 if not streamclone.allowservergeneration(repo):
1818 1820 raise error.Abort(
1819 1821 _(
1820 1822 b'stream data requested but server does not allow '
1821 1823 b'this feature'
1822 1824 ),
1823 1825 hint=_(
1824 1826 b'well-behaved clients should not be '
1825 1827 b'requesting stream data from servers not '
1826 1828 b'advertising it; the client may be buggy'
1827 1829 ),
1828 1830 )
1829 1831
1830 1832 # Stream clones don't compress well. And compression undermines a
1831 1833 # goal of stream clones, which is to be fast. Communicate the desire
1832 1834 # to avoid compression to consumers of the bundle.
1833 1835 bundler.prefercompressed = False
1834 1836
1835 1837 # get the includes and excludes
1836 1838 includepats = kwargs.get('includepats')
1837 1839 excludepats = kwargs.get('excludepats')
1838 1840
1839 1841 narrowstream = repo.ui.configbool(
1840 1842 b'experimental', b'server.stream-narrow-clones'
1841 1843 )
1842 1844
1843 1845 if (includepats or excludepats) and not narrowstream:
1844 1846 raise error.Abort(_(b'server does not support narrow stream clones'))
1845 1847
1846 1848 includeobsmarkers = False
1847 1849 if repo.obsstore:
1848 1850 remoteversions = obsmarkersversion(bundler.capabilities)
1849 1851 if not remoteversions:
1850 1852 raise error.Abort(
1851 1853 _(
1852 1854 b'server has obsolescence markers, but client '
1853 1855 b'cannot receive them via stream clone'
1854 1856 )
1855 1857 )
1856 1858 elif repo.obsstore._version in remoteversions:
1857 1859 includeobsmarkers = True
1858 1860
1859 1861 filecount, bytecount, it = streamclone.generatev2(
1860 1862 repo, includepats, excludepats, includeobsmarkers
1861 1863 )
1862 1864 requirements = _formatrequirementsspec(repo.requirements)
1863 1865 part = bundler.newpart(b'stream2', data=it)
1864 1866 part.addparam(b'bytecount', b'%d' % bytecount, mandatory=True)
1865 1867 part.addparam(b'filecount', b'%d' % filecount, mandatory=True)
1866 1868 part.addparam(b'requirements', requirements, mandatory=True)
1867 1869
1868 1870
1869 1871 def buildobsmarkerspart(bundler, markers, mandatory=True):
1870 1872 """add an obsmarker part to the bundler with <markers>
1871 1873
1872 1874 No part is created if markers is empty.
1873 1875 Raises ValueError if the bundler doesn't support any known obsmarker format.
1874 1876 """
1875 1877 if not markers:
1876 1878 return None
1877 1879
1878 1880 remoteversions = obsmarkersversion(bundler.capabilities)
1879 1881 version = obsolete.commonversion(remoteversions)
1880 1882 if version is None:
1881 1883 raise ValueError(b'bundler does not support common obsmarker format')
1882 1884 stream = obsolete.encodemarkers(markers, True, version=version)
1883 1885 return bundler.newpart(b'obsmarkers', data=stream, mandatory=mandatory)
1884 1886
1885 1887
1886 1888 def writebundle(
1887 1889 ui, cg, filename, bundletype, vfs=None, compression=None, compopts=None
1888 1890 ):
1889 1891 """Write a bundle file and return its filename.
1890 1892
1891 1893 Existing files will not be overwritten.
1892 1894 If no filename is specified, a temporary file is created.
1893 1895 bz2 compression can be turned off.
1894 1896 The bundle file will be deleted in case of errors.
1895 1897 """
1896 1898
1897 1899 if bundletype == b"HG20":
1898 1900 bundle = bundle20(ui)
1899 1901 bundle.setcompression(compression, compopts)
1900 1902 part = bundle.newpart(b'changegroup', data=cg.getchunks())
1901 1903 part.addparam(b'version', cg.version)
1902 1904 if b'clcount' in cg.extras:
1903 1905 part.addparam(
1904 1906 b'nbchanges', b'%d' % cg.extras[b'clcount'], mandatory=False
1905 1907 )
1906 1908 chunkiter = bundle.getchunks()
1907 1909 else:
1908 1910 # compression argument is only for the bundle2 case
1909 1911 assert compression is None
1910 1912 if cg.version != b'01':
1911 1913 raise error.Abort(
1912 1914 _(b'old bundle types only supports v1 changegroups')
1913 1915 )
1914 1916 header, comp = bundletypes[bundletype]
1915 1917 if comp not in util.compengines.supportedbundletypes:
1916 1918 raise error.Abort(_(b'unknown stream compression type: %s') % comp)
1917 1919 compengine = util.compengines.forbundletype(comp)
1918 1920
1919 1921 def chunkiter():
1920 1922 yield header
1921 1923 for chunk in compengine.compressstream(cg.getchunks(), compopts):
1922 1924 yield chunk
1923 1925
1924 1926 chunkiter = chunkiter()
1925 1927
1926 1928 # parse the changegroup data, otherwise we will block
1927 1929 # in case of sshrepo because we don't know the end of the stream
1928 1930 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1929 1931
1930 1932
1931 1933 def combinechangegroupresults(op):
1932 1934 """logic to combine 0 or more addchangegroup results into one"""
1933 1935 results = [r.get(b'return', 0) for r in op.records[b'changegroup']]
1934 1936 changedheads = 0
1935 1937 result = 1
1936 1938 for ret in results:
1937 1939 # If any changegroup result is 0, return 0
1938 1940 if ret == 0:
1939 1941 result = 0
1940 1942 break
1941 1943 if ret < -1:
1942 1944 changedheads += ret + 1
1943 1945 elif ret > 1:
1944 1946 changedheads += ret - 1
1945 1947 if changedheads > 0:
1946 1948 result = 1 + changedheads
1947 1949 elif changedheads < 0:
1948 1950 result = -1 + changedheads
1949 1951 return result
1950 1952
1951 1953
1952 1954 @parthandler(
1953 1955 b'changegroup',
1954 1956 (
1955 1957 b'version',
1956 1958 b'nbchanges',
1957 1959 b'exp-sidedata',
1958 1960 b'treemanifest',
1959 1961 b'targetphase',
1960 1962 ),
1961 1963 )
1962 1964 def handlechangegroup(op, inpart):
1963 1965 """apply a changegroup part on the repo"""
1964 1966 from . import localrepo
1965 1967
1966 1968 tr = op.gettransaction()
1967 1969 unpackerversion = inpart.params.get(b'version', b'01')
1968 1970 # We should raise an appropriate exception here
1969 1971 cg = changegroup.getunbundler(unpackerversion, inpart, None)
1970 1972 # the source and url passed here are overwritten by the one contained in
1971 1973 # the transaction.hookargs argument. So 'bundle2' is a placeholder
1972 1974 nbchangesets = None
1973 1975 if b'nbchanges' in inpart.params:
1974 1976 nbchangesets = int(inpart.params.get(b'nbchanges'))
1975 1977 if b'treemanifest' in inpart.params and not scmutil.istreemanifest(op.repo):
1976 1978 if len(op.repo.changelog) != 0:
1977 1979 raise error.Abort(
1978 1980 _(
1979 1981 b"bundle contains tree manifests, but local repo is "
1980 1982 b"non-empty and does not use tree manifests"
1981 1983 )
1982 1984 )
1983 1985 op.repo.requirements.add(requirements.TREEMANIFEST_REQUIREMENT)
1984 1986 op.repo.svfs.options = localrepo.resolvestorevfsoptions(
1985 1987 op.repo.ui, op.repo.requirements, op.repo.features
1986 1988 )
1987 1989 scmutil.writereporequirements(op.repo)
1988 1990
1989 1991 bundlesidedata = bool(b'exp-sidedata' in inpart.params)
1990 1992 reposidedata = bool(b'exp-sidedata-flag' in op.repo.requirements)
1991 1993 if reposidedata and not bundlesidedata:
1992 1994 msg = b"repository is using sidedata but the bundle source do not"
1993 1995 hint = b'this is currently unsupported'
1994 1996 raise error.Abort(msg, hint=hint)
1995 1997
1996 1998 extrakwargs = {}
1997 1999 targetphase = inpart.params.get(b'targetphase')
1998 2000 if targetphase is not None:
1999 2001 extrakwargs['targetphase'] = int(targetphase)
2000 2002 ret = _processchangegroup(
2001 2003 op,
2002 2004 cg,
2003 2005 tr,
2004 2006 op.source,
2005 2007 b'bundle2',
2006 2008 expectedtotal=nbchangesets,
2007 2009 **extrakwargs
2008 2010 )
2009 2011 if op.reply is not None:
2010 2012 # This is definitely not the final form of this
2011 2013 # return. But one need to start somewhere.
2012 2014 part = op.reply.newpart(b'reply:changegroup', mandatory=False)
2013 2015 part.addparam(
2014 2016 b'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False
2015 2017 )
2016 2018 part.addparam(b'return', b'%i' % ret, mandatory=False)
2017 2019 assert not inpart.read()
2018 2020
2019 2021
2020 2022 _remotechangegroupparams = tuple(
2021 2023 [b'url', b'size', b'digests']
2022 2024 + [b'digest:%s' % k for k in util.DIGESTS.keys()]
2023 2025 )
2024 2026
2025 2027
2026 2028 @parthandler(b'remote-changegroup', _remotechangegroupparams)
2027 2029 def handleremotechangegroup(op, inpart):
2028 2030 """apply a bundle10 on the repo, given an url and validation information
2029 2031
2030 2032 All the information about the remote bundle to import are given as
2031 2033 parameters. The parameters include:
2032 2034 - url: the url to the bundle10.
2033 2035 - size: the bundle10 file size. It is used to validate what was
2034 2036 retrieved by the client matches the server knowledge about the bundle.
2035 2037 - digests: a space separated list of the digest types provided as
2036 2038 parameters.
2037 2039 - digest:<digest-type>: the hexadecimal representation of the digest with
2038 2040 that name. Like the size, it is used to validate what was retrieved by
2039 2041 the client matches what the server knows about the bundle.
2040 2042
2041 2043 When multiple digest types are given, all of them are checked.
2042 2044 """
2043 2045 try:
2044 2046 raw_url = inpart.params[b'url']
2045 2047 except KeyError:
2046 2048 raise error.Abort(_(b'remote-changegroup: missing "%s" param') % b'url')
2047 2049 parsed_url = util.url(raw_url)
2048 2050 if parsed_url.scheme not in capabilities[b'remote-changegroup']:
2049 2051 raise error.Abort(
2050 2052 _(b'remote-changegroup does not support %s urls')
2051 2053 % parsed_url.scheme
2052 2054 )
2053 2055
2054 2056 try:
2055 2057 size = int(inpart.params[b'size'])
2056 2058 except ValueError:
2057 2059 raise error.Abort(
2058 2060 _(b'remote-changegroup: invalid value for param "%s"') % b'size'
2059 2061 )
2060 2062 except KeyError:
2061 2063 raise error.Abort(
2062 2064 _(b'remote-changegroup: missing "%s" param') % b'size'
2063 2065 )
2064 2066
2065 2067 digests = {}
2066 2068 for typ in inpart.params.get(b'digests', b'').split():
2067 2069 param = b'digest:%s' % typ
2068 2070 try:
2069 2071 value = inpart.params[param]
2070 2072 except KeyError:
2071 2073 raise error.Abort(
2072 2074 _(b'remote-changegroup: missing "%s" param') % param
2073 2075 )
2074 2076 digests[typ] = value
2075 2077
2076 2078 real_part = util.digestchecker(url.open(op.ui, raw_url), size, digests)
2077 2079
2078 2080 tr = op.gettransaction()
2079 2081 from . import exchange
2080 2082
2081 2083 cg = exchange.readbundle(op.repo.ui, real_part, raw_url)
2082 2084 if not isinstance(cg, changegroup.cg1unpacker):
2083 2085 raise error.Abort(
2084 2086 _(b'%s: not a bundle version 1.0') % util.hidepassword(raw_url)
2085 2087 )
2086 2088 ret = _processchangegroup(op, cg, tr, op.source, b'bundle2')
2087 2089 if op.reply is not None:
2088 2090 # This is definitely not the final form of this
2089 2091 # return. But one need to start somewhere.
2090 2092 part = op.reply.newpart(b'reply:changegroup')
2091 2093 part.addparam(
2092 2094 b'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False
2093 2095 )
2094 2096 part.addparam(b'return', b'%i' % ret, mandatory=False)
2095 2097 try:
2096 2098 real_part.validate()
2097 2099 except error.Abort as e:
2098 2100 raise error.Abort(
2099 2101 _(b'bundle at %s is corrupted:\n%s')
2100 2102 % (util.hidepassword(raw_url), e.message)
2101 2103 )
2102 2104 assert not inpart.read()
2103 2105
2104 2106
2105 2107 @parthandler(b'reply:changegroup', (b'return', b'in-reply-to'))
2106 2108 def handlereplychangegroup(op, inpart):
2107 2109 ret = int(inpart.params[b'return'])
2108 2110 replyto = int(inpart.params[b'in-reply-to'])
2109 2111 op.records.add(b'changegroup', {b'return': ret}, replyto)
2110 2112
2111 2113
2112 2114 @parthandler(b'check:bookmarks')
2113 2115 def handlecheckbookmarks(op, inpart):
2114 2116 """check location of bookmarks
2115 2117
2116 2118 This part is to be used to detect push race regarding bookmark, it
2117 2119 contains binary encoded (bookmark, node) tuple. If the local state does
2118 2120 not marks the one in the part, a PushRaced exception is raised
2119 2121 """
2120 2122 bookdata = bookmarks.binarydecode(inpart)
2121 2123
2122 2124 msgstandard = (
2123 2125 b'remote repository changed while pushing - please try again '
2124 2126 b'(bookmark "%s" move from %s to %s)'
2125 2127 )
2126 2128 msgmissing = (
2127 2129 b'remote repository changed while pushing - please try again '
2128 2130 b'(bookmark "%s" is missing, expected %s)'
2129 2131 )
2130 2132 msgexist = (
2131 2133 b'remote repository changed while pushing - please try again '
2132 2134 b'(bookmark "%s" set on %s, expected missing)'
2133 2135 )
2134 2136 for book, node in bookdata:
2135 2137 currentnode = op.repo._bookmarks.get(book)
2136 2138 if currentnode != node:
2137 2139 if node is None:
2138 2140 finalmsg = msgexist % (book, short(currentnode))
2139 2141 elif currentnode is None:
2140 2142 finalmsg = msgmissing % (book, short(node))
2141 2143 else:
2142 2144 finalmsg = msgstandard % (
2143 2145 book,
2144 2146 short(node),
2145 2147 short(currentnode),
2146 2148 )
2147 2149 raise error.PushRaced(finalmsg)
2148 2150
2149 2151
2150 2152 @parthandler(b'check:heads')
2151 2153 def handlecheckheads(op, inpart):
2152 2154 """check that head of the repo did not change
2153 2155
2154 2156 This is used to detect a push race when using unbundle.
2155 2157 This replaces the "heads" argument of unbundle."""
2156 2158 h = inpart.read(20)
2157 2159 heads = []
2158 2160 while len(h) == 20:
2159 2161 heads.append(h)
2160 2162 h = inpart.read(20)
2161 2163 assert not h
2162 2164 # Trigger a transaction so that we are guaranteed to have the lock now.
2163 2165 if op.ui.configbool(b'experimental', b'bundle2lazylocking'):
2164 2166 op.gettransaction()
2165 2167 if sorted(heads) != sorted(op.repo.heads()):
2166 2168 raise error.PushRaced(
2167 2169 b'remote repository changed while pushing - please try again'
2168 2170 )
2169 2171
2170 2172
2171 2173 @parthandler(b'check:updated-heads')
2172 2174 def handlecheckupdatedheads(op, inpart):
2173 2175 """check for race on the heads touched by a push
2174 2176
2175 2177 This is similar to 'check:heads' but focus on the heads actually updated
2176 2178 during the push. If other activities happen on unrelated heads, it is
2177 2179 ignored.
2178 2180
2179 2181 This allow server with high traffic to avoid push contention as long as
2180 2182 unrelated parts of the graph are involved."""
2181 2183 h = inpart.read(20)
2182 2184 heads = []
2183 2185 while len(h) == 20:
2184 2186 heads.append(h)
2185 2187 h = inpart.read(20)
2186 2188 assert not h
2187 2189 # trigger a transaction so that we are guaranteed to have the lock now.
2188 2190 if op.ui.configbool(b'experimental', b'bundle2lazylocking'):
2189 2191 op.gettransaction()
2190 2192
2191 2193 currentheads = set()
2192 2194 for ls in op.repo.branchmap().iterheads():
2193 2195 currentheads.update(ls)
2194 2196
2195 2197 for h in heads:
2196 2198 if h not in currentheads:
2197 2199 raise error.PushRaced(
2198 2200 b'remote repository changed while pushing - '
2199 2201 b'please try again'
2200 2202 )
2201 2203
2202 2204
2203 2205 @parthandler(b'check:phases')
2204 2206 def handlecheckphases(op, inpart):
2205 2207 """check that phase boundaries of the repository did not change
2206 2208
2207 2209 This is used to detect a push race.
2208 2210 """
2209 2211 phasetonodes = phases.binarydecode(inpart)
2210 2212 unfi = op.repo.unfiltered()
2211 2213 cl = unfi.changelog
2212 2214 phasecache = unfi._phasecache
2213 2215 msg = (
2214 2216 b'remote repository changed while pushing - please try again '
2215 2217 b'(%s is %s expected %s)'
2216 2218 )
2217 2219 for expectedphase, nodes in pycompat.iteritems(phasetonodes):
2218 2220 for n in nodes:
2219 2221 actualphase = phasecache.phase(unfi, cl.rev(n))
2220 2222 if actualphase != expectedphase:
2221 2223 finalmsg = msg % (
2222 2224 short(n),
2223 2225 phases.phasenames[actualphase],
2224 2226 phases.phasenames[expectedphase],
2225 2227 )
2226 2228 raise error.PushRaced(finalmsg)
2227 2229
2228 2230
2229 2231 @parthandler(b'output')
2230 2232 def handleoutput(op, inpart):
2231 2233 """forward output captured on the server to the client"""
2232 2234 for line in inpart.read().splitlines():
2233 2235 op.ui.status(_(b'remote: %s\n') % line)
2234 2236
2235 2237
2236 2238 @parthandler(b'replycaps')
2237 2239 def handlereplycaps(op, inpart):
2238 2240 """Notify that a reply bundle should be created
2239 2241
2240 2242 The payload contains the capabilities information for the reply"""
2241 2243 caps = decodecaps(inpart.read())
2242 2244 if op.reply is None:
2243 2245 op.reply = bundle20(op.ui, caps)
2244 2246
2245 2247
2246 2248 class AbortFromPart(error.Abort):
2247 2249 """Sub-class of Abort that denotes an error from a bundle2 part."""
2248 2250
2249 2251
2250 2252 @parthandler(b'error:abort', (b'message', b'hint'))
2251 2253 def handleerrorabort(op, inpart):
2252 2254 """Used to transmit abort error over the wire"""
2253 2255 raise AbortFromPart(
2254 2256 inpart.params[b'message'], hint=inpart.params.get(b'hint')
2255 2257 )
2256 2258
2257 2259
2258 2260 @parthandler(
2259 2261 b'error:pushkey',
2260 2262 (b'namespace', b'key', b'new', b'old', b'ret', b'in-reply-to'),
2261 2263 )
2262 2264 def handleerrorpushkey(op, inpart):
2263 2265 """Used to transmit failure of a mandatory pushkey over the wire"""
2264 2266 kwargs = {}
2265 2267 for name in (b'namespace', b'key', b'new', b'old', b'ret'):
2266 2268 value = inpart.params.get(name)
2267 2269 if value is not None:
2268 2270 kwargs[name] = value
2269 2271 raise error.PushkeyFailed(
2270 2272 inpart.params[b'in-reply-to'], **pycompat.strkwargs(kwargs)
2271 2273 )
2272 2274
2273 2275
2274 2276 @parthandler(b'error:unsupportedcontent', (b'parttype', b'params'))
2275 2277 def handleerrorunsupportedcontent(op, inpart):
2276 2278 """Used to transmit unknown content error over the wire"""
2277 2279 kwargs = {}
2278 2280 parttype = inpart.params.get(b'parttype')
2279 2281 if parttype is not None:
2280 2282 kwargs[b'parttype'] = parttype
2281 2283 params = inpart.params.get(b'params')
2282 2284 if params is not None:
2283 2285 kwargs[b'params'] = params.split(b'\0')
2284 2286
2285 2287 raise error.BundleUnknownFeatureError(**pycompat.strkwargs(kwargs))
2286 2288
2287 2289
2288 2290 @parthandler(b'error:pushraced', (b'message',))
2289 2291 def handleerrorpushraced(op, inpart):
2290 2292 """Used to transmit push race error over the wire"""
2291 2293 raise error.ResponseError(_(b'push failed:'), inpart.params[b'message'])
2292 2294
2293 2295
2294 2296 @parthandler(b'listkeys', (b'namespace',))
2295 2297 def handlelistkeys(op, inpart):
2296 2298 """retrieve pushkey namespace content stored in a bundle2"""
2297 2299 namespace = inpart.params[b'namespace']
2298 2300 r = pushkey.decodekeys(inpart.read())
2299 2301 op.records.add(b'listkeys', (namespace, r))
2300 2302
2301 2303
2302 2304 @parthandler(b'pushkey', (b'namespace', b'key', b'old', b'new'))
2303 2305 def handlepushkey(op, inpart):
2304 2306 """process a pushkey request"""
2305 2307 dec = pushkey.decode
2306 2308 namespace = dec(inpart.params[b'namespace'])
2307 2309 key = dec(inpart.params[b'key'])
2308 2310 old = dec(inpart.params[b'old'])
2309 2311 new = dec(inpart.params[b'new'])
2310 2312 # Grab the transaction to ensure that we have the lock before performing the
2311 2313 # pushkey.
2312 2314 if op.ui.configbool(b'experimental', b'bundle2lazylocking'):
2313 2315 op.gettransaction()
2314 2316 ret = op.repo.pushkey(namespace, key, old, new)
2315 2317 record = {b'namespace': namespace, b'key': key, b'old': old, b'new': new}
2316 2318 op.records.add(b'pushkey', record)
2317 2319 if op.reply is not None:
2318 2320 rpart = op.reply.newpart(b'reply:pushkey')
2319 2321 rpart.addparam(
2320 2322 b'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False
2321 2323 )
2322 2324 rpart.addparam(b'return', b'%i' % ret, mandatory=False)
2323 2325 if inpart.mandatory and not ret:
2324 2326 kwargs = {}
2325 2327 for key in (b'namespace', b'key', b'new', b'old', b'ret'):
2326 2328 if key in inpart.params:
2327 2329 kwargs[key] = inpart.params[key]
2328 2330 raise error.PushkeyFailed(
2329 2331 partid=b'%d' % inpart.id, **pycompat.strkwargs(kwargs)
2330 2332 )
2331 2333
2332 2334
2333 2335 @parthandler(b'bookmarks')
2334 2336 def handlebookmark(op, inpart):
2335 2337 """transmit bookmark information
2336 2338
2337 2339 The part contains binary encoded bookmark information.
2338 2340
2339 2341 The exact behavior of this part can be controlled by the 'bookmarks' mode
2340 2342 on the bundle operation.
2341 2343
2342 2344 When mode is 'apply' (the default) the bookmark information is applied as
2343 2345 is to the unbundling repository. Make sure a 'check:bookmarks' part is
2344 2346 issued earlier to check for push races in such update. This behavior is
2345 2347 suitable for pushing.
2346 2348
2347 2349 When mode is 'records', the information is recorded into the 'bookmarks'
2348 2350 records of the bundle operation. This behavior is suitable for pulling.
2349 2351 """
2350 2352 changes = bookmarks.binarydecode(inpart)
2351 2353
2352 2354 pushkeycompat = op.repo.ui.configbool(
2353 2355 b'server', b'bookmarks-pushkey-compat'
2354 2356 )
2355 2357 bookmarksmode = op.modes.get(b'bookmarks', b'apply')
2356 2358
2357 2359 if bookmarksmode == b'apply':
2358 2360 tr = op.gettransaction()
2359 2361 bookstore = op.repo._bookmarks
2360 2362 if pushkeycompat:
2361 2363 allhooks = []
2362 2364 for book, node in changes:
2363 2365 hookargs = tr.hookargs.copy()
2364 2366 hookargs[b'pushkeycompat'] = b'1'
2365 2367 hookargs[b'namespace'] = b'bookmarks'
2366 2368 hookargs[b'key'] = book
2367 2369 hookargs[b'old'] = hex(bookstore.get(book, b''))
2368 2370 hookargs[b'new'] = hex(node if node is not None else b'')
2369 2371 allhooks.append(hookargs)
2370 2372
2371 2373 for hookargs in allhooks:
2372 2374 op.repo.hook(
2373 2375 b'prepushkey', throw=True, **pycompat.strkwargs(hookargs)
2374 2376 )
2375 2377
2376 2378 for book, node in changes:
2377 2379 if bookmarks.isdivergent(book):
2378 2380 msg = _(b'cannot accept divergent bookmark %s!') % book
2379 2381 raise error.Abort(msg)
2380 2382
2381 2383 bookstore.applychanges(op.repo, op.gettransaction(), changes)
2382 2384
2383 2385 if pushkeycompat:
2384 2386
2385 2387 def runhook(unused_success):
2386 2388 for hookargs in allhooks:
2387 2389 op.repo.hook(b'pushkey', **pycompat.strkwargs(hookargs))
2388 2390
2389 2391 op.repo._afterlock(runhook)
2390 2392
2391 2393 elif bookmarksmode == b'records':
2392 2394 for book, node in changes:
2393 2395 record = {b'bookmark': book, b'node': node}
2394 2396 op.records.add(b'bookmarks', record)
2395 2397 else:
2396 2398 raise error.ProgrammingError(
2397 2399 b'unkown bookmark mode: %s' % bookmarksmode
2398 2400 )
2399 2401
2400 2402
2401 2403 @parthandler(b'phase-heads')
2402 2404 def handlephases(op, inpart):
2403 2405 """apply phases from bundle part to repo"""
2404 2406 headsbyphase = phases.binarydecode(inpart)
2405 2407 phases.updatephases(op.repo.unfiltered(), op.gettransaction, headsbyphase)
2406 2408
2407 2409
2408 2410 @parthandler(b'reply:pushkey', (b'return', b'in-reply-to'))
2409 2411 def handlepushkeyreply(op, inpart):
2410 2412 """retrieve the result of a pushkey request"""
2411 2413 ret = int(inpart.params[b'return'])
2412 2414 partid = int(inpart.params[b'in-reply-to'])
2413 2415 op.records.add(b'pushkey', {b'return': ret}, partid)
2414 2416
2415 2417
2416 2418 @parthandler(b'obsmarkers')
2417 2419 def handleobsmarker(op, inpart):
2418 2420 """add a stream of obsmarkers to the repo"""
2419 2421 tr = op.gettransaction()
2420 2422 markerdata = inpart.read()
2421 2423 if op.ui.config(b'experimental', b'obsmarkers-exchange-debug'):
2422 2424 op.ui.writenoi18n(
2423 2425 b'obsmarker-exchange: %i bytes received\n' % len(markerdata)
2424 2426 )
2425 2427 # The mergemarkers call will crash if marker creation is not enabled.
2426 2428 # we want to avoid this if the part is advisory.
2427 2429 if not inpart.mandatory and op.repo.obsstore.readonly:
2428 2430 op.repo.ui.debug(
2429 2431 b'ignoring obsolescence markers, feature not enabled\n'
2430 2432 )
2431 2433 return
2432 2434 new = op.repo.obsstore.mergemarkers(tr, markerdata)
2433 2435 op.repo.invalidatevolatilesets()
2434 2436 op.records.add(b'obsmarkers', {b'new': new})
2435 2437 if op.reply is not None:
2436 2438 rpart = op.reply.newpart(b'reply:obsmarkers')
2437 2439 rpart.addparam(
2438 2440 b'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False
2439 2441 )
2440 2442 rpart.addparam(b'new', b'%i' % new, mandatory=False)
2441 2443
2442 2444
2443 2445 @parthandler(b'reply:obsmarkers', (b'new', b'in-reply-to'))
2444 2446 def handleobsmarkerreply(op, inpart):
2445 2447 """retrieve the result of a pushkey request"""
2446 2448 ret = int(inpart.params[b'new'])
2447 2449 partid = int(inpart.params[b'in-reply-to'])
2448 2450 op.records.add(b'obsmarkers', {b'new': ret}, partid)
2449 2451
2450 2452
2451 2453 @parthandler(b'hgtagsfnodes')
2452 2454 def handlehgtagsfnodes(op, inpart):
2453 2455 """Applies .hgtags fnodes cache entries to the local repo.
2454 2456
2455 2457 Payload is pairs of 20 byte changeset nodes and filenodes.
2456 2458 """
2457 2459 # Grab the transaction so we ensure that we have the lock at this point.
2458 2460 if op.ui.configbool(b'experimental', b'bundle2lazylocking'):
2459 2461 op.gettransaction()
2460 2462 cache = tags.hgtagsfnodescache(op.repo.unfiltered())
2461 2463
2462 2464 count = 0
2463 2465 while True:
2464 2466 node = inpart.read(20)
2465 2467 fnode = inpart.read(20)
2466 2468 if len(node) < 20 or len(fnode) < 20:
2467 2469 op.ui.debug(b'ignoring incomplete received .hgtags fnodes data\n')
2468 2470 break
2469 2471 cache.setfnode(node, fnode)
2470 2472 count += 1
2471 2473
2472 2474 cache.write()
2473 2475 op.ui.debug(b'applied %i hgtags fnodes cache entries\n' % count)
2474 2476
2475 2477
2476 2478 rbcstruct = struct.Struct(b'>III')
2477 2479
2478 2480
2479 2481 @parthandler(b'cache:rev-branch-cache')
2480 2482 def handlerbc(op, inpart):
2481 2483 """Legacy part, ignored for compatibility with bundles from or
2482 2484 for Mercurial before 5.7. Newer Mercurial computes the cache
2483 2485 efficiently enough during unbundling that the additional transfer
2484 2486 is unnecessary."""
2485 2487
2486 2488
2487 2489 @parthandler(b'pushvars')
2488 2490 def bundle2getvars(op, part):
2489 2491 '''unbundle a bundle2 containing shellvars on the server'''
2490 2492 # An option to disable unbundling on server-side for security reasons
2491 2493 if op.ui.configbool(b'push', b'pushvars.server'):
2492 2494 hookargs = {}
2493 2495 for key, value in part.advisoryparams:
2494 2496 key = key.upper()
2495 2497 # We want pushed variables to have USERVAR_ prepended so we know
2496 2498 # they came from the --pushvar flag.
2497 2499 key = b"USERVAR_" + key
2498 2500 hookargs[key] = value
2499 2501 op.addhookargs(hookargs)
2500 2502
2501 2503
2502 2504 @parthandler(b'stream2', (b'requirements', b'filecount', b'bytecount'))
2503 2505 def handlestreamv2bundle(op, part):
2504 2506
2505 2507 requirements = urlreq.unquote(part.params[b'requirements']).split(b',')
2506 2508 filecount = int(part.params[b'filecount'])
2507 2509 bytecount = int(part.params[b'bytecount'])
2508 2510
2509 2511 repo = op.repo
2510 2512 if len(repo):
2511 2513 msg = _(b'cannot apply stream clone to non empty repository')
2512 2514 raise error.Abort(msg)
2513 2515
2514 2516 repo.ui.debug(b'applying stream bundle\n')
2515 2517 streamclone.applybundlev2(repo, part, filecount, bytecount, requirements)
2516 2518
2517 2519
2518 2520 def widen_bundle(
2519 2521 bundler, repo, oldmatcher, newmatcher, common, known, cgversion, ellipses
2520 2522 ):
2521 2523 """generates bundle2 for widening a narrow clone
2522 2524
2523 2525 bundler is the bundle to which data should be added
2524 2526 repo is the localrepository instance
2525 2527 oldmatcher matches what the client already has
2526 2528 newmatcher matches what the client needs (including what it already has)
2527 2529 common is set of common heads between server and client
2528 2530 known is a set of revs known on the client side (used in ellipses)
2529 2531 cgversion is the changegroup version to send
2530 2532 ellipses is boolean value telling whether to send ellipses data or not
2531 2533
2532 2534 returns bundle2 of the data required for extending
2533 2535 """
2534 2536 commonnodes = set()
2535 2537 cl = repo.changelog
2536 2538 for r in repo.revs(b"::%ln", common):
2537 2539 commonnodes.add(cl.node(r))
2538 2540 if commonnodes:
2539 2541 packer = changegroup.getbundler(
2540 2542 cgversion,
2541 2543 repo,
2542 2544 oldmatcher=oldmatcher,
2543 2545 matcher=newmatcher,
2544 2546 fullnodes=commonnodes,
2545 2547 )
2546 2548 cgdata = packer.generate(
2547 2549 {nullid},
2548 2550 list(commonnodes),
2549 2551 False,
2550 2552 b'narrow_widen',
2551 2553 changelog=False,
2552 2554 )
2553 2555
2554 2556 part = bundler.newpart(b'changegroup', data=cgdata)
2555 2557 part.addparam(b'version', cgversion)
2556 2558 if scmutil.istreemanifest(repo):
2557 2559 part.addparam(b'treemanifest', b'1')
2558 2560 if b'exp-sidedata-flag' in repo.requirements:
2559 2561 part.addparam(b'exp-sidedata', b'1')
2560 2562
2561 2563 return bundler
@@ -1,202 +1,198 b''
1 1 # common patterns in test at can safely be replaced
2 2 from __future__ import absolute_import
3 3
4 4 import os
5 5
6 6 substitutions = [
7 7 # list of possible compressions
8 8 (br'(zstd,)?zlib,none,bzip2', br'$USUAL_COMPRESSIONS$'),
9 9 (br'=(zstd,)?zlib', br'=$BUNDLE2_COMPRESSIONS$'),
10 10 # capabilities sent through http
11 11 (
12 12 br'bundlecaps=HG20%2Cbundle2%3DHG20%250A'
13 13 br'bookmarks%250A'
14 14 br'changegroup%253D01%252C02%250A'
15 15 br'checkheads%253Drelated%250A'
16 16 br'digests%253Dmd5%252Csha1%252Csha512%250A'
17 17 br'error%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250A'
18 18 br'hgtagsfnodes%250A'
19 19 br'listkeys%250A'
20 20 br'phases%253Dheads%250A'
21 21 br'pushkey%250A'
22 22 br'remote-changegroup%253Dhttp%252Chttps%250A'
23 br'rev-branch-cache%250A'
24 23 br'stream%253Dv2',
25 24 # (the replacement patterns)
26 25 br'$USUAL_BUNDLE_CAPS$',
27 26 ),
28 27 (
29 28 br'bundlecaps=HG20%2Cbundle2%3DHG20%250A'
30 29 br'bookmarks%250A'
31 30 br'changegroup%253D01%252C02%250A'
32 31 br'checkheads%3Drelated%0A'
33 32 br'digests%253Dmd5%252Csha1%252Csha512%250A'
34 33 br'error%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250A'
35 34 br'hgtagsfnodes%250A'
36 35 br'listkeys%250A'
37 36 br'phases%253Dheads%250A'
38 37 br'pushkey%250A'
39 38 br'remote-changegroup%253Dhttp%252Chttps',
40 39 # (the replacement patterns)
41 40 br'$USUAL_BUNDLE_CAPS_SERVER$',
42 41 ),
43 42 # bundle2 capabilities sent through ssh
44 43 (
45 44 br'bundle2=HG20%0A'
46 45 br'bookmarks%0A'
47 46 br'changegroup%3D01%2C02%0A'
48 47 br'checkheads%3Drelated%0A'
49 48 br'digests%3Dmd5%2Csha1%2Csha512%0A'
50 49 br'error%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0A'
51 50 br'hgtagsfnodes%0A'
52 51 br'listkeys%0A'
53 52 br'phases%3Dheads%0A'
54 53 br'pushkey%0A'
55 54 br'remote-changegroup%3Dhttp%2Chttps%0A'
56 br'rev-branch-cache%0A'
57 55 br'stream%3Dv2',
58 56 # (replacement patterns)
59 57 br'$USUAL_BUNDLE2_CAPS$',
60 58 ),
61 59 # bundle2 capabilities advertised by the server
62 60 (
63 61 br'bundle2=HG20%0A'
64 62 br'bookmarks%0A'
65 63 br'changegroup%3D01%2C02%0A'
66 64 br'checkheads%3Drelated%0A'
67 65 br'digests%3Dmd5%2Csha1%2Csha512%0A'
68 66 br'error%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0A'
69 67 br'hgtagsfnodes%0A'
70 68 br'listkeys%0A'
71 69 br'phases%3Dheads%0A'
72 70 br'pushkey%0A'
73 br'remote-changegroup%3Dhttp%2Chttps%0A'
74 br'rev-branch-cache',
71 br'remote-changegroup%3Dhttp%2Chttps',
75 72 # (replacement patterns)
76 73 br'$USUAL_BUNDLE2_CAPS_SERVER$',
77 74 ),
78 75 (
79 76 br'bundle2=HG20%0A'
80 77 br'bookmarks%0A'
81 78 br'changegroup%3D01%2C02%0A'
82 79 br'digests%3Dmd5%2Csha1%2Csha512%0A'
83 80 br'error%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0A'
84 81 br'hgtagsfnodes%0A'
85 82 br'listkeys%0A'
86 83 br'pushkey%0A'
87 84 br'remote-changegroup%3Dhttp%2Chttps%0A'
88 br'rev-branch-cache%0A'
89 85 br'stream%3Dv2',
90 86 # (replacement patterns)
91 87 br'$USUAL_BUNDLE2_CAPS_NO_PHASES$',
92 88 ),
93 89 # HTTP access log dates
94 90 (
95 91 br' - - \[\d\d/.../2\d\d\d \d\d:\d\d:\d\d] "(GET|PUT|POST)',
96 92 lambda m: br' - - [$LOGDATE$] "' + m.group(1),
97 93 ),
98 94 # HTTP error log dates
99 95 (
100 96 br' - - \[\d\d/.../2\d\d\d \d\d:\d\d:\d\d] (HG error:|Exception)',
101 97 lambda m: br' - - [$ERRDATE$] ' + m.group(1),
102 98 ),
103 99 # HTTP header dates- RFC 1123
104 100 (
105 101 br'([Dd]ate): [A-Za-z]{3}, \d\d [A-Za-z]{3} \d{4} \d\d:\d\d:\d\d GMT',
106 102 lambda m: br'%s: $HTTP_DATE$' % m.group(1),
107 103 ),
108 104 # LFS expiration value
109 105 (
110 106 br'"expires_at": "\d{4}-\d\d-\d\dT\d\d:\d\d:\d\dZ"',
111 107 br'"expires_at": "$ISO_8601_DATE_TIME$"',
112 108 ),
113 109 # Windows has an extra '/' in the following lines that get globbed away:
114 110 # pushing to file:/*/$TESTTMP/r2 (glob)
115 111 # comparing with file:/*/$TESTTMP/r2 (glob)
116 112 # sub/maybelarge.dat: largefile 34..9c not available from
117 113 # file:/*/$TESTTMP/largefiles-repo (glob)
118 114 (
119 115 br'(.*file:/)/?(/\$TESTTMP.*)',
120 116 lambda m: m.group(1) + b'*' + m.group(2) + b' (glob)',
121 117 ),
122 118 ]
123 119
124 120 # Various platform error strings, keyed on a common replacement string
125 121 _errors = {
126 122 br'$ENOENT$': (
127 123 # IOError in Python does not have the same error message
128 124 # than in Rust, and automatic conversion is not possible
129 125 # because of module member privacy.
130 126 br'No such file or directory \(os error 2\)',
131 127 # strerror()
132 128 br'No such file or directory',
133 129 # FormatMessage(ERROR_FILE_NOT_FOUND)
134 130 br'The system cannot find the file specified',
135 131 ),
136 132 br'$ENOTDIR$': (
137 133 # strerror()
138 134 br'Not a directory',
139 135 # FormatMessage(ERROR_PATH_NOT_FOUND)
140 136 br'The system cannot find the path specified',
141 137 ),
142 138 br'$ECONNRESET$': (
143 139 # strerror()
144 140 br'Connection reset by peer',
145 141 # FormatMessage(WSAECONNRESET)
146 142 br'An existing connection was forcibly closed by the remote host',
147 143 ),
148 144 br'$EADDRINUSE$': (
149 145 # strerror()
150 146 br'Address already in use',
151 147 # FormatMessage(WSAEADDRINUSE)
152 148 br'Only one usage of each socket address'
153 149 br' \(protocol/network address/port\) is normally permitted',
154 150 ),
155 151 br'$EADDRNOTAVAIL$': (
156 152 # strerror()
157 153 br'Cannot assign requested address',
158 154 # FormatMessage(WSAEADDRNOTAVAIL)
159 155 ),
160 156 }
161 157
162 158 for replace, msgs in _errors.items():
163 159 substitutions.extend((m, replace) for m in msgs)
164 160
165 161 # Output lines on Windows that can be autocorrected for '\' vs '/' path
166 162 # differences.
167 163 _winpathfixes = [
168 164 # cloning subrepo s\ss from $TESTTMP/t/s/ss
169 165 # cloning subrepo foo\bar from http://localhost:$HGPORT/foo/bar
170 166 br'(?m)^cloning subrepo \S+\\.*',
171 167 # pulling from $TESTTMP\issue1852a
172 168 br'(?m)^pulling from \$TESTTMP\\.*',
173 169 # pushing to $TESTTMP\a
174 170 br'(?m)^pushing to \$TESTTMP\\.*',
175 171 # pushing subrepo s\ss to $TESTTMP/t/s/ss
176 172 br'(?m)^pushing subrepo \S+\\\S+ to.*',
177 173 # moving d1\d11\a1 to d3/d11/a1
178 174 br'(?m)^moving \S+\\.*',
179 175 # d1\a: not recording move - dummy does not exist
180 176 br'\S+\\\S+: not recording move .+',
181 177 # reverting s\a
182 178 br'(?m)^reverting (?!subrepo ).*\\.*',
183 179 # saved backup bundle to
184 180 # $TESTTMP\test\.hg\strip-backup/443431ffac4f-2fc5398a-backup.hg
185 181 br'(?m)^saved backup bundle to \$TESTTMP.*\.hg',
186 182 # no changes made to subrepo s\ss since last push to ../tcc/s/ss
187 183 br'(?m)^no changes made to subrepo \S+\\\S+ since.*',
188 184 # changeset 5:9cc5aa7204f0: stuff/maybelarge.dat references missing
189 185 # $TESTTMP\largefiles-repo-hg\.hg\largefiles\76..38
190 186 br'(?m)^changeset .* references (corrupted|missing) \$TESTTMP\\.*',
191 187 # stuff/maybelarge.dat: largefile 76..38 not available from
192 188 # file:/*/$TESTTMP\largefiles-repo (glob)
193 189 br'.*: largefile \S+ not available from file:/\*/.+',
194 190 ]
195 191
196 192 if os.name == 'nt':
197 193 substitutions.extend(
198 194 [
199 195 (s, lambda match: match.group().replace(b'\\', b'/'))
200 196 for s in _winpathfixes
201 197 ]
202 198 )
@@ -1,2444 +1,2444 b''
1 1 > do_push()
2 2 > {
3 3 > user=$1
4 4 > shift
5 5 > echo "Pushing as user $user"
6 6 > echo 'hgrc = """'
7 7 > sed -n '/\[[ha]/,$p' b/.hg/hgrc | grep -v fakegroups.py
8 8 > echo '"""'
9 9 > if test -f acl.config; then
10 10 > echo 'acl.config = """'
11 11 > cat acl.config
12 12 > echo '"""'
13 13 > fi
14 14 > # On AIX /etc/profile sets LOGNAME read-only. So
15 15 > # LOGNAME=$user hg --cws a --debug push ../b
16 16 > # fails with "This variable is read only."
17 17 > # Use env to work around this.
18 18 > env LOGNAME=$user hg --cwd a --debug push ../b $*
19 19 > hg --cwd b rollback
20 20 > hg --cwd b --quiet tip
21 21 > echo
22 22 > }
23 23
24 24 > cat > posixgetuser.py <<'EOF'
25 25 > import getpass
26 26 > from mercurial import pycompat
27 27 > from mercurial.utils import procutil
28 28 > def posixgetuser():
29 29 > return pycompat.fsencode(getpass.getuser())
30 30 > if not pycompat.isposix:
31 31 > procutil.getuser = posixgetuser # forcibly trust $LOGNAME
32 32 > EOF
33 33
34 34 > init_config()
35 35 > {
36 36 > cat > fakegroups.py <<EOF
37 37 > from hgext import acl
38 38 > def fakegetusers(ui, group):
39 39 > try:
40 40 > return acl._getusersorig(ui, group)
41 41 > except BaseException:
42 42 > return [b"fred", b"betty"]
43 43 > acl._getusersorig = acl._getusers
44 44 > acl._getusers = fakegetusers
45 45 > EOF
46 46 > rm -f acl.config
47 47 > cat > $config <<EOF
48 48 > [hooks]
49 49 > pretxnchangegroup.acl = python:hgext.acl.hook
50 50 > prepushkey.acl = python:hgext.acl.hook
51 51 > [acl]
52 52 > sources = push
53 53 > [extensions]
54 54 > f=`pwd`/fakegroups.py
55 55 > posixgetuser=$TESTTMP/posixgetuser.py
56 56 > EOF
57 57 > }
58 58
59 59 $ hg init a
60 60 $ cd a
61 61 $ mkdir foo foo/Bar quux
62 62 $ echo 'in foo' > foo/file.txt
63 63 $ echo 'in foo/Bar' > foo/Bar/file.txt
64 64 $ echo 'in quux' > quux/file.py
65 65 $ hg add -q
66 66 $ hg ci -m 'add files' -d '1000000 0'
67 67 $ echo >> foo/file.txt
68 68 $ hg ci -m 'change foo/file' -d '1000001 0'
69 69 $ echo >> foo/Bar/file.txt
70 70 $ hg ci -m 'change foo/Bar/file' -d '1000002 0'
71 71 $ echo >> quux/file.py
72 72 $ hg ci -m 'change quux/file' -d '1000003 0'
73 73 $ hg tip --quiet
74 74 3:911600dab2ae
75 75
76 76 $ cd ..
77 77 $ hg clone -r 0 a b
78 78 adding changesets
79 79 adding manifests
80 80 adding file changes
81 81 added 1 changesets with 3 changes to 3 files
82 82 new changesets 6675d58eff77
83 83 updating to branch default
84 84 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
85 85
86 86 $ config=b/.hg/hgrc
87 87 $ cat >> "$config" <<EOF
88 88 > [extensions]
89 89 > posixgetuser=$TESTTMP/posixgetuser.py
90 90 > EOF
91 91
92 92 Extension disabled for lack of a hook
93 93
94 94 $ do_push fred
95 95 Pushing as user fred
96 96 hgrc = """
97 97 """
98 98 pushing to ../b
99 99 query 1; heads
100 100 searching for changes
101 101 all remote heads known locally
102 102 listing keys for "phases"
103 103 checking for updated bookmarks
104 104 listing keys for "bookmarks"
105 105 listing keys for "bookmarks"
106 106 3 changesets found
107 107 list of changesets:
108 108 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
109 109 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
110 110 911600dab2ae7a9baff75958b84fe606851ce955
111 111 bundle2-output-bundle: "HG20", 5 parts total
112 bundle2-output-part: "replycaps" 224 bytes payload
112 bundle2-output-part: "replycaps" 207 bytes payload
113 113 bundle2-output-part: "check:phases" 24 bytes payload
114 114 bundle2-output-part: "check:updated-heads" streamed payload
115 115 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
116 116 bundle2-output-part: "phase-heads" 24 bytes payload
117 117 bundle2-input-bundle: with-transaction
118 118 bundle2-input-part: "replycaps" supported
119 bundle2-input-part: total payload size 224
119 bundle2-input-part: total payload size 207
120 120 bundle2-input-part: "check:phases" supported
121 121 bundle2-input-part: total payload size 24
122 122 bundle2-input-part: "check:updated-heads" supported
123 123 bundle2-input-part: total payload size 20
124 124 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
125 125 adding changesets
126 126 add changeset ef1ea85a6374
127 127 add changeset f9cafe1212c8
128 128 add changeset 911600dab2ae
129 129 adding manifests
130 130 adding file changes
131 131 adding foo/Bar/file.txt revisions
132 132 adding foo/file.txt revisions
133 133 adding quux/file.py revisions
134 134 bundle2-input-part: total payload size 1553
135 135 bundle2-input-part: "phase-heads" supported
136 136 bundle2-input-part: total payload size 24
137 137 bundle2-input-bundle: 5 parts total
138 138 updating the branch cache
139 139 added 3 changesets with 3 changes to 3 files
140 140 bundle2-output-bundle: "HG20", 1 parts total
141 141 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
142 142 bundle2-input-bundle: no-transaction
143 143 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
144 144 bundle2-input-bundle: 1 parts total
145 145 listing keys for "phases"
146 146 repository tip rolled back to revision 0 (undo push)
147 147 0:6675d58eff77
148 148
149 149
150 150 $ echo '[hooks]' >> $config
151 151 $ echo 'pretxnchangegroup.acl = python:hgext.acl.hook' >> $config
152 152 $ echo 'prepushkey.acl = python:hgext.acl.hook' >> $config
153 153
154 154 Extension disabled for lack of acl.sources
155 155
156 156 $ do_push fred
157 157 Pushing as user fred
158 158 hgrc = """
159 159 [hooks]
160 160 pretxnchangegroup.acl = python:hgext.acl.hook
161 161 prepushkey.acl = python:hgext.acl.hook
162 162 """
163 163 pushing to ../b
164 164 query 1; heads
165 165 searching for changes
166 166 all remote heads known locally
167 167 listing keys for "phases"
168 168 checking for updated bookmarks
169 169 listing keys for "bookmarks"
170 170 invalid branch cache (served): tip differs
171 171 listing keys for "bookmarks"
172 172 3 changesets found
173 173 list of changesets:
174 174 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
175 175 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
176 176 911600dab2ae7a9baff75958b84fe606851ce955
177 177 bundle2-output-bundle: "HG20", 5 parts total
178 bundle2-output-part: "replycaps" 224 bytes payload
178 bundle2-output-part: "replycaps" 207 bytes payload
179 179 bundle2-output-part: "check:phases" 24 bytes payload
180 180 bundle2-output-part: "check:updated-heads" streamed payload
181 181 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
182 182 bundle2-output-part: "phase-heads" 24 bytes payload
183 183 bundle2-input-bundle: with-transaction
184 184 bundle2-input-part: "replycaps" supported
185 bundle2-input-part: total payload size 224
185 bundle2-input-part: total payload size 207
186 186 bundle2-input-part: "check:phases" supported
187 187 bundle2-input-part: total payload size 24
188 188 bundle2-input-part: "check:updated-heads" supported
189 189 bundle2-input-part: total payload size 20
190 190 invalid branch cache (served): tip differs
191 191 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
192 192 adding changesets
193 193 add changeset ef1ea85a6374
194 194 add changeset f9cafe1212c8
195 195 add changeset 911600dab2ae
196 196 adding manifests
197 197 adding file changes
198 198 adding foo/Bar/file.txt revisions
199 199 adding foo/file.txt revisions
200 200 adding quux/file.py revisions
201 201 calling hook pretxnchangegroup.acl: hgext.acl.hook
202 202 acl: changes have source "push" - skipping
203 203 bundle2-input-part: total payload size 1553
204 204 bundle2-input-part: "phase-heads" supported
205 205 bundle2-input-part: total payload size 24
206 206 bundle2-input-bundle: 5 parts total
207 207 truncating cache/rbc-revs-v1 to 8
208 208 updating the branch cache
209 209 added 3 changesets with 3 changes to 3 files
210 210 bundle2-output-bundle: "HG20", 1 parts total
211 211 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
212 212 bundle2-input-bundle: no-transaction
213 213 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
214 214 bundle2-input-bundle: 1 parts total
215 215 listing keys for "phases"
216 216 repository tip rolled back to revision 0 (undo push)
217 217 0:6675d58eff77
218 218
219 219
220 220 No [acl.allow]/[acl.deny]
221 221
222 222 $ echo '[acl]' >> $config
223 223 $ echo 'sources = push' >> $config
224 224 $ do_push fred
225 225 Pushing as user fred
226 226 hgrc = """
227 227 [hooks]
228 228 pretxnchangegroup.acl = python:hgext.acl.hook
229 229 prepushkey.acl = python:hgext.acl.hook
230 230 [acl]
231 231 sources = push
232 232 """
233 233 pushing to ../b
234 234 query 1; heads
235 235 searching for changes
236 236 all remote heads known locally
237 237 listing keys for "phases"
238 238 checking for updated bookmarks
239 239 listing keys for "bookmarks"
240 240 invalid branch cache (served): tip differs
241 241 listing keys for "bookmarks"
242 242 3 changesets found
243 243 list of changesets:
244 244 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
245 245 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
246 246 911600dab2ae7a9baff75958b84fe606851ce955
247 247 bundle2-output-bundle: "HG20", 5 parts total
248 bundle2-output-part: "replycaps" 224 bytes payload
248 bundle2-output-part: "replycaps" 207 bytes payload
249 249 bundle2-output-part: "check:phases" 24 bytes payload
250 250 bundle2-output-part: "check:updated-heads" streamed payload
251 251 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
252 252 bundle2-output-part: "phase-heads" 24 bytes payload
253 253 bundle2-input-bundle: with-transaction
254 254 bundle2-input-part: "replycaps" supported
255 bundle2-input-part: total payload size 224
255 bundle2-input-part: total payload size 207
256 256 bundle2-input-part: "check:phases" supported
257 257 bundle2-input-part: total payload size 24
258 258 bundle2-input-part: "check:updated-heads" supported
259 259 bundle2-input-part: total payload size 20
260 260 invalid branch cache (served): tip differs
261 261 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
262 262 adding changesets
263 263 add changeset ef1ea85a6374
264 264 add changeset f9cafe1212c8
265 265 add changeset 911600dab2ae
266 266 adding manifests
267 267 adding file changes
268 268 adding foo/Bar/file.txt revisions
269 269 adding foo/file.txt revisions
270 270 adding quux/file.py revisions
271 271 calling hook pretxnchangegroup.acl: hgext.acl.hook
272 272 acl: checking access for user "fred"
273 273 acl: acl.allow.branches not enabled
274 274 acl: acl.deny.branches not enabled
275 275 acl: acl.allow not enabled
276 276 acl: acl.deny not enabled
277 277 acl: branch access granted: "ef1ea85a6374" on branch "default"
278 278 acl: path access granted: "ef1ea85a6374"
279 279 acl: branch access granted: "f9cafe1212c8" on branch "default"
280 280 acl: path access granted: "f9cafe1212c8"
281 281 acl: branch access granted: "911600dab2ae" on branch "default"
282 282 acl: path access granted: "911600dab2ae"
283 283 bundle2-input-part: total payload size 1553
284 284 bundle2-input-part: "phase-heads" supported
285 285 bundle2-input-part: total payload size 24
286 286 bundle2-input-bundle: 5 parts total
287 287 truncating cache/rbc-revs-v1 to 8
288 288 updating the branch cache
289 289 added 3 changesets with 3 changes to 3 files
290 290 bundle2-output-bundle: "HG20", 1 parts total
291 291 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
292 292 bundle2-input-bundle: no-transaction
293 293 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
294 294 bundle2-input-bundle: 1 parts total
295 295 listing keys for "phases"
296 296 repository tip rolled back to revision 0 (undo push)
297 297 0:6675d58eff77
298 298
299 299
300 300 Empty [acl.allow]
301 301
302 302 $ echo '[acl.allow]' >> $config
303 303 $ do_push fred
304 304 Pushing as user fred
305 305 hgrc = """
306 306 [hooks]
307 307 pretxnchangegroup.acl = python:hgext.acl.hook
308 308 prepushkey.acl = python:hgext.acl.hook
309 309 [acl]
310 310 sources = push
311 311 [acl.allow]
312 312 """
313 313 pushing to ../b
314 314 query 1; heads
315 315 searching for changes
316 316 all remote heads known locally
317 317 listing keys for "phases"
318 318 checking for updated bookmarks
319 319 listing keys for "bookmarks"
320 320 invalid branch cache (served): tip differs
321 321 listing keys for "bookmarks"
322 322 3 changesets found
323 323 list of changesets:
324 324 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
325 325 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
326 326 911600dab2ae7a9baff75958b84fe606851ce955
327 327 bundle2-output-bundle: "HG20", 5 parts total
328 bundle2-output-part: "replycaps" 224 bytes payload
328 bundle2-output-part: "replycaps" 207 bytes payload
329 329 bundle2-output-part: "check:phases" 24 bytes payload
330 330 bundle2-output-part: "check:updated-heads" streamed payload
331 331 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
332 332 bundle2-output-part: "phase-heads" 24 bytes payload
333 333 bundle2-input-bundle: with-transaction
334 334 bundle2-input-part: "replycaps" supported
335 bundle2-input-part: total payload size 224
335 bundle2-input-part: total payload size 207
336 336 bundle2-input-part: "check:phases" supported
337 337 bundle2-input-part: total payload size 24
338 338 bundle2-input-part: "check:updated-heads" supported
339 339 bundle2-input-part: total payload size 20
340 340 invalid branch cache (served): tip differs
341 341 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
342 342 adding changesets
343 343 add changeset ef1ea85a6374
344 344 add changeset f9cafe1212c8
345 345 add changeset 911600dab2ae
346 346 adding manifests
347 347 adding file changes
348 348 adding foo/Bar/file.txt revisions
349 349 adding foo/file.txt revisions
350 350 adding quux/file.py revisions
351 351 calling hook pretxnchangegroup.acl: hgext.acl.hook
352 352 acl: checking access for user "fred"
353 353 acl: acl.allow.branches not enabled
354 354 acl: acl.deny.branches not enabled
355 355 acl: acl.allow enabled, 0 entries for user fred
356 356 acl: acl.deny not enabled
357 357 acl: branch access granted: "ef1ea85a6374" on branch "default"
358 358 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
359 359 bundle2-input-part: total payload size 1553
360 360 bundle2-input-part: total payload size 24
361 361 bundle2-input-bundle: 5 parts total
362 362 transaction abort!
363 363 rollback completed
364 364 abort: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
365 365 no rollback information available
366 366 0:6675d58eff77
367 367
368 368
369 369 fred is allowed inside foo/
370 370
371 371 $ echo 'foo/** = fred' >> $config
372 372 $ do_push fred
373 373 Pushing as user fred
374 374 hgrc = """
375 375 [hooks]
376 376 pretxnchangegroup.acl = python:hgext.acl.hook
377 377 prepushkey.acl = python:hgext.acl.hook
378 378 [acl]
379 379 sources = push
380 380 [acl.allow]
381 381 foo/** = fred
382 382 """
383 383 pushing to ../b
384 384 query 1; heads
385 385 searching for changes
386 386 all remote heads known locally
387 387 listing keys for "phases"
388 388 checking for updated bookmarks
389 389 listing keys for "bookmarks"
390 390 invalid branch cache (served): tip differs
391 391 listing keys for "bookmarks"
392 392 3 changesets found
393 393 list of changesets:
394 394 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
395 395 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
396 396 911600dab2ae7a9baff75958b84fe606851ce955
397 397 bundle2-output-bundle: "HG20", 5 parts total
398 bundle2-output-part: "replycaps" 224 bytes payload
398 bundle2-output-part: "replycaps" 207 bytes payload
399 399 bundle2-output-part: "check:phases" 24 bytes payload
400 400 bundle2-output-part: "check:updated-heads" streamed payload
401 401 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
402 402 bundle2-output-part: "phase-heads" 24 bytes payload
403 403 bundle2-input-bundle: with-transaction
404 404 bundle2-input-part: "replycaps" supported
405 bundle2-input-part: total payload size 224
405 bundle2-input-part: total payload size 207
406 406 bundle2-input-part: "check:phases" supported
407 407 bundle2-input-part: total payload size 24
408 408 bundle2-input-part: "check:updated-heads" supported
409 409 bundle2-input-part: total payload size 20
410 410 invalid branch cache (served): tip differs
411 411 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
412 412 adding changesets
413 413 add changeset ef1ea85a6374
414 414 add changeset f9cafe1212c8
415 415 add changeset 911600dab2ae
416 416 adding manifests
417 417 adding file changes
418 418 adding foo/Bar/file.txt revisions
419 419 adding foo/file.txt revisions
420 420 adding quux/file.py revisions
421 421 calling hook pretxnchangegroup.acl: hgext.acl.hook
422 422 acl: checking access for user "fred"
423 423 acl: acl.allow.branches not enabled
424 424 acl: acl.deny.branches not enabled
425 425 acl: acl.allow enabled, 1 entries for user fred
426 426 acl: acl.deny not enabled
427 427 acl: branch access granted: "ef1ea85a6374" on branch "default"
428 428 acl: path access granted: "ef1ea85a6374"
429 429 acl: branch access granted: "f9cafe1212c8" on branch "default"
430 430 acl: path access granted: "f9cafe1212c8"
431 431 acl: branch access granted: "911600dab2ae" on branch "default"
432 432 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
433 433 bundle2-input-part: total payload size 1553
434 434 bundle2-input-part: total payload size 24
435 435 bundle2-input-bundle: 5 parts total
436 436 transaction abort!
437 437 rollback completed
438 438 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
439 439 no rollback information available
440 440 0:6675d58eff77
441 441
442 442
443 443 Empty [acl.deny]
444 444
445 445 $ echo '[acl.deny]' >> $config
446 446 $ do_push barney
447 447 Pushing as user barney
448 448 hgrc = """
449 449 [hooks]
450 450 pretxnchangegroup.acl = python:hgext.acl.hook
451 451 prepushkey.acl = python:hgext.acl.hook
452 452 [acl]
453 453 sources = push
454 454 [acl.allow]
455 455 foo/** = fred
456 456 [acl.deny]
457 457 """
458 458 pushing to ../b
459 459 query 1; heads
460 460 searching for changes
461 461 all remote heads known locally
462 462 listing keys for "phases"
463 463 checking for updated bookmarks
464 464 listing keys for "bookmarks"
465 465 invalid branch cache (served): tip differs
466 466 listing keys for "bookmarks"
467 467 3 changesets found
468 468 list of changesets:
469 469 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
470 470 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
471 471 911600dab2ae7a9baff75958b84fe606851ce955
472 472 bundle2-output-bundle: "HG20", 5 parts total
473 bundle2-output-part: "replycaps" 224 bytes payload
473 bundle2-output-part: "replycaps" 207 bytes payload
474 474 bundle2-output-part: "check:phases" 24 bytes payload
475 475 bundle2-output-part: "check:updated-heads" streamed payload
476 476 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
477 477 bundle2-output-part: "phase-heads" 24 bytes payload
478 478 bundle2-input-bundle: with-transaction
479 479 bundle2-input-part: "replycaps" supported
480 bundle2-input-part: total payload size 224
480 bundle2-input-part: total payload size 207
481 481 bundle2-input-part: "check:phases" supported
482 482 bundle2-input-part: total payload size 24
483 483 bundle2-input-part: "check:updated-heads" supported
484 484 bundle2-input-part: total payload size 20
485 485 invalid branch cache (served): tip differs
486 486 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
487 487 adding changesets
488 488 add changeset ef1ea85a6374
489 489 add changeset f9cafe1212c8
490 490 add changeset 911600dab2ae
491 491 adding manifests
492 492 adding file changes
493 493 adding foo/Bar/file.txt revisions
494 494 adding foo/file.txt revisions
495 495 adding quux/file.py revisions
496 496 calling hook pretxnchangegroup.acl: hgext.acl.hook
497 497 acl: checking access for user "barney"
498 498 acl: acl.allow.branches not enabled
499 499 acl: acl.deny.branches not enabled
500 500 acl: acl.allow enabled, 0 entries for user barney
501 501 acl: acl.deny enabled, 0 entries for user barney
502 502 acl: branch access granted: "ef1ea85a6374" on branch "default"
503 503 error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
504 504 bundle2-input-part: total payload size 1553
505 505 bundle2-input-part: total payload size 24
506 506 bundle2-input-bundle: 5 parts total
507 507 transaction abort!
508 508 rollback completed
509 509 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
510 510 no rollback information available
511 511 0:6675d58eff77
512 512
513 513
514 514 fred is allowed inside foo/, but not foo/bar/ (case matters)
515 515
516 516 $ echo 'foo/bar/** = fred' >> $config
517 517 $ do_push fred
518 518 Pushing as user fred
519 519 hgrc = """
520 520 [hooks]
521 521 pretxnchangegroup.acl = python:hgext.acl.hook
522 522 prepushkey.acl = python:hgext.acl.hook
523 523 [acl]
524 524 sources = push
525 525 [acl.allow]
526 526 foo/** = fred
527 527 [acl.deny]
528 528 foo/bar/** = fred
529 529 """
530 530 pushing to ../b
531 531 query 1; heads
532 532 searching for changes
533 533 all remote heads known locally
534 534 listing keys for "phases"
535 535 checking for updated bookmarks
536 536 listing keys for "bookmarks"
537 537 invalid branch cache (served): tip differs
538 538 listing keys for "bookmarks"
539 539 3 changesets found
540 540 list of changesets:
541 541 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
542 542 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
543 543 911600dab2ae7a9baff75958b84fe606851ce955
544 544 bundle2-output-bundle: "HG20", 5 parts total
545 bundle2-output-part: "replycaps" 224 bytes payload
545 bundle2-output-part: "replycaps" 207 bytes payload
546 546 bundle2-output-part: "check:phases" 24 bytes payload
547 547 bundle2-output-part: "check:updated-heads" streamed payload
548 548 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
549 549 bundle2-output-part: "phase-heads" 24 bytes payload
550 550 bundle2-input-bundle: with-transaction
551 551 bundle2-input-part: "replycaps" supported
552 bundle2-input-part: total payload size 224
552 bundle2-input-part: total payload size 207
553 553 bundle2-input-part: "check:phases" supported
554 554 bundle2-input-part: total payload size 24
555 555 bundle2-input-part: "check:updated-heads" supported
556 556 bundle2-input-part: total payload size 20
557 557 invalid branch cache (served): tip differs
558 558 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
559 559 adding changesets
560 560 add changeset ef1ea85a6374
561 561 add changeset f9cafe1212c8
562 562 add changeset 911600dab2ae
563 563 adding manifests
564 564 adding file changes
565 565 adding foo/Bar/file.txt revisions
566 566 adding foo/file.txt revisions
567 567 adding quux/file.py revisions
568 568 calling hook pretxnchangegroup.acl: hgext.acl.hook
569 569 acl: checking access for user "fred"
570 570 acl: acl.allow.branches not enabled
571 571 acl: acl.deny.branches not enabled
572 572 acl: acl.allow enabled, 1 entries for user fred
573 573 acl: acl.deny enabled, 1 entries for user fred
574 574 acl: branch access granted: "ef1ea85a6374" on branch "default"
575 575 acl: path access granted: "ef1ea85a6374"
576 576 acl: branch access granted: "f9cafe1212c8" on branch "default"
577 577 acl: path access granted: "f9cafe1212c8"
578 578 acl: branch access granted: "911600dab2ae" on branch "default"
579 579 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
580 580 bundle2-input-part: total payload size 1553
581 581 bundle2-input-part: total payload size 24
582 582 bundle2-input-bundle: 5 parts total
583 583 transaction abort!
584 584 rollback completed
585 585 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
586 586 no rollback information available
587 587 0:6675d58eff77
588 588
589 589
590 590 fred is allowed inside foo/, but not foo/Bar/
591 591
592 592 $ echo 'foo/Bar/** = fred' >> $config
593 593 $ do_push fred
594 594 Pushing as user fred
595 595 hgrc = """
596 596 [hooks]
597 597 pretxnchangegroup.acl = python:hgext.acl.hook
598 598 prepushkey.acl = python:hgext.acl.hook
599 599 [acl]
600 600 sources = push
601 601 [acl.allow]
602 602 foo/** = fred
603 603 [acl.deny]
604 604 foo/bar/** = fred
605 605 foo/Bar/** = fred
606 606 """
607 607 pushing to ../b
608 608 query 1; heads
609 609 searching for changes
610 610 all remote heads known locally
611 611 listing keys for "phases"
612 612 checking for updated bookmarks
613 613 listing keys for "bookmarks"
614 614 invalid branch cache (served): tip differs
615 615 listing keys for "bookmarks"
616 616 3 changesets found
617 617 list of changesets:
618 618 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
619 619 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
620 620 911600dab2ae7a9baff75958b84fe606851ce955
621 621 bundle2-output-bundle: "HG20", 5 parts total
622 bundle2-output-part: "replycaps" 224 bytes payload
622 bundle2-output-part: "replycaps" 207 bytes payload
623 623 bundle2-output-part: "check:phases" 24 bytes payload
624 624 bundle2-output-part: "check:updated-heads" streamed payload
625 625 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
626 626 bundle2-output-part: "phase-heads" 24 bytes payload
627 627 bundle2-input-bundle: with-transaction
628 628 bundle2-input-part: "replycaps" supported
629 bundle2-input-part: total payload size 224
629 bundle2-input-part: total payload size 207
630 630 bundle2-input-part: "check:phases" supported
631 631 bundle2-input-part: total payload size 24
632 632 bundle2-input-part: "check:updated-heads" supported
633 633 bundle2-input-part: total payload size 20
634 634 invalid branch cache (served): tip differs
635 635 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
636 636 adding changesets
637 637 add changeset ef1ea85a6374
638 638 add changeset f9cafe1212c8
639 639 add changeset 911600dab2ae
640 640 adding manifests
641 641 adding file changes
642 642 adding foo/Bar/file.txt revisions
643 643 adding foo/file.txt revisions
644 644 adding quux/file.py revisions
645 645 calling hook pretxnchangegroup.acl: hgext.acl.hook
646 646 acl: checking access for user "fred"
647 647 acl: acl.allow.branches not enabled
648 648 acl: acl.deny.branches not enabled
649 649 acl: acl.allow enabled, 1 entries for user fred
650 650 acl: acl.deny enabled, 2 entries for user fred
651 651 acl: branch access granted: "ef1ea85a6374" on branch "default"
652 652 acl: path access granted: "ef1ea85a6374"
653 653 acl: branch access granted: "f9cafe1212c8" on branch "default"
654 654 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
655 655 bundle2-input-part: total payload size 1553
656 656 bundle2-input-part: total payload size 24
657 657 bundle2-input-bundle: 5 parts total
658 658 transaction abort!
659 659 rollback completed
660 660 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
661 661 no rollback information available
662 662 0:6675d58eff77
663 663
664 664
665 665 $ echo 'barney is not mentioned => not allowed anywhere'
666 666 barney is not mentioned => not allowed anywhere
667 667 $ do_push barney
668 668 Pushing as user barney
669 669 hgrc = """
670 670 [hooks]
671 671 pretxnchangegroup.acl = python:hgext.acl.hook
672 672 prepushkey.acl = python:hgext.acl.hook
673 673 [acl]
674 674 sources = push
675 675 [acl.allow]
676 676 foo/** = fred
677 677 [acl.deny]
678 678 foo/bar/** = fred
679 679 foo/Bar/** = fred
680 680 """
681 681 pushing to ../b
682 682 query 1; heads
683 683 searching for changes
684 684 all remote heads known locally
685 685 listing keys for "phases"
686 686 checking for updated bookmarks
687 687 listing keys for "bookmarks"
688 688 invalid branch cache (served): tip differs
689 689 listing keys for "bookmarks"
690 690 3 changesets found
691 691 list of changesets:
692 692 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
693 693 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
694 694 911600dab2ae7a9baff75958b84fe606851ce955
695 695 bundle2-output-bundle: "HG20", 5 parts total
696 bundle2-output-part: "replycaps" 224 bytes payload
696 bundle2-output-part: "replycaps" 207 bytes payload
697 697 bundle2-output-part: "check:phases" 24 bytes payload
698 698 bundle2-output-part: "check:updated-heads" streamed payload
699 699 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
700 700 bundle2-output-part: "phase-heads" 24 bytes payload
701 701 bundle2-input-bundle: with-transaction
702 702 bundle2-input-part: "replycaps" supported
703 bundle2-input-part: total payload size 224
703 bundle2-input-part: total payload size 207
704 704 bundle2-input-part: "check:phases" supported
705 705 bundle2-input-part: total payload size 24
706 706 bundle2-input-part: "check:updated-heads" supported
707 707 bundle2-input-part: total payload size 20
708 708 invalid branch cache (served): tip differs
709 709 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
710 710 adding changesets
711 711 add changeset ef1ea85a6374
712 712 add changeset f9cafe1212c8
713 713 add changeset 911600dab2ae
714 714 adding manifests
715 715 adding file changes
716 716 adding foo/Bar/file.txt revisions
717 717 adding foo/file.txt revisions
718 718 adding quux/file.py revisions
719 719 calling hook pretxnchangegroup.acl: hgext.acl.hook
720 720 acl: checking access for user "barney"
721 721 acl: acl.allow.branches not enabled
722 722 acl: acl.deny.branches not enabled
723 723 acl: acl.allow enabled, 0 entries for user barney
724 724 acl: acl.deny enabled, 0 entries for user barney
725 725 acl: branch access granted: "ef1ea85a6374" on branch "default"
726 726 error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
727 727 bundle2-input-part: total payload size 1553
728 728 bundle2-input-part: total payload size 24
729 729 bundle2-input-bundle: 5 parts total
730 730 transaction abort!
731 731 rollback completed
732 732 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
733 733 no rollback information available
734 734 0:6675d58eff77
735 735
736 736
737 737 fred is not blocked from moving bookmarks
738 738
739 739 $ hg -R a book -q moving-bookmark -r 1
740 740 $ hg -R b book -q moving-bookmark -r 0
741 741 $ cp $config normalconfig
742 742 $ do_push fred -r 1
743 743 Pushing as user fred
744 744 hgrc = """
745 745 [hooks]
746 746 pretxnchangegroup.acl = python:hgext.acl.hook
747 747 prepushkey.acl = python:hgext.acl.hook
748 748 [acl]
749 749 sources = push
750 750 [acl.allow]
751 751 foo/** = fred
752 752 [acl.deny]
753 753 foo/bar/** = fred
754 754 foo/Bar/** = fred
755 755 """
756 756 pushing to ../b
757 757 query 1; heads
758 758 searching for changes
759 759 all remote heads known locally
760 760 listing keys for "phases"
761 761 checking for updated bookmarks
762 762 listing keys for "bookmarks"
763 763 invalid branch cache (served): tip differs
764 764 listing keys for "bookmarks"
765 765 1 changesets found
766 766 list of changesets:
767 767 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
768 768 bundle2-output-bundle: "HG20", 7 parts total
769 bundle2-output-part: "replycaps" 224 bytes payload
769 bundle2-output-part: "replycaps" 207 bytes payload
770 770 bundle2-output-part: "check:bookmarks" 37 bytes payload
771 771 bundle2-output-part: "check:phases" 24 bytes payload
772 772 bundle2-output-part: "check:updated-heads" streamed payload
773 773 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
774 774 bundle2-output-part: "phase-heads" 24 bytes payload
775 775 bundle2-output-part: "bookmarks" 37 bytes payload
776 776 bundle2-input-bundle: with-transaction
777 777 bundle2-input-part: "replycaps" supported
778 bundle2-input-part: total payload size 224
778 bundle2-input-part: total payload size 207
779 779 bundle2-input-part: "check:bookmarks" supported
780 780 bundle2-input-part: total payload size 37
781 781 bundle2-input-part: "check:phases" supported
782 782 bundle2-input-part: total payload size 24
783 783 bundle2-input-part: "check:updated-heads" supported
784 784 bundle2-input-part: total payload size 20
785 785 invalid branch cache (served): tip differs
786 786 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
787 787 adding changesets
788 788 add changeset ef1ea85a6374
789 789 adding manifests
790 790 adding file changes
791 791 adding foo/file.txt revisions
792 792 calling hook pretxnchangegroup.acl: hgext.acl.hook
793 793 acl: checking access for user "fred"
794 794 acl: acl.allow.branches not enabled
795 795 acl: acl.deny.branches not enabled
796 796 acl: acl.allow enabled, 1 entries for user fred
797 797 acl: acl.deny enabled, 2 entries for user fred
798 798 acl: branch access granted: "ef1ea85a6374" on branch "default"
799 799 acl: path access granted: "ef1ea85a6374"
800 800 bundle2-input-part: total payload size 520
801 801 bundle2-input-part: "phase-heads" supported
802 802 bundle2-input-part: total payload size 24
803 803 bundle2-input-part: "bookmarks" supported
804 804 bundle2-input-part: total payload size 37
805 805 calling hook prepushkey.acl: hgext.acl.hook
806 806 acl: checking access for user "fred"
807 807 acl: acl.allow.bookmarks not enabled
808 808 acl: acl.deny.bookmarks not enabled
809 809 acl: bookmark access granted: "ef1ea85a6374b77d6da9dcda9541f498f2d17df7" on bookmark "moving-bookmark"
810 810 bundle2-input-bundle: 7 parts total
811 811 truncating cache/rbc-revs-v1 to 8
812 812 updating the branch cache
813 813 invalid branch cache (served.hidden): tip differs
814 814 added 1 changesets with 1 changes to 1 files
815 815 bundle2-output-bundle: "HG20", 1 parts total
816 816 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
817 817 bundle2-input-bundle: no-transaction
818 818 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
819 819 bundle2-input-bundle: 1 parts total
820 820 updating bookmark moving-bookmark
821 821 listing keys for "phases"
822 822 repository tip rolled back to revision 0 (undo push)
823 823 0:6675d58eff77
824 824
825 825
826 826 fred is not allowed to move bookmarks
827 827
828 828 $ echo '[acl.deny.bookmarks]' >> $config
829 829 $ echo '* = fred' >> $config
830 830 $ do_push fred -r 1
831 831 Pushing as user fred
832 832 hgrc = """
833 833 [hooks]
834 834 pretxnchangegroup.acl = python:hgext.acl.hook
835 835 prepushkey.acl = python:hgext.acl.hook
836 836 [acl]
837 837 sources = push
838 838 [acl.allow]
839 839 foo/** = fred
840 840 [acl.deny]
841 841 foo/bar/** = fred
842 842 foo/Bar/** = fred
843 843 [acl.deny.bookmarks]
844 844 * = fred
845 845 """
846 846 pushing to ../b
847 847 query 1; heads
848 848 searching for changes
849 849 all remote heads known locally
850 850 listing keys for "phases"
851 851 checking for updated bookmarks
852 852 listing keys for "bookmarks"
853 853 invalid branch cache (served): tip differs
854 854 listing keys for "bookmarks"
855 855 1 changesets found
856 856 list of changesets:
857 857 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
858 858 bundle2-output-bundle: "HG20", 7 parts total
859 bundle2-output-part: "replycaps" 224 bytes payload
859 bundle2-output-part: "replycaps" 207 bytes payload
860 860 bundle2-output-part: "check:bookmarks" 37 bytes payload
861 861 bundle2-output-part: "check:phases" 24 bytes payload
862 862 bundle2-output-part: "check:updated-heads" streamed payload
863 863 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
864 864 bundle2-output-part: "phase-heads" 24 bytes payload
865 865 bundle2-output-part: "bookmarks" 37 bytes payload
866 866 bundle2-input-bundle: with-transaction
867 867 bundle2-input-part: "replycaps" supported
868 bundle2-input-part: total payload size 224
868 bundle2-input-part: total payload size 207
869 869 bundle2-input-part: "check:bookmarks" supported
870 870 bundle2-input-part: total payload size 37
871 871 bundle2-input-part: "check:phases" supported
872 872 bundle2-input-part: total payload size 24
873 873 bundle2-input-part: "check:updated-heads" supported
874 874 bundle2-input-part: total payload size 20
875 875 invalid branch cache (served): tip differs
876 876 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
877 877 adding changesets
878 878 add changeset ef1ea85a6374
879 879 adding manifests
880 880 adding file changes
881 881 adding foo/file.txt revisions
882 882 calling hook pretxnchangegroup.acl: hgext.acl.hook
883 883 acl: checking access for user "fred"
884 884 acl: acl.allow.branches not enabled
885 885 acl: acl.deny.branches not enabled
886 886 acl: acl.allow enabled, 1 entries for user fred
887 887 acl: acl.deny enabled, 2 entries for user fred
888 888 acl: branch access granted: "ef1ea85a6374" on branch "default"
889 889 acl: path access granted: "ef1ea85a6374"
890 890 bundle2-input-part: total payload size 520
891 891 bundle2-input-part: "phase-heads" supported
892 892 bundle2-input-part: total payload size 24
893 893 bundle2-input-part: "bookmarks" supported
894 894 bundle2-input-part: total payload size 37
895 895 calling hook prepushkey.acl: hgext.acl.hook
896 896 acl: checking access for user "fred"
897 897 acl: acl.allow.bookmarks not enabled
898 898 acl: acl.deny.bookmarks enabled, 1 entries for user fred
899 899 error: prepushkey.acl hook failed: acl: user "fred" denied on bookmark "moving-bookmark" (changeset "ef1ea85a6374b77d6da9dcda9541f498f2d17df7")
900 900 bundle2-input-bundle: 7 parts total
901 901 transaction abort!
902 902 rollback completed
903 903 abort: acl: user "fred" denied on bookmark "moving-bookmark" (changeset "ef1ea85a6374b77d6da9dcda9541f498f2d17df7")
904 904 no rollback information available
905 905 0:6675d58eff77
906 906
907 907
908 908 cleanup bookmark stuff
909 909
910 910 $ hg book -R a -d moving-bookmark
911 911 $ hg book -R b -d moving-bookmark
912 912 $ cp normalconfig $config
913 913
914 914 barney is allowed everywhere
915 915
916 916 $ echo '[acl.allow]' >> $config
917 917 $ echo '** = barney' >> $config
918 918 $ do_push barney
919 919 Pushing as user barney
920 920 hgrc = """
921 921 [hooks]
922 922 pretxnchangegroup.acl = python:hgext.acl.hook
923 923 prepushkey.acl = python:hgext.acl.hook
924 924 [acl]
925 925 sources = push
926 926 [acl.allow]
927 927 foo/** = fred
928 928 [acl.deny]
929 929 foo/bar/** = fred
930 930 foo/Bar/** = fred
931 931 [acl.allow]
932 932 ** = barney
933 933 """
934 934 pushing to ../b
935 935 query 1; heads
936 936 searching for changes
937 937 all remote heads known locally
938 938 listing keys for "phases"
939 939 checking for updated bookmarks
940 940 listing keys for "bookmarks"
941 941 invalid branch cache (served): tip differs
942 942 listing keys for "bookmarks"
943 943 3 changesets found
944 944 list of changesets:
945 945 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
946 946 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
947 947 911600dab2ae7a9baff75958b84fe606851ce955
948 948 bundle2-output-bundle: "HG20", 5 parts total
949 bundle2-output-part: "replycaps" 224 bytes payload
949 bundle2-output-part: "replycaps" 207 bytes payload
950 950 bundle2-output-part: "check:phases" 24 bytes payload
951 951 bundle2-output-part: "check:updated-heads" streamed payload
952 952 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
953 953 bundle2-output-part: "phase-heads" 24 bytes payload
954 954 bundle2-input-bundle: with-transaction
955 955 bundle2-input-part: "replycaps" supported
956 bundle2-input-part: total payload size 224
956 bundle2-input-part: total payload size 207
957 957 bundle2-input-part: "check:phases" supported
958 958 bundle2-input-part: total payload size 24
959 959 bundle2-input-part: "check:updated-heads" supported
960 960 bundle2-input-part: total payload size 20
961 961 invalid branch cache (served): tip differs
962 962 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
963 963 adding changesets
964 964 add changeset ef1ea85a6374
965 965 add changeset f9cafe1212c8
966 966 add changeset 911600dab2ae
967 967 adding manifests
968 968 adding file changes
969 969 adding foo/Bar/file.txt revisions
970 970 adding foo/file.txt revisions
971 971 adding quux/file.py revisions
972 972 calling hook pretxnchangegroup.acl: hgext.acl.hook
973 973 acl: checking access for user "barney"
974 974 acl: acl.allow.branches not enabled
975 975 acl: acl.deny.branches not enabled
976 976 acl: acl.allow enabled, 1 entries for user barney
977 977 acl: acl.deny enabled, 0 entries for user barney
978 978 acl: branch access granted: "ef1ea85a6374" on branch "default"
979 979 acl: path access granted: "ef1ea85a6374"
980 980 acl: branch access granted: "f9cafe1212c8" on branch "default"
981 981 acl: path access granted: "f9cafe1212c8"
982 982 acl: branch access granted: "911600dab2ae" on branch "default"
983 983 acl: path access granted: "911600dab2ae"
984 984 bundle2-input-part: total payload size 1553
985 985 bundle2-input-part: "phase-heads" supported
986 986 bundle2-input-part: total payload size 24
987 987 bundle2-input-bundle: 5 parts total
988 988 truncating cache/rbc-revs-v1 to 8
989 989 updating the branch cache
990 990 added 3 changesets with 3 changes to 3 files
991 991 bundle2-output-bundle: "HG20", 1 parts total
992 992 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
993 993 bundle2-input-bundle: no-transaction
994 994 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
995 995 bundle2-input-bundle: 1 parts total
996 996 listing keys for "phases"
997 997 repository tip rolled back to revision 0 (undo push)
998 998 0:6675d58eff77
999 999
1000 1000
1001 1001 wilma can change files with a .txt extension
1002 1002
1003 1003 $ echo '**/*.txt = wilma' >> $config
1004 1004 $ do_push wilma
1005 1005 Pushing as user wilma
1006 1006 hgrc = """
1007 1007 [hooks]
1008 1008 pretxnchangegroup.acl = python:hgext.acl.hook
1009 1009 prepushkey.acl = python:hgext.acl.hook
1010 1010 [acl]
1011 1011 sources = push
1012 1012 [acl.allow]
1013 1013 foo/** = fred
1014 1014 [acl.deny]
1015 1015 foo/bar/** = fred
1016 1016 foo/Bar/** = fred
1017 1017 [acl.allow]
1018 1018 ** = barney
1019 1019 **/*.txt = wilma
1020 1020 """
1021 1021 pushing to ../b
1022 1022 query 1; heads
1023 1023 searching for changes
1024 1024 all remote heads known locally
1025 1025 listing keys for "phases"
1026 1026 checking for updated bookmarks
1027 1027 listing keys for "bookmarks"
1028 1028 invalid branch cache (served): tip differs
1029 1029 listing keys for "bookmarks"
1030 1030 3 changesets found
1031 1031 list of changesets:
1032 1032 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1033 1033 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1034 1034 911600dab2ae7a9baff75958b84fe606851ce955
1035 1035 bundle2-output-bundle: "HG20", 5 parts total
1036 bundle2-output-part: "replycaps" 224 bytes payload
1036 bundle2-output-part: "replycaps" 207 bytes payload
1037 1037 bundle2-output-part: "check:phases" 24 bytes payload
1038 1038 bundle2-output-part: "check:updated-heads" streamed payload
1039 1039 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1040 1040 bundle2-output-part: "phase-heads" 24 bytes payload
1041 1041 bundle2-input-bundle: with-transaction
1042 1042 bundle2-input-part: "replycaps" supported
1043 bundle2-input-part: total payload size 224
1043 bundle2-input-part: total payload size 207
1044 1044 bundle2-input-part: "check:phases" supported
1045 1045 bundle2-input-part: total payload size 24
1046 1046 bundle2-input-part: "check:updated-heads" supported
1047 1047 bundle2-input-part: total payload size 20
1048 1048 invalid branch cache (served): tip differs
1049 1049 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1050 1050 adding changesets
1051 1051 add changeset ef1ea85a6374
1052 1052 add changeset f9cafe1212c8
1053 1053 add changeset 911600dab2ae
1054 1054 adding manifests
1055 1055 adding file changes
1056 1056 adding foo/Bar/file.txt revisions
1057 1057 adding foo/file.txt revisions
1058 1058 adding quux/file.py revisions
1059 1059 calling hook pretxnchangegroup.acl: hgext.acl.hook
1060 1060 acl: checking access for user "wilma"
1061 1061 acl: acl.allow.branches not enabled
1062 1062 acl: acl.deny.branches not enabled
1063 1063 acl: acl.allow enabled, 1 entries for user wilma
1064 1064 acl: acl.deny enabled, 0 entries for user wilma
1065 1065 acl: branch access granted: "ef1ea85a6374" on branch "default"
1066 1066 acl: path access granted: "ef1ea85a6374"
1067 1067 acl: branch access granted: "f9cafe1212c8" on branch "default"
1068 1068 acl: path access granted: "f9cafe1212c8"
1069 1069 acl: branch access granted: "911600dab2ae" on branch "default"
1070 1070 error: pretxnchangegroup.acl hook failed: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
1071 1071 bundle2-input-part: total payload size 1553
1072 1072 bundle2-input-part: total payload size 24
1073 1073 bundle2-input-bundle: 5 parts total
1074 1074 transaction abort!
1075 1075 rollback completed
1076 1076 abort: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
1077 1077 no rollback information available
1078 1078 0:6675d58eff77
1079 1079
1080 1080
1081 1081 file specified by acl.config does not exist
1082 1082
1083 1083 $ echo '[acl]' >> $config
1084 1084 $ echo 'config = ../acl.config' >> $config
1085 1085 $ do_push barney
1086 1086 Pushing as user barney
1087 1087 hgrc = """
1088 1088 [hooks]
1089 1089 pretxnchangegroup.acl = python:hgext.acl.hook
1090 1090 prepushkey.acl = python:hgext.acl.hook
1091 1091 [acl]
1092 1092 sources = push
1093 1093 [acl.allow]
1094 1094 foo/** = fred
1095 1095 [acl.deny]
1096 1096 foo/bar/** = fred
1097 1097 foo/Bar/** = fred
1098 1098 [acl.allow]
1099 1099 ** = barney
1100 1100 **/*.txt = wilma
1101 1101 [acl]
1102 1102 config = ../acl.config
1103 1103 """
1104 1104 pushing to ../b
1105 1105 query 1; heads
1106 1106 searching for changes
1107 1107 all remote heads known locally
1108 1108 listing keys for "phases"
1109 1109 checking for updated bookmarks
1110 1110 listing keys for "bookmarks"
1111 1111 invalid branch cache (served): tip differs
1112 1112 listing keys for "bookmarks"
1113 1113 3 changesets found
1114 1114 list of changesets:
1115 1115 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1116 1116 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1117 1117 911600dab2ae7a9baff75958b84fe606851ce955
1118 1118 bundle2-output-bundle: "HG20", 5 parts total
1119 bundle2-output-part: "replycaps" 224 bytes payload
1119 bundle2-output-part: "replycaps" 207 bytes payload
1120 1120 bundle2-output-part: "check:phases" 24 bytes payload
1121 1121 bundle2-output-part: "check:updated-heads" streamed payload
1122 1122 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1123 1123 bundle2-output-part: "phase-heads" 24 bytes payload
1124 1124 bundle2-input-bundle: with-transaction
1125 1125 bundle2-input-part: "replycaps" supported
1126 bundle2-input-part: total payload size 224
1126 bundle2-input-part: total payload size 207
1127 1127 bundle2-input-part: "check:phases" supported
1128 1128 bundle2-input-part: total payload size 24
1129 1129 bundle2-input-part: "check:updated-heads" supported
1130 1130 bundle2-input-part: total payload size 20
1131 1131 invalid branch cache (served): tip differs
1132 1132 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1133 1133 adding changesets
1134 1134 add changeset ef1ea85a6374
1135 1135 add changeset f9cafe1212c8
1136 1136 add changeset 911600dab2ae
1137 1137 adding manifests
1138 1138 adding file changes
1139 1139 adding foo/Bar/file.txt revisions
1140 1140 adding foo/file.txt revisions
1141 1141 adding quux/file.py revisions
1142 1142 calling hook pretxnchangegroup.acl: hgext.acl.hook
1143 1143 acl: checking access for user "barney"
1144 1144 error: pretxnchangegroup.acl hook raised an exception: [Errno *] * (glob)
1145 1145 bundle2-input-part: total payload size 1553
1146 1146 bundle2-input-part: total payload size 24
1147 1147 bundle2-input-bundle: 5 parts total
1148 1148 transaction abort!
1149 1149 rollback completed
1150 1150 abort: $ENOENT$: '../acl.config'
1151 1151 no rollback information available
1152 1152 0:6675d58eff77
1153 1153
1154 1154
1155 1155 betty is allowed inside foo/ by a acl.config file
1156 1156
1157 1157 $ echo '[acl.allow]' >> acl.config
1158 1158 $ echo 'foo/** = betty' >> acl.config
1159 1159 $ do_push betty
1160 1160 Pushing as user betty
1161 1161 hgrc = """
1162 1162 [hooks]
1163 1163 pretxnchangegroup.acl = python:hgext.acl.hook
1164 1164 prepushkey.acl = python:hgext.acl.hook
1165 1165 [acl]
1166 1166 sources = push
1167 1167 [acl.allow]
1168 1168 foo/** = fred
1169 1169 [acl.deny]
1170 1170 foo/bar/** = fred
1171 1171 foo/Bar/** = fred
1172 1172 [acl.allow]
1173 1173 ** = barney
1174 1174 **/*.txt = wilma
1175 1175 [acl]
1176 1176 config = ../acl.config
1177 1177 """
1178 1178 acl.config = """
1179 1179 [acl.allow]
1180 1180 foo/** = betty
1181 1181 """
1182 1182 pushing to ../b
1183 1183 query 1; heads
1184 1184 searching for changes
1185 1185 all remote heads known locally
1186 1186 listing keys for "phases"
1187 1187 checking for updated bookmarks
1188 1188 listing keys for "bookmarks"
1189 1189 invalid branch cache (served): tip differs
1190 1190 listing keys for "bookmarks"
1191 1191 3 changesets found
1192 1192 list of changesets:
1193 1193 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1194 1194 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1195 1195 911600dab2ae7a9baff75958b84fe606851ce955
1196 1196 bundle2-output-bundle: "HG20", 5 parts total
1197 bundle2-output-part: "replycaps" 224 bytes payload
1197 bundle2-output-part: "replycaps" 207 bytes payload
1198 1198 bundle2-output-part: "check:phases" 24 bytes payload
1199 1199 bundle2-output-part: "check:updated-heads" streamed payload
1200 1200 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1201 1201 bundle2-output-part: "phase-heads" 24 bytes payload
1202 1202 bundle2-input-bundle: with-transaction
1203 1203 bundle2-input-part: "replycaps" supported
1204 bundle2-input-part: total payload size 224
1204 bundle2-input-part: total payload size 207
1205 1205 bundle2-input-part: "check:phases" supported
1206 1206 bundle2-input-part: total payload size 24
1207 1207 bundle2-input-part: "check:updated-heads" supported
1208 1208 bundle2-input-part: total payload size 20
1209 1209 invalid branch cache (served): tip differs
1210 1210 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1211 1211 adding changesets
1212 1212 add changeset ef1ea85a6374
1213 1213 add changeset f9cafe1212c8
1214 1214 add changeset 911600dab2ae
1215 1215 adding manifests
1216 1216 adding file changes
1217 1217 adding foo/Bar/file.txt revisions
1218 1218 adding foo/file.txt revisions
1219 1219 adding quux/file.py revisions
1220 1220 calling hook pretxnchangegroup.acl: hgext.acl.hook
1221 1221 acl: checking access for user "betty"
1222 1222 acl: acl.allow.branches not enabled
1223 1223 acl: acl.deny.branches not enabled
1224 1224 acl: acl.allow enabled, 1 entries for user betty
1225 1225 acl: acl.deny enabled, 0 entries for user betty
1226 1226 acl: branch access granted: "ef1ea85a6374" on branch "default"
1227 1227 acl: path access granted: "ef1ea85a6374"
1228 1228 acl: branch access granted: "f9cafe1212c8" on branch "default"
1229 1229 acl: path access granted: "f9cafe1212c8"
1230 1230 acl: branch access granted: "911600dab2ae" on branch "default"
1231 1231 error: pretxnchangegroup.acl hook failed: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
1232 1232 bundle2-input-part: total payload size 1553
1233 1233 bundle2-input-part: total payload size 24
1234 1234 bundle2-input-bundle: 5 parts total
1235 1235 transaction abort!
1236 1236 rollback completed
1237 1237 abort: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
1238 1238 no rollback information available
1239 1239 0:6675d58eff77
1240 1240
1241 1241
1242 1242 acl.config can set only [acl.allow]/[acl.deny]
1243 1243
1244 1244 $ echo '[hooks]' >> acl.config
1245 1245 $ echo 'changegroup.acl = false' >> acl.config
1246 1246 $ do_push barney
1247 1247 Pushing as user barney
1248 1248 hgrc = """
1249 1249 [hooks]
1250 1250 pretxnchangegroup.acl = python:hgext.acl.hook
1251 1251 prepushkey.acl = python:hgext.acl.hook
1252 1252 [acl]
1253 1253 sources = push
1254 1254 [acl.allow]
1255 1255 foo/** = fred
1256 1256 [acl.deny]
1257 1257 foo/bar/** = fred
1258 1258 foo/Bar/** = fred
1259 1259 [acl.allow]
1260 1260 ** = barney
1261 1261 **/*.txt = wilma
1262 1262 [acl]
1263 1263 config = ../acl.config
1264 1264 """
1265 1265 acl.config = """
1266 1266 [acl.allow]
1267 1267 foo/** = betty
1268 1268 [hooks]
1269 1269 changegroup.acl = false
1270 1270 """
1271 1271 pushing to ../b
1272 1272 query 1; heads
1273 1273 searching for changes
1274 1274 all remote heads known locally
1275 1275 listing keys for "phases"
1276 1276 checking for updated bookmarks
1277 1277 listing keys for "bookmarks"
1278 1278 invalid branch cache (served): tip differs
1279 1279 listing keys for "bookmarks"
1280 1280 3 changesets found
1281 1281 list of changesets:
1282 1282 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1283 1283 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1284 1284 911600dab2ae7a9baff75958b84fe606851ce955
1285 1285 bundle2-output-bundle: "HG20", 5 parts total
1286 bundle2-output-part: "replycaps" 224 bytes payload
1286 bundle2-output-part: "replycaps" 207 bytes payload
1287 1287 bundle2-output-part: "check:phases" 24 bytes payload
1288 1288 bundle2-output-part: "check:updated-heads" streamed payload
1289 1289 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1290 1290 bundle2-output-part: "phase-heads" 24 bytes payload
1291 1291 bundle2-input-bundle: with-transaction
1292 1292 bundle2-input-part: "replycaps" supported
1293 bundle2-input-part: total payload size 224
1293 bundle2-input-part: total payload size 207
1294 1294 bundle2-input-part: "check:phases" supported
1295 1295 bundle2-input-part: total payload size 24
1296 1296 bundle2-input-part: "check:updated-heads" supported
1297 1297 bundle2-input-part: total payload size 20
1298 1298 invalid branch cache (served): tip differs
1299 1299 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1300 1300 adding changesets
1301 1301 add changeset ef1ea85a6374
1302 1302 add changeset f9cafe1212c8
1303 1303 add changeset 911600dab2ae
1304 1304 adding manifests
1305 1305 adding file changes
1306 1306 adding foo/Bar/file.txt revisions
1307 1307 adding foo/file.txt revisions
1308 1308 adding quux/file.py revisions
1309 1309 calling hook pretxnchangegroup.acl: hgext.acl.hook
1310 1310 acl: checking access for user "barney"
1311 1311 acl: acl.allow.branches not enabled
1312 1312 acl: acl.deny.branches not enabled
1313 1313 acl: acl.allow enabled, 1 entries for user barney
1314 1314 acl: acl.deny enabled, 0 entries for user barney
1315 1315 acl: branch access granted: "ef1ea85a6374" on branch "default"
1316 1316 acl: path access granted: "ef1ea85a6374"
1317 1317 acl: branch access granted: "f9cafe1212c8" on branch "default"
1318 1318 acl: path access granted: "f9cafe1212c8"
1319 1319 acl: branch access granted: "911600dab2ae" on branch "default"
1320 1320 acl: path access granted: "911600dab2ae"
1321 1321 bundle2-input-part: total payload size 1553
1322 1322 bundle2-input-part: "phase-heads" supported
1323 1323 bundle2-input-part: total payload size 24
1324 1324 bundle2-input-bundle: 5 parts total
1325 1325 truncating cache/rbc-revs-v1 to 8
1326 1326 updating the branch cache
1327 1327 added 3 changesets with 3 changes to 3 files
1328 1328 bundle2-output-bundle: "HG20", 1 parts total
1329 1329 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1330 1330 bundle2-input-bundle: no-transaction
1331 1331 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1332 1332 bundle2-input-bundle: 1 parts total
1333 1333 listing keys for "phases"
1334 1334 repository tip rolled back to revision 0 (undo push)
1335 1335 0:6675d58eff77
1336 1336
1337 1337
1338 1338 asterisk
1339 1339
1340 1340 $ init_config
1341 1341
1342 1342 asterisk test
1343 1343
1344 1344 $ echo '[acl.allow]' >> $config
1345 1345 $ echo "** = fred" >> $config
1346 1346
1347 1347 fred is always allowed
1348 1348
1349 1349 $ do_push fred
1350 1350 Pushing as user fred
1351 1351 hgrc = """
1352 1352 [hooks]
1353 1353 pretxnchangegroup.acl = python:hgext.acl.hook
1354 1354 prepushkey.acl = python:hgext.acl.hook
1355 1355 [acl]
1356 1356 sources = push
1357 1357 [extensions]
1358 1358 posixgetuser=$TESTTMP/posixgetuser.py
1359 1359 [acl.allow]
1360 1360 ** = fred
1361 1361 """
1362 1362 pushing to ../b
1363 1363 query 1; heads
1364 1364 searching for changes
1365 1365 all remote heads known locally
1366 1366 listing keys for "phases"
1367 1367 checking for updated bookmarks
1368 1368 listing keys for "bookmarks"
1369 1369 invalid branch cache (served): tip differs
1370 1370 listing keys for "bookmarks"
1371 1371 3 changesets found
1372 1372 list of changesets:
1373 1373 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1374 1374 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1375 1375 911600dab2ae7a9baff75958b84fe606851ce955
1376 1376 bundle2-output-bundle: "HG20", 5 parts total
1377 bundle2-output-part: "replycaps" 224 bytes payload
1377 bundle2-output-part: "replycaps" 207 bytes payload
1378 1378 bundle2-output-part: "check:phases" 24 bytes payload
1379 1379 bundle2-output-part: "check:updated-heads" streamed payload
1380 1380 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1381 1381 bundle2-output-part: "phase-heads" 24 bytes payload
1382 1382 bundle2-input-bundle: with-transaction
1383 1383 bundle2-input-part: "replycaps" supported
1384 bundle2-input-part: total payload size 224
1384 bundle2-input-part: total payload size 207
1385 1385 bundle2-input-part: "check:phases" supported
1386 1386 bundle2-input-part: total payload size 24
1387 1387 bundle2-input-part: "check:updated-heads" supported
1388 1388 bundle2-input-part: total payload size 20
1389 1389 invalid branch cache (served): tip differs
1390 1390 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1391 1391 adding changesets
1392 1392 add changeset ef1ea85a6374
1393 1393 add changeset f9cafe1212c8
1394 1394 add changeset 911600dab2ae
1395 1395 adding manifests
1396 1396 adding file changes
1397 1397 adding foo/Bar/file.txt revisions
1398 1398 adding foo/file.txt revisions
1399 1399 adding quux/file.py revisions
1400 1400 calling hook pretxnchangegroup.acl: hgext.acl.hook
1401 1401 acl: checking access for user "fred"
1402 1402 acl: acl.allow.branches not enabled
1403 1403 acl: acl.deny.branches not enabled
1404 1404 acl: acl.allow enabled, 1 entries for user fred
1405 1405 acl: acl.deny not enabled
1406 1406 acl: branch access granted: "ef1ea85a6374" on branch "default"
1407 1407 acl: path access granted: "ef1ea85a6374"
1408 1408 acl: branch access granted: "f9cafe1212c8" on branch "default"
1409 1409 acl: path access granted: "f9cafe1212c8"
1410 1410 acl: branch access granted: "911600dab2ae" on branch "default"
1411 1411 acl: path access granted: "911600dab2ae"
1412 1412 bundle2-input-part: total payload size 1553
1413 1413 bundle2-input-part: "phase-heads" supported
1414 1414 bundle2-input-part: total payload size 24
1415 1415 bundle2-input-bundle: 5 parts total
1416 1416 truncating cache/rbc-revs-v1 to 8
1417 1417 updating the branch cache
1418 1418 added 3 changesets with 3 changes to 3 files
1419 1419 bundle2-output-bundle: "HG20", 1 parts total
1420 1420 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1421 1421 bundle2-input-bundle: no-transaction
1422 1422 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1423 1423 bundle2-input-bundle: 1 parts total
1424 1424 listing keys for "phases"
1425 1425 repository tip rolled back to revision 0 (undo push)
1426 1426 0:6675d58eff77
1427 1427
1428 1428
1429 1429 $ echo '[acl.deny]' >> $config
1430 1430 $ echo "foo/Bar/** = *" >> $config
1431 1431
1432 1432 no one is allowed inside foo/Bar/
1433 1433
1434 1434 $ do_push fred
1435 1435 Pushing as user fred
1436 1436 hgrc = """
1437 1437 [hooks]
1438 1438 pretxnchangegroup.acl = python:hgext.acl.hook
1439 1439 prepushkey.acl = python:hgext.acl.hook
1440 1440 [acl]
1441 1441 sources = push
1442 1442 [extensions]
1443 1443 posixgetuser=$TESTTMP/posixgetuser.py
1444 1444 [acl.allow]
1445 1445 ** = fred
1446 1446 [acl.deny]
1447 1447 foo/Bar/** = *
1448 1448 """
1449 1449 pushing to ../b
1450 1450 query 1; heads
1451 1451 searching for changes
1452 1452 all remote heads known locally
1453 1453 listing keys for "phases"
1454 1454 checking for updated bookmarks
1455 1455 listing keys for "bookmarks"
1456 1456 invalid branch cache (served): tip differs
1457 1457 listing keys for "bookmarks"
1458 1458 3 changesets found
1459 1459 list of changesets:
1460 1460 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1461 1461 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1462 1462 911600dab2ae7a9baff75958b84fe606851ce955
1463 1463 bundle2-output-bundle: "HG20", 5 parts total
1464 bundle2-output-part: "replycaps" 224 bytes payload
1464 bundle2-output-part: "replycaps" 207 bytes payload
1465 1465 bundle2-output-part: "check:phases" 24 bytes payload
1466 1466 bundle2-output-part: "check:updated-heads" streamed payload
1467 1467 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1468 1468 bundle2-output-part: "phase-heads" 24 bytes payload
1469 1469 bundle2-input-bundle: with-transaction
1470 1470 bundle2-input-part: "replycaps" supported
1471 bundle2-input-part: total payload size 224
1471 bundle2-input-part: total payload size 207
1472 1472 bundle2-input-part: "check:phases" supported
1473 1473 bundle2-input-part: total payload size 24
1474 1474 bundle2-input-part: "check:updated-heads" supported
1475 1475 bundle2-input-part: total payload size 20
1476 1476 invalid branch cache (served): tip differs
1477 1477 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1478 1478 adding changesets
1479 1479 add changeset ef1ea85a6374
1480 1480 add changeset f9cafe1212c8
1481 1481 add changeset 911600dab2ae
1482 1482 adding manifests
1483 1483 adding file changes
1484 1484 adding foo/Bar/file.txt revisions
1485 1485 adding foo/file.txt revisions
1486 1486 adding quux/file.py revisions
1487 1487 calling hook pretxnchangegroup.acl: hgext.acl.hook
1488 1488 acl: checking access for user "fred"
1489 1489 acl: acl.allow.branches not enabled
1490 1490 acl: acl.deny.branches not enabled
1491 1491 acl: acl.allow enabled, 1 entries for user fred
1492 1492 acl: acl.deny enabled, 1 entries for user fred
1493 1493 acl: branch access granted: "ef1ea85a6374" on branch "default"
1494 1494 acl: path access granted: "ef1ea85a6374"
1495 1495 acl: branch access granted: "f9cafe1212c8" on branch "default"
1496 1496 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1497 1497 bundle2-input-part: total payload size 1553
1498 1498 bundle2-input-part: total payload size 24
1499 1499 bundle2-input-bundle: 5 parts total
1500 1500 transaction abort!
1501 1501 rollback completed
1502 1502 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1503 1503 no rollback information available
1504 1504 0:6675d58eff77
1505 1505
1506 1506
1507 1507 Groups
1508 1508
1509 1509 $ init_config
1510 1510
1511 1511 OS-level groups
1512 1512
1513 1513 $ echo '[acl.allow]' >> $config
1514 1514 $ echo "** = @group1" >> $config
1515 1515
1516 1516 @group1 is always allowed
1517 1517
1518 1518 $ do_push fred
1519 1519 Pushing as user fred
1520 1520 hgrc = """
1521 1521 [hooks]
1522 1522 pretxnchangegroup.acl = python:hgext.acl.hook
1523 1523 prepushkey.acl = python:hgext.acl.hook
1524 1524 [acl]
1525 1525 sources = push
1526 1526 [extensions]
1527 1527 posixgetuser=$TESTTMP/posixgetuser.py
1528 1528 [acl.allow]
1529 1529 ** = @group1
1530 1530 """
1531 1531 pushing to ../b
1532 1532 query 1; heads
1533 1533 searching for changes
1534 1534 all remote heads known locally
1535 1535 listing keys for "phases"
1536 1536 checking for updated bookmarks
1537 1537 listing keys for "bookmarks"
1538 1538 invalid branch cache (served): tip differs
1539 1539 listing keys for "bookmarks"
1540 1540 3 changesets found
1541 1541 list of changesets:
1542 1542 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1543 1543 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1544 1544 911600dab2ae7a9baff75958b84fe606851ce955
1545 1545 bundle2-output-bundle: "HG20", 5 parts total
1546 bundle2-output-part: "replycaps" 224 bytes payload
1546 bundle2-output-part: "replycaps" 207 bytes payload
1547 1547 bundle2-output-part: "check:phases" 24 bytes payload
1548 1548 bundle2-output-part: "check:updated-heads" streamed payload
1549 1549 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1550 1550 bundle2-output-part: "phase-heads" 24 bytes payload
1551 1551 bundle2-input-bundle: with-transaction
1552 1552 bundle2-input-part: "replycaps" supported
1553 bundle2-input-part: total payload size 224
1553 bundle2-input-part: total payload size 207
1554 1554 bundle2-input-part: "check:phases" supported
1555 1555 bundle2-input-part: total payload size 24
1556 1556 bundle2-input-part: "check:updated-heads" supported
1557 1557 bundle2-input-part: total payload size 20
1558 1558 invalid branch cache (served): tip differs
1559 1559 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1560 1560 adding changesets
1561 1561 add changeset ef1ea85a6374
1562 1562 add changeset f9cafe1212c8
1563 1563 add changeset 911600dab2ae
1564 1564 adding manifests
1565 1565 adding file changes
1566 1566 adding foo/Bar/file.txt revisions
1567 1567 adding foo/file.txt revisions
1568 1568 adding quux/file.py revisions
1569 1569 calling hook pretxnchangegroup.acl: hgext.acl.hook
1570 1570 acl: checking access for user "fred"
1571 1571 acl: acl.allow.branches not enabled
1572 1572 acl: acl.deny.branches not enabled
1573 1573 acl: "group1" not defined in [acl.groups]
1574 1574 acl: acl.allow enabled, 1 entries for user fred
1575 1575 acl: acl.deny not enabled
1576 1576 acl: branch access granted: "ef1ea85a6374" on branch "default"
1577 1577 acl: path access granted: "ef1ea85a6374"
1578 1578 acl: branch access granted: "f9cafe1212c8" on branch "default"
1579 1579 acl: path access granted: "f9cafe1212c8"
1580 1580 acl: branch access granted: "911600dab2ae" on branch "default"
1581 1581 acl: path access granted: "911600dab2ae"
1582 1582 bundle2-input-part: total payload size 1553
1583 1583 bundle2-input-part: "phase-heads" supported
1584 1584 bundle2-input-part: total payload size 24
1585 1585 bundle2-input-bundle: 5 parts total
1586 1586 truncating cache/rbc-revs-v1 to 8
1587 1587 updating the branch cache
1588 1588 added 3 changesets with 3 changes to 3 files
1589 1589 bundle2-output-bundle: "HG20", 1 parts total
1590 1590 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1591 1591 bundle2-input-bundle: no-transaction
1592 1592 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1593 1593 bundle2-input-bundle: 1 parts total
1594 1594 listing keys for "phases"
1595 1595 repository tip rolled back to revision 0 (undo push)
1596 1596 0:6675d58eff77
1597 1597
1598 1598
1599 1599 $ echo '[acl.deny]' >> $config
1600 1600 $ echo "foo/Bar/** = @group1" >> $config
1601 1601
1602 1602 @group is allowed inside anything but foo/Bar/
1603 1603
1604 1604 $ do_push fred
1605 1605 Pushing as user fred
1606 1606 hgrc = """
1607 1607 [hooks]
1608 1608 pretxnchangegroup.acl = python:hgext.acl.hook
1609 1609 prepushkey.acl = python:hgext.acl.hook
1610 1610 [acl]
1611 1611 sources = push
1612 1612 [extensions]
1613 1613 posixgetuser=$TESTTMP/posixgetuser.py
1614 1614 [acl.allow]
1615 1615 ** = @group1
1616 1616 [acl.deny]
1617 1617 foo/Bar/** = @group1
1618 1618 """
1619 1619 pushing to ../b
1620 1620 query 1; heads
1621 1621 searching for changes
1622 1622 all remote heads known locally
1623 1623 listing keys for "phases"
1624 1624 checking for updated bookmarks
1625 1625 listing keys for "bookmarks"
1626 1626 invalid branch cache (served): tip differs
1627 1627 listing keys for "bookmarks"
1628 1628 3 changesets found
1629 1629 list of changesets:
1630 1630 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1631 1631 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1632 1632 911600dab2ae7a9baff75958b84fe606851ce955
1633 1633 bundle2-output-bundle: "HG20", 5 parts total
1634 bundle2-output-part: "replycaps" 224 bytes payload
1634 bundle2-output-part: "replycaps" 207 bytes payload
1635 1635 bundle2-output-part: "check:phases" 24 bytes payload
1636 1636 bundle2-output-part: "check:updated-heads" streamed payload
1637 1637 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1638 1638 bundle2-output-part: "phase-heads" 24 bytes payload
1639 1639 bundle2-input-bundle: with-transaction
1640 1640 bundle2-input-part: "replycaps" supported
1641 bundle2-input-part: total payload size 224
1641 bundle2-input-part: total payload size 207
1642 1642 bundle2-input-part: "check:phases" supported
1643 1643 bundle2-input-part: total payload size 24
1644 1644 bundle2-input-part: "check:updated-heads" supported
1645 1645 bundle2-input-part: total payload size 20
1646 1646 invalid branch cache (served): tip differs
1647 1647 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1648 1648 adding changesets
1649 1649 add changeset ef1ea85a6374
1650 1650 add changeset f9cafe1212c8
1651 1651 add changeset 911600dab2ae
1652 1652 adding manifests
1653 1653 adding file changes
1654 1654 adding foo/Bar/file.txt revisions
1655 1655 adding foo/file.txt revisions
1656 1656 adding quux/file.py revisions
1657 1657 calling hook pretxnchangegroup.acl: hgext.acl.hook
1658 1658 acl: checking access for user "fred"
1659 1659 acl: acl.allow.branches not enabled
1660 1660 acl: acl.deny.branches not enabled
1661 1661 acl: "group1" not defined in [acl.groups]
1662 1662 acl: acl.allow enabled, 1 entries for user fred
1663 1663 acl: "group1" not defined in [acl.groups]
1664 1664 acl: acl.deny enabled, 1 entries for user fred
1665 1665 acl: branch access granted: "ef1ea85a6374" on branch "default"
1666 1666 acl: path access granted: "ef1ea85a6374"
1667 1667 acl: branch access granted: "f9cafe1212c8" on branch "default"
1668 1668 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1669 1669 bundle2-input-part: total payload size 1553
1670 1670 bundle2-input-part: total payload size 24
1671 1671 bundle2-input-bundle: 5 parts total
1672 1672 transaction abort!
1673 1673 rollback completed
1674 1674 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1675 1675 no rollback information available
1676 1676 0:6675d58eff77
1677 1677
1678 1678
1679 1679 Invalid group
1680 1680
1681 1681 Disable the fakegroups trick to get real failures
1682 1682
1683 1683 $ grep -v fakegroups $config > config.tmp
1684 1684 $ mv config.tmp $config
1685 1685 $ echo '[acl.allow]' >> $config
1686 1686 $ echo "** = @unlikelytoexist" >> $config
1687 1687 $ do_push fred 2>&1 | grep unlikelytoexist
1688 1688 ** = @unlikelytoexist
1689 1689 acl: "unlikelytoexist" not defined in [acl.groups]
1690 1690 error: pretxnchangegroup.acl hook failed: group 'unlikelytoexist' is undefined
1691 1691 abort: group 'unlikelytoexist' is undefined
1692 1692
1693 1693
1694 1694 Branch acl tests setup
1695 1695
1696 1696 $ init_config
1697 1697 $ cd b
1698 1698 $ hg up
1699 1699 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1700 1700 $ hg branch foobar
1701 1701 marked working directory as branch foobar
1702 1702 (branches are permanent and global, did you want a bookmark?)
1703 1703 $ hg commit -m 'create foobar'
1704 1704 $ echo 'foo contents' > abc.txt
1705 1705 $ hg add abc.txt
1706 1706 $ hg commit -m 'foobar contents'
1707 1707 $ cd ..
1708 1708 $ hg --cwd a pull ../b
1709 1709 pulling from ../b
1710 1710 searching for changes
1711 1711 adding changesets
1712 1712 adding manifests
1713 1713 adding file changes
1714 1714 added 2 changesets with 1 changes to 1 files (+1 heads)
1715 1715 new changesets 81fbf4469322:fb35475503ef
1716 1716 (run 'hg heads' to see heads)
1717 1717
1718 1718 Create additional changeset on foobar branch
1719 1719
1720 1720 $ cd a
1721 1721 $ hg up -C foobar
1722 1722 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1723 1723 $ echo 'foo contents2' > abc.txt
1724 1724 $ hg commit -m 'foobar contents2'
1725 1725 $ cd ..
1726 1726
1727 1727
1728 1728 No branch acls specified
1729 1729
1730 1730 $ do_push astro
1731 1731 Pushing as user astro
1732 1732 hgrc = """
1733 1733 [hooks]
1734 1734 pretxnchangegroup.acl = python:hgext.acl.hook
1735 1735 prepushkey.acl = python:hgext.acl.hook
1736 1736 [acl]
1737 1737 sources = push
1738 1738 [extensions]
1739 1739 posixgetuser=$TESTTMP/posixgetuser.py
1740 1740 """
1741 1741 pushing to ../b
1742 1742 query 1; heads
1743 1743 searching for changes
1744 1744 all remote heads known locally
1745 1745 listing keys for "phases"
1746 1746 checking for updated bookmarks
1747 1747 listing keys for "bookmarks"
1748 1748 listing keys for "bookmarks"
1749 1749 4 changesets found
1750 1750 list of changesets:
1751 1751 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1752 1752 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1753 1753 911600dab2ae7a9baff75958b84fe606851ce955
1754 1754 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1755 1755 bundle2-output-bundle: "HG20", 5 parts total
1756 bundle2-output-part: "replycaps" 224 bytes payload
1756 bundle2-output-part: "replycaps" 207 bytes payload
1757 1757 bundle2-output-part: "check:phases" 48 bytes payload
1758 1758 bundle2-output-part: "check:updated-heads" streamed payload
1759 1759 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1760 1760 bundle2-output-part: "phase-heads" 48 bytes payload
1761 1761 bundle2-input-bundle: with-transaction
1762 1762 bundle2-input-part: "replycaps" supported
1763 bundle2-input-part: total payload size 224
1763 bundle2-input-part: total payload size 207
1764 1764 bundle2-input-part: "check:phases" supported
1765 1765 bundle2-input-part: total payload size 48
1766 1766 bundle2-input-part: "check:updated-heads" supported
1767 1767 bundle2-input-part: total payload size 40
1768 1768 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1769 1769 adding changesets
1770 1770 add changeset ef1ea85a6374
1771 1771 add changeset f9cafe1212c8
1772 1772 add changeset 911600dab2ae
1773 1773 add changeset e8fc755d4d82
1774 1774 adding manifests
1775 1775 adding file changes
1776 1776 adding abc.txt revisions
1777 1777 adding foo/Bar/file.txt revisions
1778 1778 adding foo/file.txt revisions
1779 1779 adding quux/file.py revisions
1780 1780 calling hook pretxnchangegroup.acl: hgext.acl.hook
1781 1781 acl: checking access for user "astro"
1782 1782 acl: acl.allow.branches not enabled
1783 1783 acl: acl.deny.branches not enabled
1784 1784 acl: acl.allow not enabled
1785 1785 acl: acl.deny not enabled
1786 1786 acl: branch access granted: "ef1ea85a6374" on branch "default"
1787 1787 acl: path access granted: "ef1ea85a6374"
1788 1788 acl: branch access granted: "f9cafe1212c8" on branch "default"
1789 1789 acl: path access granted: "f9cafe1212c8"
1790 1790 acl: branch access granted: "911600dab2ae" on branch "default"
1791 1791 acl: path access granted: "911600dab2ae"
1792 1792 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1793 1793 acl: path access granted: "e8fc755d4d82"
1794 1794 bundle2-input-part: total payload size 2068
1795 1795 bundle2-input-part: "phase-heads" supported
1796 1796 bundle2-input-part: total payload size 48
1797 1797 bundle2-input-bundle: 5 parts total
1798 1798 updating the branch cache
1799 1799 invalid branch cache (served.hidden): tip differs
1800 1800 added 4 changesets with 4 changes to 4 files (+1 heads)
1801 1801 bundle2-output-bundle: "HG20", 1 parts total
1802 1802 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
1803 1803 bundle2-input-bundle: no-transaction
1804 1804 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
1805 1805 bundle2-input-bundle: 1 parts total
1806 1806 listing keys for "phases"
1807 1807 repository tip rolled back to revision 2 (undo push)
1808 1808 2:fb35475503ef
1809 1809
1810 1810
1811 1811 Branch acl deny test
1812 1812
1813 1813 $ echo "[acl.deny.branches]" >> $config
1814 1814 $ echo "foobar = *" >> $config
1815 1815 $ do_push astro
1816 1816 Pushing as user astro
1817 1817 hgrc = """
1818 1818 [hooks]
1819 1819 pretxnchangegroup.acl = python:hgext.acl.hook
1820 1820 prepushkey.acl = python:hgext.acl.hook
1821 1821 [acl]
1822 1822 sources = push
1823 1823 [extensions]
1824 1824 posixgetuser=$TESTTMP/posixgetuser.py
1825 1825 [acl.deny.branches]
1826 1826 foobar = *
1827 1827 """
1828 1828 pushing to ../b
1829 1829 query 1; heads
1830 1830 searching for changes
1831 1831 all remote heads known locally
1832 1832 listing keys for "phases"
1833 1833 checking for updated bookmarks
1834 1834 listing keys for "bookmarks"
1835 1835 listing keys for "bookmarks"
1836 1836 4 changesets found
1837 1837 list of changesets:
1838 1838 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1839 1839 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1840 1840 911600dab2ae7a9baff75958b84fe606851ce955
1841 1841 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1842 1842 bundle2-output-bundle: "HG20", 5 parts total
1843 bundle2-output-part: "replycaps" 224 bytes payload
1843 bundle2-output-part: "replycaps" 207 bytes payload
1844 1844 bundle2-output-part: "check:phases" 48 bytes payload
1845 1845 bundle2-output-part: "check:updated-heads" streamed payload
1846 1846 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1847 1847 bundle2-output-part: "phase-heads" 48 bytes payload
1848 1848 bundle2-input-bundle: with-transaction
1849 1849 bundle2-input-part: "replycaps" supported
1850 bundle2-input-part: total payload size 224
1850 bundle2-input-part: total payload size 207
1851 1851 bundle2-input-part: "check:phases" supported
1852 1852 bundle2-input-part: total payload size 48
1853 1853 bundle2-input-part: "check:updated-heads" supported
1854 1854 bundle2-input-part: total payload size 40
1855 1855 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1856 1856 adding changesets
1857 1857 add changeset ef1ea85a6374
1858 1858 add changeset f9cafe1212c8
1859 1859 add changeset 911600dab2ae
1860 1860 add changeset e8fc755d4d82
1861 1861 adding manifests
1862 1862 adding file changes
1863 1863 adding abc.txt revisions
1864 1864 adding foo/Bar/file.txt revisions
1865 1865 adding foo/file.txt revisions
1866 1866 adding quux/file.py revisions
1867 1867 calling hook pretxnchangegroup.acl: hgext.acl.hook
1868 1868 acl: checking access for user "astro"
1869 1869 acl: acl.allow.branches not enabled
1870 1870 acl: acl.deny.branches enabled, 1 entries for user astro
1871 1871 acl: acl.allow not enabled
1872 1872 acl: acl.deny not enabled
1873 1873 acl: branch access granted: "ef1ea85a6374" on branch "default"
1874 1874 acl: path access granted: "ef1ea85a6374"
1875 1875 acl: branch access granted: "f9cafe1212c8" on branch "default"
1876 1876 acl: path access granted: "f9cafe1212c8"
1877 1877 acl: branch access granted: "911600dab2ae" on branch "default"
1878 1878 acl: path access granted: "911600dab2ae"
1879 1879 error: pretxnchangegroup.acl hook failed: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1880 1880 bundle2-input-part: total payload size 2068
1881 1881 bundle2-input-part: total payload size 48
1882 1882 bundle2-input-bundle: 5 parts total
1883 1883 transaction abort!
1884 1884 rollback completed
1885 1885 abort: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1886 1886 no rollback information available
1887 1887 2:fb35475503ef
1888 1888
1889 1889
1890 1890 Branch acl empty allow test
1891 1891
1892 1892 $ init_config
1893 1893 $ echo "[acl.allow.branches]" >> $config
1894 1894 $ do_push astro
1895 1895 Pushing as user astro
1896 1896 hgrc = """
1897 1897 [hooks]
1898 1898 pretxnchangegroup.acl = python:hgext.acl.hook
1899 1899 prepushkey.acl = python:hgext.acl.hook
1900 1900 [acl]
1901 1901 sources = push
1902 1902 [extensions]
1903 1903 posixgetuser=$TESTTMP/posixgetuser.py
1904 1904 [acl.allow.branches]
1905 1905 """
1906 1906 pushing to ../b
1907 1907 query 1; heads
1908 1908 searching for changes
1909 1909 all remote heads known locally
1910 1910 listing keys for "phases"
1911 1911 checking for updated bookmarks
1912 1912 listing keys for "bookmarks"
1913 1913 listing keys for "bookmarks"
1914 1914 4 changesets found
1915 1915 list of changesets:
1916 1916 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1917 1917 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1918 1918 911600dab2ae7a9baff75958b84fe606851ce955
1919 1919 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1920 1920 bundle2-output-bundle: "HG20", 5 parts total
1921 bundle2-output-part: "replycaps" 224 bytes payload
1921 bundle2-output-part: "replycaps" 207 bytes payload
1922 1922 bundle2-output-part: "check:phases" 48 bytes payload
1923 1923 bundle2-output-part: "check:updated-heads" streamed payload
1924 1924 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1925 1925 bundle2-output-part: "phase-heads" 48 bytes payload
1926 1926 bundle2-input-bundle: with-transaction
1927 1927 bundle2-input-part: "replycaps" supported
1928 bundle2-input-part: total payload size 224
1928 bundle2-input-part: total payload size 207
1929 1929 bundle2-input-part: "check:phases" supported
1930 1930 bundle2-input-part: total payload size 48
1931 1931 bundle2-input-part: "check:updated-heads" supported
1932 1932 bundle2-input-part: total payload size 40
1933 1933 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
1934 1934 adding changesets
1935 1935 add changeset ef1ea85a6374
1936 1936 add changeset f9cafe1212c8
1937 1937 add changeset 911600dab2ae
1938 1938 add changeset e8fc755d4d82
1939 1939 adding manifests
1940 1940 adding file changes
1941 1941 adding abc.txt revisions
1942 1942 adding foo/Bar/file.txt revisions
1943 1943 adding foo/file.txt revisions
1944 1944 adding quux/file.py revisions
1945 1945 calling hook pretxnchangegroup.acl: hgext.acl.hook
1946 1946 acl: checking access for user "astro"
1947 1947 acl: acl.allow.branches enabled, 0 entries for user astro
1948 1948 acl: acl.deny.branches not enabled
1949 1949 acl: acl.allow not enabled
1950 1950 acl: acl.deny not enabled
1951 1951 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1952 1952 bundle2-input-part: total payload size 2068
1953 1953 bundle2-input-part: total payload size 48
1954 1954 bundle2-input-bundle: 5 parts total
1955 1955 transaction abort!
1956 1956 rollback completed
1957 1957 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1958 1958 no rollback information available
1959 1959 2:fb35475503ef
1960 1960
1961 1961
1962 1962 Branch acl allow other
1963 1963
1964 1964 $ init_config
1965 1965 $ echo "[acl.allow.branches]" >> $config
1966 1966 $ echo "* = george" >> $config
1967 1967 $ do_push astro
1968 1968 Pushing as user astro
1969 1969 hgrc = """
1970 1970 [hooks]
1971 1971 pretxnchangegroup.acl = python:hgext.acl.hook
1972 1972 prepushkey.acl = python:hgext.acl.hook
1973 1973 [acl]
1974 1974 sources = push
1975 1975 [extensions]
1976 1976 posixgetuser=$TESTTMP/posixgetuser.py
1977 1977 [acl.allow.branches]
1978 1978 * = george
1979 1979 """
1980 1980 pushing to ../b
1981 1981 query 1; heads
1982 1982 searching for changes
1983 1983 all remote heads known locally
1984 1984 listing keys for "phases"
1985 1985 checking for updated bookmarks
1986 1986 listing keys for "bookmarks"
1987 1987 listing keys for "bookmarks"
1988 1988 4 changesets found
1989 1989 list of changesets:
1990 1990 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1991 1991 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1992 1992 911600dab2ae7a9baff75958b84fe606851ce955
1993 1993 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1994 1994 bundle2-output-bundle: "HG20", 5 parts total
1995 bundle2-output-part: "replycaps" 224 bytes payload
1995 bundle2-output-part: "replycaps" 207 bytes payload
1996 1996 bundle2-output-part: "check:phases" 48 bytes payload
1997 1997 bundle2-output-part: "check:updated-heads" streamed payload
1998 1998 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
1999 1999 bundle2-output-part: "phase-heads" 48 bytes payload
2000 2000 bundle2-input-bundle: with-transaction
2001 2001 bundle2-input-part: "replycaps" supported
2002 bundle2-input-part: total payload size 224
2002 bundle2-input-part: total payload size 207
2003 2003 bundle2-input-part: "check:phases" supported
2004 2004 bundle2-input-part: total payload size 48
2005 2005 bundle2-input-part: "check:updated-heads" supported
2006 2006 bundle2-input-part: total payload size 40
2007 2007 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2008 2008 adding changesets
2009 2009 add changeset ef1ea85a6374
2010 2010 add changeset f9cafe1212c8
2011 2011 add changeset 911600dab2ae
2012 2012 add changeset e8fc755d4d82
2013 2013 adding manifests
2014 2014 adding file changes
2015 2015 adding abc.txt revisions
2016 2016 adding foo/Bar/file.txt revisions
2017 2017 adding foo/file.txt revisions
2018 2018 adding quux/file.py revisions
2019 2019 calling hook pretxnchangegroup.acl: hgext.acl.hook
2020 2020 acl: checking access for user "astro"
2021 2021 acl: acl.allow.branches enabled, 0 entries for user astro
2022 2022 acl: acl.deny.branches not enabled
2023 2023 acl: acl.allow not enabled
2024 2024 acl: acl.deny not enabled
2025 2025 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
2026 2026 bundle2-input-part: total payload size 2068
2027 2027 bundle2-input-part: total payload size 48
2028 2028 bundle2-input-bundle: 5 parts total
2029 2029 transaction abort!
2030 2030 rollback completed
2031 2031 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
2032 2032 no rollback information available
2033 2033 2:fb35475503ef
2034 2034
2035 2035 $ do_push george
2036 2036 Pushing as user george
2037 2037 hgrc = """
2038 2038 [hooks]
2039 2039 pretxnchangegroup.acl = python:hgext.acl.hook
2040 2040 prepushkey.acl = python:hgext.acl.hook
2041 2041 [acl]
2042 2042 sources = push
2043 2043 [extensions]
2044 2044 posixgetuser=$TESTTMP/posixgetuser.py
2045 2045 [acl.allow.branches]
2046 2046 * = george
2047 2047 """
2048 2048 pushing to ../b
2049 2049 query 1; heads
2050 2050 searching for changes
2051 2051 all remote heads known locally
2052 2052 listing keys for "phases"
2053 2053 checking for updated bookmarks
2054 2054 listing keys for "bookmarks"
2055 2055 listing keys for "bookmarks"
2056 2056 4 changesets found
2057 2057 list of changesets:
2058 2058 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2059 2059 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2060 2060 911600dab2ae7a9baff75958b84fe606851ce955
2061 2061 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2062 2062 bundle2-output-bundle: "HG20", 5 parts total
2063 bundle2-output-part: "replycaps" 224 bytes payload
2063 bundle2-output-part: "replycaps" 207 bytes payload
2064 2064 bundle2-output-part: "check:phases" 48 bytes payload
2065 2065 bundle2-output-part: "check:updated-heads" streamed payload
2066 2066 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2067 2067 bundle2-output-part: "phase-heads" 48 bytes payload
2068 2068 bundle2-input-bundle: with-transaction
2069 2069 bundle2-input-part: "replycaps" supported
2070 bundle2-input-part: total payload size 224
2070 bundle2-input-part: total payload size 207
2071 2071 bundle2-input-part: "check:phases" supported
2072 2072 bundle2-input-part: total payload size 48
2073 2073 bundle2-input-part: "check:updated-heads" supported
2074 2074 bundle2-input-part: total payload size 40
2075 2075 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2076 2076 adding changesets
2077 2077 add changeset ef1ea85a6374
2078 2078 add changeset f9cafe1212c8
2079 2079 add changeset 911600dab2ae
2080 2080 add changeset e8fc755d4d82
2081 2081 adding manifests
2082 2082 adding file changes
2083 2083 adding abc.txt revisions
2084 2084 adding foo/Bar/file.txt revisions
2085 2085 adding foo/file.txt revisions
2086 2086 adding quux/file.py revisions
2087 2087 calling hook pretxnchangegroup.acl: hgext.acl.hook
2088 2088 acl: checking access for user "george"
2089 2089 acl: acl.allow.branches enabled, 1 entries for user george
2090 2090 acl: acl.deny.branches not enabled
2091 2091 acl: acl.allow not enabled
2092 2092 acl: acl.deny not enabled
2093 2093 acl: branch access granted: "ef1ea85a6374" on branch "default"
2094 2094 acl: path access granted: "ef1ea85a6374"
2095 2095 acl: branch access granted: "f9cafe1212c8" on branch "default"
2096 2096 acl: path access granted: "f9cafe1212c8"
2097 2097 acl: branch access granted: "911600dab2ae" on branch "default"
2098 2098 acl: path access granted: "911600dab2ae"
2099 2099 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
2100 2100 acl: path access granted: "e8fc755d4d82"
2101 2101 bundle2-input-part: total payload size 2068
2102 2102 bundle2-input-part: "phase-heads" supported
2103 2103 bundle2-input-part: total payload size 48
2104 2104 bundle2-input-bundle: 5 parts total
2105 2105 updating the branch cache
2106 2106 invalid branch cache (served.hidden): tip differs
2107 2107 added 4 changesets with 4 changes to 4 files (+1 heads)
2108 2108 bundle2-output-bundle: "HG20", 1 parts total
2109 2109 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
2110 2110 bundle2-input-bundle: no-transaction
2111 2111 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
2112 2112 bundle2-input-bundle: 1 parts total
2113 2113 listing keys for "phases"
2114 2114 repository tip rolled back to revision 2 (undo push)
2115 2115 2:fb35475503ef
2116 2116
2117 2117
2118 2118 Branch acl conflicting allow
2119 2119 asterisk ends up applying to all branches and allowing george to
2120 2120 push foobar into the remote
2121 2121
2122 2122 $ init_config
2123 2123 $ echo "[acl.allow.branches]" >> $config
2124 2124 $ echo "foobar = astro" >> $config
2125 2125 $ echo "* = george" >> $config
2126 2126 $ do_push george
2127 2127 Pushing as user george
2128 2128 hgrc = """
2129 2129 [hooks]
2130 2130 pretxnchangegroup.acl = python:hgext.acl.hook
2131 2131 prepushkey.acl = python:hgext.acl.hook
2132 2132 [acl]
2133 2133 sources = push
2134 2134 [extensions]
2135 2135 posixgetuser=$TESTTMP/posixgetuser.py
2136 2136 [acl.allow.branches]
2137 2137 foobar = astro
2138 2138 * = george
2139 2139 """
2140 2140 pushing to ../b
2141 2141 query 1; heads
2142 2142 searching for changes
2143 2143 all remote heads known locally
2144 2144 listing keys for "phases"
2145 2145 checking for updated bookmarks
2146 2146 listing keys for "bookmarks"
2147 2147 listing keys for "bookmarks"
2148 2148 4 changesets found
2149 2149 list of changesets:
2150 2150 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2151 2151 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2152 2152 911600dab2ae7a9baff75958b84fe606851ce955
2153 2153 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2154 2154 bundle2-output-bundle: "HG20", 5 parts total
2155 bundle2-output-part: "replycaps" 224 bytes payload
2155 bundle2-output-part: "replycaps" 207 bytes payload
2156 2156 bundle2-output-part: "check:phases" 48 bytes payload
2157 2157 bundle2-output-part: "check:updated-heads" streamed payload
2158 2158 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2159 2159 bundle2-output-part: "phase-heads" 48 bytes payload
2160 2160 bundle2-input-bundle: with-transaction
2161 2161 bundle2-input-part: "replycaps" supported
2162 bundle2-input-part: total payload size 224
2162 bundle2-input-part: total payload size 207
2163 2163 bundle2-input-part: "check:phases" supported
2164 2164 bundle2-input-part: total payload size 48
2165 2165 bundle2-input-part: "check:updated-heads" supported
2166 2166 bundle2-input-part: total payload size 40
2167 2167 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2168 2168 adding changesets
2169 2169 add changeset ef1ea85a6374
2170 2170 add changeset f9cafe1212c8
2171 2171 add changeset 911600dab2ae
2172 2172 add changeset e8fc755d4d82
2173 2173 adding manifests
2174 2174 adding file changes
2175 2175 adding abc.txt revisions
2176 2176 adding foo/Bar/file.txt revisions
2177 2177 adding foo/file.txt revisions
2178 2178 adding quux/file.py revisions
2179 2179 calling hook pretxnchangegroup.acl: hgext.acl.hook
2180 2180 acl: checking access for user "george"
2181 2181 acl: acl.allow.branches enabled, 1 entries for user george
2182 2182 acl: acl.deny.branches not enabled
2183 2183 acl: acl.allow not enabled
2184 2184 acl: acl.deny not enabled
2185 2185 acl: branch access granted: "ef1ea85a6374" on branch "default"
2186 2186 acl: path access granted: "ef1ea85a6374"
2187 2187 acl: branch access granted: "f9cafe1212c8" on branch "default"
2188 2188 acl: path access granted: "f9cafe1212c8"
2189 2189 acl: branch access granted: "911600dab2ae" on branch "default"
2190 2190 acl: path access granted: "911600dab2ae"
2191 2191 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
2192 2192 acl: path access granted: "e8fc755d4d82"
2193 2193 bundle2-input-part: total payload size 2068
2194 2194 bundle2-input-part: "phase-heads" supported
2195 2195 bundle2-input-part: total payload size 48
2196 2196 bundle2-input-bundle: 5 parts total
2197 2197 updating the branch cache
2198 2198 invalid branch cache (served.hidden): tip differs
2199 2199 added 4 changesets with 4 changes to 4 files (+1 heads)
2200 2200 bundle2-output-bundle: "HG20", 1 parts total
2201 2201 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
2202 2202 bundle2-input-bundle: no-transaction
2203 2203 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
2204 2204 bundle2-input-bundle: 1 parts total
2205 2205 listing keys for "phases"
2206 2206 repository tip rolled back to revision 2 (undo push)
2207 2207 2:fb35475503ef
2208 2208
2209 2209 Branch acl conflicting deny
2210 2210
2211 2211 $ init_config
2212 2212 $ echo "[acl.deny.branches]" >> $config
2213 2213 $ echo "foobar = astro" >> $config
2214 2214 $ echo "default = astro" >> $config
2215 2215 $ echo "* = george" >> $config
2216 2216 $ do_push george
2217 2217 Pushing as user george
2218 2218 hgrc = """
2219 2219 [hooks]
2220 2220 pretxnchangegroup.acl = python:hgext.acl.hook
2221 2221 prepushkey.acl = python:hgext.acl.hook
2222 2222 [acl]
2223 2223 sources = push
2224 2224 [extensions]
2225 2225 posixgetuser=$TESTTMP/posixgetuser.py
2226 2226 [acl.deny.branches]
2227 2227 foobar = astro
2228 2228 default = astro
2229 2229 * = george
2230 2230 """
2231 2231 pushing to ../b
2232 2232 query 1; heads
2233 2233 searching for changes
2234 2234 all remote heads known locally
2235 2235 listing keys for "phases"
2236 2236 checking for updated bookmarks
2237 2237 listing keys for "bookmarks"
2238 2238 listing keys for "bookmarks"
2239 2239 4 changesets found
2240 2240 list of changesets:
2241 2241 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2242 2242 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2243 2243 911600dab2ae7a9baff75958b84fe606851ce955
2244 2244 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2245 2245 bundle2-output-bundle: "HG20", 5 parts total
2246 bundle2-output-part: "replycaps" 224 bytes payload
2246 bundle2-output-part: "replycaps" 207 bytes payload
2247 2247 bundle2-output-part: "check:phases" 48 bytes payload
2248 2248 bundle2-output-part: "check:updated-heads" streamed payload
2249 2249 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2250 2250 bundle2-output-part: "phase-heads" 48 bytes payload
2251 2251 bundle2-input-bundle: with-transaction
2252 2252 bundle2-input-part: "replycaps" supported
2253 bundle2-input-part: total payload size 224
2253 bundle2-input-part: total payload size 207
2254 2254 bundle2-input-part: "check:phases" supported
2255 2255 bundle2-input-part: total payload size 48
2256 2256 bundle2-input-part: "check:updated-heads" supported
2257 2257 bundle2-input-part: total payload size 40
2258 2258 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2259 2259 adding changesets
2260 2260 add changeset ef1ea85a6374
2261 2261 add changeset f9cafe1212c8
2262 2262 add changeset 911600dab2ae
2263 2263 add changeset e8fc755d4d82
2264 2264 adding manifests
2265 2265 adding file changes
2266 2266 adding abc.txt revisions
2267 2267 adding foo/Bar/file.txt revisions
2268 2268 adding foo/file.txt revisions
2269 2269 adding quux/file.py revisions
2270 2270 calling hook pretxnchangegroup.acl: hgext.acl.hook
2271 2271 acl: checking access for user "george"
2272 2272 acl: acl.allow.branches not enabled
2273 2273 acl: acl.deny.branches enabled, 1 entries for user george
2274 2274 acl: acl.allow not enabled
2275 2275 acl: acl.deny not enabled
2276 2276 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2277 2277 bundle2-input-part: total payload size 2068
2278 2278 bundle2-input-part: total payload size 48
2279 2279 bundle2-input-bundle: 5 parts total
2280 2280 transaction abort!
2281 2281 rollback completed
2282 2282 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2283 2283 no rollback information available
2284 2284 2:fb35475503ef
2285 2285
2286 2286 User 'astro' must not be denied
2287 2287
2288 2288 $ init_config
2289 2289 $ echo "[acl.deny.branches]" >> $config
2290 2290 $ echo "default = !astro" >> $config
2291 2291 $ do_push astro
2292 2292 Pushing as user astro
2293 2293 hgrc = """
2294 2294 [hooks]
2295 2295 pretxnchangegroup.acl = python:hgext.acl.hook
2296 2296 prepushkey.acl = python:hgext.acl.hook
2297 2297 [acl]
2298 2298 sources = push
2299 2299 [extensions]
2300 2300 posixgetuser=$TESTTMP/posixgetuser.py
2301 2301 [acl.deny.branches]
2302 2302 default = !astro
2303 2303 """
2304 2304 pushing to ../b
2305 2305 query 1; heads
2306 2306 searching for changes
2307 2307 all remote heads known locally
2308 2308 listing keys for "phases"
2309 2309 checking for updated bookmarks
2310 2310 listing keys for "bookmarks"
2311 2311 listing keys for "bookmarks"
2312 2312 4 changesets found
2313 2313 list of changesets:
2314 2314 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2315 2315 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2316 2316 911600dab2ae7a9baff75958b84fe606851ce955
2317 2317 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2318 2318 bundle2-output-bundle: "HG20", 5 parts total
2319 bundle2-output-part: "replycaps" 224 bytes payload
2319 bundle2-output-part: "replycaps" 207 bytes payload
2320 2320 bundle2-output-part: "check:phases" 48 bytes payload
2321 2321 bundle2-output-part: "check:updated-heads" streamed payload
2322 2322 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2323 2323 bundle2-output-part: "phase-heads" 48 bytes payload
2324 2324 bundle2-input-bundle: with-transaction
2325 2325 bundle2-input-part: "replycaps" supported
2326 bundle2-input-part: total payload size 224
2326 bundle2-input-part: total payload size 207
2327 2327 bundle2-input-part: "check:phases" supported
2328 2328 bundle2-input-part: total payload size 48
2329 2329 bundle2-input-part: "check:updated-heads" supported
2330 2330 bundle2-input-part: total payload size 40
2331 2331 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2332 2332 adding changesets
2333 2333 add changeset ef1ea85a6374
2334 2334 add changeset f9cafe1212c8
2335 2335 add changeset 911600dab2ae
2336 2336 add changeset e8fc755d4d82
2337 2337 adding manifests
2338 2338 adding file changes
2339 2339 adding abc.txt revisions
2340 2340 adding foo/Bar/file.txt revisions
2341 2341 adding foo/file.txt revisions
2342 2342 adding quux/file.py revisions
2343 2343 calling hook pretxnchangegroup.acl: hgext.acl.hook
2344 2344 acl: checking access for user "astro"
2345 2345 acl: acl.allow.branches not enabled
2346 2346 acl: acl.deny.branches enabled, 0 entries for user astro
2347 2347 acl: acl.allow not enabled
2348 2348 acl: acl.deny not enabled
2349 2349 acl: branch access granted: "ef1ea85a6374" on branch "default"
2350 2350 acl: path access granted: "ef1ea85a6374"
2351 2351 acl: branch access granted: "f9cafe1212c8" on branch "default"
2352 2352 acl: path access granted: "f9cafe1212c8"
2353 2353 acl: branch access granted: "911600dab2ae" on branch "default"
2354 2354 acl: path access granted: "911600dab2ae"
2355 2355 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
2356 2356 acl: path access granted: "e8fc755d4d82"
2357 2357 bundle2-input-part: total payload size 2068
2358 2358 bundle2-input-part: "phase-heads" supported
2359 2359 bundle2-input-part: total payload size 48
2360 2360 bundle2-input-bundle: 5 parts total
2361 2361 updating the branch cache
2362 2362 invalid branch cache (served.hidden): tip differs
2363 2363 added 4 changesets with 4 changes to 4 files (+1 heads)
2364 2364 bundle2-output-bundle: "HG20", 1 parts total
2365 2365 bundle2-output-part: "reply:changegroup" (advisory) (params: 0 advisory) empty payload
2366 2366 bundle2-input-bundle: no-transaction
2367 2367 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
2368 2368 bundle2-input-bundle: 1 parts total
2369 2369 listing keys for "phases"
2370 2370 repository tip rolled back to revision 2 (undo push)
2371 2371 2:fb35475503ef
2372 2372
2373 2373
2374 2374 Non-astro users must be denied
2375 2375
2376 2376 $ do_push george
2377 2377 Pushing as user george
2378 2378 hgrc = """
2379 2379 [hooks]
2380 2380 pretxnchangegroup.acl = python:hgext.acl.hook
2381 2381 prepushkey.acl = python:hgext.acl.hook
2382 2382 [acl]
2383 2383 sources = push
2384 2384 [extensions]
2385 2385 posixgetuser=$TESTTMP/posixgetuser.py
2386 2386 [acl.deny.branches]
2387 2387 default = !astro
2388 2388 """
2389 2389 pushing to ../b
2390 2390 query 1; heads
2391 2391 searching for changes
2392 2392 all remote heads known locally
2393 2393 listing keys for "phases"
2394 2394 checking for updated bookmarks
2395 2395 listing keys for "bookmarks"
2396 2396 listing keys for "bookmarks"
2397 2397 4 changesets found
2398 2398 list of changesets:
2399 2399 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
2400 2400 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
2401 2401 911600dab2ae7a9baff75958b84fe606851ce955
2402 2402 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
2403 2403 bundle2-output-bundle: "HG20", 5 parts total
2404 bundle2-output-part: "replycaps" 224 bytes payload
2404 bundle2-output-part: "replycaps" 207 bytes payload
2405 2405 bundle2-output-part: "check:phases" 48 bytes payload
2406 2406 bundle2-output-part: "check:updated-heads" streamed payload
2407 2407 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
2408 2408 bundle2-output-part: "phase-heads" 48 bytes payload
2409 2409 bundle2-input-bundle: with-transaction
2410 2410 bundle2-input-part: "replycaps" supported
2411 bundle2-input-part: total payload size 224
2411 bundle2-input-part: total payload size 207
2412 2412 bundle2-input-part: "check:phases" supported
2413 2413 bundle2-input-part: total payload size 48
2414 2414 bundle2-input-part: "check:updated-heads" supported
2415 2415 bundle2-input-part: total payload size 40
2416 2416 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
2417 2417 adding changesets
2418 2418 add changeset ef1ea85a6374
2419 2419 add changeset f9cafe1212c8
2420 2420 add changeset 911600dab2ae
2421 2421 add changeset e8fc755d4d82
2422 2422 adding manifests
2423 2423 adding file changes
2424 2424 adding abc.txt revisions
2425 2425 adding foo/Bar/file.txt revisions
2426 2426 adding foo/file.txt revisions
2427 2427 adding quux/file.py revisions
2428 2428 calling hook pretxnchangegroup.acl: hgext.acl.hook
2429 2429 acl: checking access for user "george"
2430 2430 acl: acl.allow.branches not enabled
2431 2431 acl: acl.deny.branches enabled, 1 entries for user george
2432 2432 acl: acl.allow not enabled
2433 2433 acl: acl.deny not enabled
2434 2434 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2435 2435 bundle2-input-part: total payload size 2068
2436 2436 bundle2-input-part: total payload size 48
2437 2437 bundle2-input-bundle: 5 parts total
2438 2438 transaction abort!
2439 2439 rollback completed
2440 2440 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
2441 2441 no rollback information available
2442 2442 2:fb35475503ef
2443 2443
2444 2444
@@ -1,1396 +1,1396 b''
1 1 #testcases b2-pushkey b2-binary
2 2
3 3 #if b2-pushkey
4 4 $ cat << EOF >> $HGRCPATH
5 5 > [devel]
6 6 > legacy.exchange=bookmarks
7 7 > EOF
8 8 #endif
9 9
10 10 #require serve
11 11
12 12 $ cat << EOF >> $HGRCPATH
13 13 > [command-templates]
14 14 > log={rev}:{node|short} {desc|firstline}
15 15 > [phases]
16 16 > publish=False
17 17 > [experimental]
18 18 > evolution.createmarkers=True
19 19 > evolution.exchange=True
20 20 > EOF
21 21
22 22 $ cat > $TESTTMP/hook.sh <<'EOF'
23 23 > echo "test-hook-bookmark: $HG_BOOKMARK: $HG_OLDNODE -> $HG_NODE"
24 24 > EOF
25 25 $ TESTHOOK="hooks.txnclose-bookmark.test=sh $TESTTMP/hook.sh"
26 26
27 27 initialize
28 28
29 29 $ hg init a
30 30 $ cd a
31 31 $ echo 'test' > test
32 32 $ hg commit -Am'test'
33 33 adding test
34 34
35 35 set bookmarks
36 36
37 37 $ hg bookmark X
38 38 $ hg bookmark Y
39 39 $ hg bookmark Z
40 40
41 41 import bookmark by name
42 42
43 43 $ hg init ../b
44 44 $ cd ../b
45 45 $ hg book Y
46 46 $ hg book
47 47 * Y -1:000000000000
48 48 $ hg pull ../a --config "$TESTHOOK"
49 49 pulling from ../a
50 50 requesting all changes
51 51 adding changesets
52 52 adding manifests
53 53 adding file changes
54 54 adding remote bookmark X
55 55 updating bookmark Y
56 56 adding remote bookmark Z
57 57 added 1 changesets with 1 changes to 1 files
58 58 new changesets 4e3505fd9583 (1 drafts)
59 59 test-hook-bookmark: X: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
60 60 test-hook-bookmark: Y: 0000000000000000000000000000000000000000 -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
61 61 test-hook-bookmark: Z: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
62 62 (run 'hg update' to get a working copy)
63 63 $ hg bookmarks
64 64 X 0:4e3505fd9583
65 65 * Y 0:4e3505fd9583
66 66 Z 0:4e3505fd9583
67 67 $ hg debugpushkey ../a namespaces
68 68 bookmarks
69 69 namespaces
70 70 obsolete
71 71 phases
72 72 $ hg debugpushkey ../a bookmarks
73 73 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
74 74 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
75 75 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
76 76
77 77 delete the bookmark to re-pull it
78 78
79 79 $ hg book -d X
80 80 $ hg pull -B X ../a
81 81 pulling from ../a
82 82 no changes found
83 83 adding remote bookmark X
84 84
85 85 finally no-op pull
86 86
87 87 $ hg pull -B X ../a
88 88 pulling from ../a
89 89 no changes found
90 90 $ hg bookmark
91 91 X 0:4e3505fd9583
92 92 * Y 0:4e3505fd9583
93 93 Z 0:4e3505fd9583
94 94
95 95 export bookmark by name
96 96
97 97 $ hg bookmark W
98 98 $ hg bookmark foo
99 99 $ hg bookmark foobar
100 100 $ hg push -B W ../a
101 101 pushing to ../a
102 102 searching for changes
103 103 no changes found
104 104 exporting bookmark W
105 105 [1]
106 106 $ hg -R ../a bookmarks
107 107 W -1:000000000000
108 108 X 0:4e3505fd9583
109 109 Y 0:4e3505fd9583
110 110 * Z 0:4e3505fd9583
111 111
112 112 delete a remote bookmark
113 113
114 114 $ hg book -d W
115 115
116 116 #if b2-pushkey
117 117
118 118 $ hg push -B W ../a --config "$TESTHOOK" --debug --config devel.bundle2.debug=yes
119 119 pushing to ../a
120 120 query 1; heads
121 121 searching for changes
122 122 all remote heads known locally
123 123 listing keys for "phases"
124 124 checking for updated bookmarks
125 125 listing keys for "bookmarks"
126 126 no changes found
127 127 bundle2-output-bundle: "HG20", 4 parts total
128 128 bundle2-output: start emission of HG20 stream
129 129 bundle2-output: bundle parameter:
130 130 bundle2-output: start of parts
131 131 bundle2-output: bundle part: "replycaps"
132 bundle2-output-part: "replycaps" 241 bytes payload
132 bundle2-output-part: "replycaps" 224 bytes payload
133 133 bundle2-output: part 0: "REPLYCAPS"
134 134 bundle2-output: header chunk size: 16
135 bundle2-output: payload chunk size: 241
135 bundle2-output: payload chunk size: 224
136 136 bundle2-output: closing payload chunk
137 137 bundle2-output: bundle part: "check:bookmarks"
138 138 bundle2-output-part: "check:bookmarks" 23 bytes payload
139 139 bundle2-output: part 1: "CHECK:BOOKMARKS"
140 140 bundle2-output: header chunk size: 22
141 141 bundle2-output: payload chunk size: 23
142 142 bundle2-output: closing payload chunk
143 143 bundle2-output: bundle part: "check:phases"
144 144 bundle2-output-part: "check:phases" 24 bytes payload
145 145 bundle2-output: part 2: "CHECK:PHASES"
146 146 bundle2-output: header chunk size: 19
147 147 bundle2-output: payload chunk size: 24
148 148 bundle2-output: closing payload chunk
149 149 bundle2-output: bundle part: "pushkey"
150 150 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
151 151 bundle2-output: part 3: "PUSHKEY"
152 152 bundle2-output: header chunk size: 90
153 153 bundle2-output: closing payload chunk
154 154 bundle2-output: end of bundle
155 155 bundle2-input: start processing of HG20 stream
156 156 bundle2-input: reading bundle2 stream parameters
157 157 bundle2-input-bundle: with-transaction
158 158 bundle2-input: start extraction of bundle2 parts
159 159 bundle2-input: part header size: 16
160 160 bundle2-input: part type: "REPLYCAPS"
161 161 bundle2-input: part id: "0"
162 162 bundle2-input: part parameters: 0
163 163 bundle2-input: found a handler for part replycaps
164 164 bundle2-input-part: "replycaps" supported
165 bundle2-input: payload chunk size: 241
165 bundle2-input: payload chunk size: 224
166 166 bundle2-input: payload chunk size: 0
167 bundle2-input-part: total payload size 241
167 bundle2-input-part: total payload size 224
168 168 bundle2-input: part header size: 22
169 169 bundle2-input: part type: "CHECK:BOOKMARKS"
170 170 bundle2-input: part id: "1"
171 171 bundle2-input: part parameters: 0
172 172 bundle2-input: found a handler for part check:bookmarks
173 173 bundle2-input-part: "check:bookmarks" supported
174 174 bundle2-input: payload chunk size: 23
175 175 bundle2-input: payload chunk size: 0
176 176 bundle2-input-part: total payload size 23
177 177 bundle2-input: part header size: 19
178 178 bundle2-input: part type: "CHECK:PHASES"
179 179 bundle2-input: part id: "2"
180 180 bundle2-input: part parameters: 0
181 181 bundle2-input: found a handler for part check:phases
182 182 bundle2-input-part: "check:phases" supported
183 183 bundle2-input: payload chunk size: 24
184 184 bundle2-input: payload chunk size: 0
185 185 bundle2-input-part: total payload size 24
186 186 bundle2-input: part header size: 90
187 187 bundle2-input: part type: "PUSHKEY"
188 188 bundle2-input: part id: "3"
189 189 bundle2-input: part parameters: 4
190 190 bundle2-input: found a handler for part pushkey
191 191 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
192 192 pushing key for "bookmarks:W"
193 193 bundle2-input: payload chunk size: 0
194 194 bundle2-input: part header size: 0
195 195 bundle2-input: end of bundle2 stream
196 196 bundle2-input-bundle: 4 parts total
197 197 running hook txnclose-bookmark.test: sh $TESTTMP/hook.sh
198 198 test-hook-bookmark: W: 0000000000000000000000000000000000000000 ->
199 199 bundle2-output-bundle: "HG20", 1 parts total
200 200 bundle2-output: start emission of HG20 stream
201 201 bundle2-output: bundle parameter:
202 202 bundle2-output: start of parts
203 203 bundle2-output: bundle part: "reply:pushkey"
204 204 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
205 205 bundle2-output: part 0: "REPLY:PUSHKEY"
206 206 bundle2-output: header chunk size: 43
207 207 bundle2-output: closing payload chunk
208 208 bundle2-output: end of bundle
209 209 bundle2-input: start processing of HG20 stream
210 210 bundle2-input: reading bundle2 stream parameters
211 211 bundle2-input-bundle: no-transaction
212 212 bundle2-input: start extraction of bundle2 parts
213 213 bundle2-input: part header size: 43
214 214 bundle2-input: part type: "REPLY:PUSHKEY"
215 215 bundle2-input: part id: "0"
216 216 bundle2-input: part parameters: 2
217 217 bundle2-input: found a handler for part reply:pushkey
218 218 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
219 219 bundle2-input: payload chunk size: 0
220 220 bundle2-input: part header size: 0
221 221 bundle2-input: end of bundle2 stream
222 222 bundle2-input-bundle: 1 parts total
223 223 deleting remote bookmark W
224 224 listing keys for "phases"
225 225 [1]
226 226
227 227 #endif
228 228 #if b2-binary
229 229
230 230 $ hg push -B W ../a --config "$TESTHOOK" --debug --config devel.bundle2.debug=yes
231 231 pushing to ../a
232 232 query 1; heads
233 233 searching for changes
234 234 all remote heads known locally
235 235 listing keys for "phases"
236 236 checking for updated bookmarks
237 237 listing keys for "bookmarks"
238 238 no changes found
239 239 bundle2-output-bundle: "HG20", 4 parts total
240 240 bundle2-output: start emission of HG20 stream
241 241 bundle2-output: bundle parameter:
242 242 bundle2-output: start of parts
243 243 bundle2-output: bundle part: "replycaps"
244 bundle2-output-part: "replycaps" 241 bytes payload
244 bundle2-output-part: "replycaps" 224 bytes payload
245 245 bundle2-output: part 0: "REPLYCAPS"
246 246 bundle2-output: header chunk size: 16
247 bundle2-output: payload chunk size: 241
247 bundle2-output: payload chunk size: 224
248 248 bundle2-output: closing payload chunk
249 249 bundle2-output: bundle part: "check:bookmarks"
250 250 bundle2-output-part: "check:bookmarks" 23 bytes payload
251 251 bundle2-output: part 1: "CHECK:BOOKMARKS"
252 252 bundle2-output: header chunk size: 22
253 253 bundle2-output: payload chunk size: 23
254 254 bundle2-output: closing payload chunk
255 255 bundle2-output: bundle part: "check:phases"
256 256 bundle2-output-part: "check:phases" 24 bytes payload
257 257 bundle2-output: part 2: "CHECK:PHASES"
258 258 bundle2-output: header chunk size: 19
259 259 bundle2-output: payload chunk size: 24
260 260 bundle2-output: closing payload chunk
261 261 bundle2-output: bundle part: "bookmarks"
262 262 bundle2-output-part: "bookmarks" 23 bytes payload
263 263 bundle2-output: part 3: "BOOKMARKS"
264 264 bundle2-output: header chunk size: 16
265 265 bundle2-output: payload chunk size: 23
266 266 bundle2-output: closing payload chunk
267 267 bundle2-output: end of bundle
268 268 bundle2-input: start processing of HG20 stream
269 269 bundle2-input: reading bundle2 stream parameters
270 270 bundle2-input-bundle: with-transaction
271 271 bundle2-input: start extraction of bundle2 parts
272 272 bundle2-input: part header size: 16
273 273 bundle2-input: part type: "REPLYCAPS"
274 274 bundle2-input: part id: "0"
275 275 bundle2-input: part parameters: 0
276 276 bundle2-input: found a handler for part replycaps
277 277 bundle2-input-part: "replycaps" supported
278 bundle2-input: payload chunk size: 241
278 bundle2-input: payload chunk size: 224
279 279 bundle2-input: payload chunk size: 0
280 bundle2-input-part: total payload size 241
280 bundle2-input-part: total payload size 224
281 281 bundle2-input: part header size: 22
282 282 bundle2-input: part type: "CHECK:BOOKMARKS"
283 283 bundle2-input: part id: "1"
284 284 bundle2-input: part parameters: 0
285 285 bundle2-input: found a handler for part check:bookmarks
286 286 bundle2-input-part: "check:bookmarks" supported
287 287 bundle2-input: payload chunk size: 23
288 288 bundle2-input: payload chunk size: 0
289 289 bundle2-input-part: total payload size 23
290 290 bundle2-input: part header size: 19
291 291 bundle2-input: part type: "CHECK:PHASES"
292 292 bundle2-input: part id: "2"
293 293 bundle2-input: part parameters: 0
294 294 bundle2-input: found a handler for part check:phases
295 295 bundle2-input-part: "check:phases" supported
296 296 bundle2-input: payload chunk size: 24
297 297 bundle2-input: payload chunk size: 0
298 298 bundle2-input-part: total payload size 24
299 299 bundle2-input: part header size: 16
300 300 bundle2-input: part type: "BOOKMARKS"
301 301 bundle2-input: part id: "3"
302 302 bundle2-input: part parameters: 0
303 303 bundle2-input: found a handler for part bookmarks
304 304 bundle2-input-part: "bookmarks" supported
305 305 bundle2-input: payload chunk size: 23
306 306 bundle2-input: payload chunk size: 0
307 307 bundle2-input-part: total payload size 23
308 308 bundle2-input: part header size: 0
309 309 bundle2-input: end of bundle2 stream
310 310 bundle2-input-bundle: 4 parts total
311 311 running hook txnclose-bookmark.test: sh $TESTTMP/hook.sh
312 312 test-hook-bookmark: W: 0000000000000000000000000000000000000000 ->
313 313 bundle2-output-bundle: "HG20", 0 parts total
314 314 bundle2-output: start emission of HG20 stream
315 315 bundle2-output: bundle parameter:
316 316 bundle2-output: start of parts
317 317 bundle2-output: end of bundle
318 318 bundle2-input: start processing of HG20 stream
319 319 bundle2-input: reading bundle2 stream parameters
320 320 bundle2-input-bundle: no-transaction
321 321 bundle2-input: start extraction of bundle2 parts
322 322 bundle2-input: part header size: 0
323 323 bundle2-input: end of bundle2 stream
324 324 bundle2-input-bundle: 0 parts total
325 325 deleting remote bookmark W
326 326 listing keys for "phases"
327 327 [1]
328 328
329 329 #endif
330 330
331 331 Divergent bookmark cannot be exported
332 332
333 333 $ hg book W@default
334 334 $ hg push -B W@default ../a
335 335 pushing to ../a
336 336 searching for changes
337 337 cannot push divergent bookmark W@default!
338 338 no changes found
339 339 [2]
340 340 $ hg book -d W@default
341 341
342 342 export the active bookmark
343 343
344 344 $ hg bookmark V
345 345 $ hg push -B . ../a
346 346 pushing to ../a
347 347 searching for changes
348 348 no changes found
349 349 exporting bookmark V
350 350 [1]
351 351
352 352 exporting the active bookmark with 'push -B .'
353 353 demand that one of the bookmarks is activated
354 354
355 355 $ hg update -r default
356 356 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 357 (leaving bookmark V)
358 358 $ hg push -B . ../a
359 359 abort: no active bookmark
360 360 [255]
361 361 $ hg update -r V
362 362 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
363 363 (activating bookmark V)
364 364
365 365 delete the bookmark
366 366
367 367 $ hg book -d V
368 368 $ hg push -B V ../a
369 369 pushing to ../a
370 370 searching for changes
371 371 no changes found
372 372 deleting remote bookmark V
373 373 [1]
374 374 $ hg up foobar
375 375 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 376 (activating bookmark foobar)
377 377
378 378 push/pull name that doesn't exist
379 379
380 380 $ hg push -B badname ../a
381 381 pushing to ../a
382 382 searching for changes
383 383 bookmark badname does not exist on the local or remote repository!
384 384 no changes found
385 385 [2]
386 386 $ hg pull -B anotherbadname ../a
387 387 pulling from ../a
388 388 abort: remote bookmark anotherbadname not found!
389 389 [10]
390 390
391 391 divergent bookmarks
392 392
393 393 $ cd ../a
394 394 $ echo c1 > f1
395 395 $ hg ci -Am1
396 396 adding f1
397 397 $ hg book -f @
398 398 $ hg book -f X
399 399 $ hg book
400 400 @ 1:0d2164f0ce0d
401 401 * X 1:0d2164f0ce0d
402 402 Y 0:4e3505fd9583
403 403 Z 1:0d2164f0ce0d
404 404
405 405 $ cd ../b
406 406 $ hg up
407 407 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
408 408 updating bookmark foobar
409 409 $ echo c2 > f2
410 410 $ hg ci -Am2
411 411 adding f2
412 412 $ hg book -if @
413 413 $ hg book -if X
414 414 $ hg book
415 415 @ 1:9b140be10808
416 416 X 1:9b140be10808
417 417 Y 0:4e3505fd9583
418 418 Z 0:4e3505fd9583
419 419 foo -1:000000000000
420 420 * foobar 1:9b140be10808
421 421
422 422 $ hg pull --config paths.foo=../a foo --config "$TESTHOOK"
423 423 pulling from $TESTTMP/a
424 424 searching for changes
425 425 adding changesets
426 426 adding manifests
427 427 adding file changes
428 428 divergent bookmark @ stored as @foo
429 429 divergent bookmark X stored as X@foo
430 430 updating bookmark Z
431 431 added 1 changesets with 1 changes to 1 files (+1 heads)
432 432 new changesets 0d2164f0ce0d (1 drafts)
433 433 test-hook-bookmark: @foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
434 434 test-hook-bookmark: X@foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
435 435 test-hook-bookmark: Z: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
436 436 (run 'hg heads' to see heads, 'hg merge' to merge)
437 437 $ hg book
438 438 @ 1:9b140be10808
439 439 @foo 2:0d2164f0ce0d
440 440 X 1:9b140be10808
441 441 X@foo 2:0d2164f0ce0d
442 442 Y 0:4e3505fd9583
443 443 Z 2:0d2164f0ce0d
444 444 foo -1:000000000000
445 445 * foobar 1:9b140be10808
446 446
447 447 (test that too many divergence of bookmark)
448 448
449 449 $ "$PYTHON" $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
450 450 $ hg pull ../a
451 451 pulling from ../a
452 452 searching for changes
453 453 no changes found
454 454 warning: failed to assign numbered name to divergent bookmark X
455 455 divergent bookmark @ stored as @1
456 456 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
457 457 X 1:9b140be10808
458 458 X@foo 2:0d2164f0ce0d
459 459
460 460 (test that remotely diverged bookmarks are reused if they aren't changed)
461 461
462 462 $ hg bookmarks | grep '^ @'
463 463 @ 1:9b140be10808
464 464 @1 2:0d2164f0ce0d
465 465 @foo 2:0d2164f0ce0d
466 466 $ hg pull ../a
467 467 pulling from ../a
468 468 searching for changes
469 469 no changes found
470 470 warning: failed to assign numbered name to divergent bookmark X
471 471 divergent bookmark @ stored as @1
472 472 $ hg bookmarks | grep '^ @'
473 473 @ 1:9b140be10808
474 474 @1 2:0d2164f0ce0d
475 475 @foo 2:0d2164f0ce0d
476 476
477 477 $ "$PYTHON" $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
478 478 $ hg bookmarks -d "@1"
479 479
480 480 $ hg push -f ../a
481 481 pushing to ../a
482 482 searching for changes
483 483 adding changesets
484 484 adding manifests
485 485 adding file changes
486 486 added 1 changesets with 1 changes to 1 files (+1 heads)
487 487 $ hg -R ../a book
488 488 @ 1:0d2164f0ce0d
489 489 * X 1:0d2164f0ce0d
490 490 Y 0:4e3505fd9583
491 491 Z 1:0d2164f0ce0d
492 492
493 493 explicit pull should overwrite the local version (issue4439)
494 494
495 495 $ hg update -r X
496 496 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
497 497 (activating bookmark X)
498 498 $ hg pull --config paths.foo=../a foo -B . --config "$TESTHOOK"
499 499 pulling from $TESTTMP/a
500 500 no changes found
501 501 divergent bookmark @ stored as @foo
502 502 importing bookmark X
503 503 test-hook-bookmark: @foo: 0d2164f0ce0d8f1d6f94351eba04b794909be66c -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
504 504 test-hook-bookmark: X: 9b140be1080824d768c5a4691a564088eede71f9 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
505 505
506 506 reinstall state for further testing:
507 507
508 508 $ hg book -fr 9b140be10808 X
509 509
510 510 revsets should not ignore divergent bookmarks
511 511
512 512 $ hg bookmark -fr 1 Z
513 513 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
514 514 0:4e3505fd9583 Y
515 515 1:9b140be10808 @ X Z foobar
516 516 2:0d2164f0ce0d @foo X@foo
517 517 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
518 518 2:0d2164f0ce0d @foo X@foo
519 519 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
520 520 2:0d2164f0ce0d @foo X@foo
521 521
522 522 update a remote bookmark from a non-head to a head
523 523
524 524 $ hg up -q Y
525 525 $ echo c3 > f2
526 526 $ hg ci -Am3
527 527 adding f2
528 528 created new head
529 529 $ hg push ../a --config "$TESTHOOK"
530 530 pushing to ../a
531 531 searching for changes
532 532 adding changesets
533 533 adding manifests
534 534 adding file changes
535 535 added 1 changesets with 1 changes to 1 files (+1 heads)
536 536 test-hook-bookmark: Y: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
537 537 updating bookmark Y
538 538 $ hg -R ../a book
539 539 @ 1:0d2164f0ce0d
540 540 * X 1:0d2164f0ce0d
541 541 Y 3:f6fc62dde3c0
542 542 Z 1:0d2164f0ce0d
543 543
544 544 update a bookmark in the middle of a client pulling changes
545 545
546 546 $ cd ..
547 547 $ hg clone -q a pull-race
548 548
549 549 We want to use http because it is stateless and therefore more susceptible to
550 550 race conditions
551 551
552 552 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
553 553 $ cat pull-race.pid >> $DAEMON_PIDS
554 554
555 555 $ cat <<EOF > $TESTTMP/out_makecommit.sh
556 556 > #!/bin/sh
557 557 > hg ci -Am5
558 558 > echo committed in pull-race
559 559 > EOF
560 560
561 561 $ hg clone -q http://localhost:$HGPORT/ pull-race2 --config "$TESTHOOK"
562 562 test-hook-bookmark: @: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
563 563 test-hook-bookmark: X: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
564 564 test-hook-bookmark: Y: -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
565 565 test-hook-bookmark: Z: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
566 566 $ cd pull-race
567 567 $ hg up -q Y
568 568 $ echo c4 > f2
569 569 $ hg ci -Am4
570 570 $ echo c5 > f3
571 571 $ cat <<EOF > .hg/hgrc
572 572 > [hooks]
573 573 > outgoing.makecommit = sh $TESTTMP/out_makecommit.sh
574 574 > EOF
575 575
576 576 (new config needs a server restart)
577 577
578 578 $ cd ..
579 579 $ killdaemons.py
580 580 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
581 581 $ cat pull-race.pid >> $DAEMON_PIDS
582 582 $ cd pull-race2
583 583 $ hg -R $TESTTMP/pull-race book
584 584 @ 1:0d2164f0ce0d
585 585 X 1:0d2164f0ce0d
586 586 * Y 4:b0a5eff05604
587 587 Z 1:0d2164f0ce0d
588 588 $ hg pull
589 589 pulling from http://localhost:$HGPORT/
590 590 searching for changes
591 591 adding changesets
592 592 adding manifests
593 593 adding file changes
594 594 updating bookmark Y
595 595 added 1 changesets with 1 changes to 1 files
596 596 new changesets b0a5eff05604 (1 drafts)
597 597 (run 'hg update' to get a working copy)
598 598 $ hg book
599 599 * @ 1:0d2164f0ce0d
600 600 X 1:0d2164f0ce0d
601 601 Y 4:b0a5eff05604
602 602 Z 1:0d2164f0ce0d
603 603
604 604 Update a bookmark right after the initial lookup -B (issue4689)
605 605
606 606 $ echo c6 > ../pull-race/f3 # to be committed during the race
607 607 $ cat <<EOF > $TESTTMP/listkeys_makecommit.sh
608 608 > #!/bin/sh
609 609 > if hg st | grep -q M; then
610 610 > hg commit -m race
611 611 > echo committed in pull-race
612 612 > else
613 613 > exit 0
614 614 > fi
615 615 > EOF
616 616 $ cat <<EOF > ../pull-race/.hg/hgrc
617 617 > [hooks]
618 618 > # If anything to commit, commit it right after the first key listing used
619 619 > # during lookup. This makes the commit appear before the actual getbundle
620 620 > # call.
621 621 > listkeys.makecommit= sh $TESTTMP/listkeys_makecommit.sh
622 622 > EOF
623 623 $ restart_server() {
624 624 > "$TESTDIR/killdaemons.py" $DAEMON_PIDS
625 625 > hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
626 626 > cat ../pull-race.pid >> $DAEMON_PIDS
627 627 > }
628 628 $ restart_server # new config need server restart
629 629 $ hg -R $TESTTMP/pull-race book
630 630 @ 1:0d2164f0ce0d
631 631 X 1:0d2164f0ce0d
632 632 * Y 5:35d1ef0a8d1b
633 633 Z 1:0d2164f0ce0d
634 634 $ hg update -r Y
635 635 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
636 636 (activating bookmark Y)
637 637 $ hg pull -B .
638 638 pulling from http://localhost:$HGPORT/
639 639 searching for changes
640 640 adding changesets
641 641 adding manifests
642 642 adding file changes
643 643 updating bookmark Y
644 644 added 1 changesets with 1 changes to 1 files
645 645 new changesets 35d1ef0a8d1b (1 drafts)
646 646 (run 'hg update' to get a working copy)
647 647 $ hg book
648 648 @ 1:0d2164f0ce0d
649 649 X 1:0d2164f0ce0d
650 650 * Y 5:35d1ef0a8d1b
651 651 Z 1:0d2164f0ce0d
652 652
653 653 Update a bookmark right after the initial lookup -r (issue4700)
654 654
655 655 $ echo c7 > ../pull-race/f3 # to be committed during the race
656 656 $ cat <<EOF > ../lookuphook.py
657 657 > """small extensions adding a hook after wireprotocol lookup to test race"""
658 658 > import functools
659 659 > from mercurial import wireprotov1server, wireprotov2server
660 660 >
661 661 > def wrappedlookup(orig, repo, *args, **kwargs):
662 662 > ret = orig(repo, *args, **kwargs)
663 663 > repo.hook(b'lookup')
664 664 > return ret
665 665 > for table in [wireprotov1server.commands, wireprotov2server.COMMANDS]:
666 666 > table[b'lookup'].func = functools.partial(wrappedlookup, table[b'lookup'].func)
667 667 > EOF
668 668 $ cat <<EOF > ../pull-race/.hg/hgrc
669 669 > [extensions]
670 670 > lookuphook=$TESTTMP/lookuphook.py
671 671 > [hooks]
672 672 > lookup.makecommit= sh $TESTTMP/listkeys_makecommit.sh
673 673 > EOF
674 674 $ restart_server # new config need server restart
675 675 $ hg -R $TESTTMP/pull-race book
676 676 @ 1:0d2164f0ce0d
677 677 X 1:0d2164f0ce0d
678 678 * Y 6:0d60821d2197
679 679 Z 1:0d2164f0ce0d
680 680 $ hg pull -r Y
681 681 pulling from http://localhost:$HGPORT/
682 682 searching for changes
683 683 adding changesets
684 684 adding manifests
685 685 adding file changes
686 686 updating bookmark Y
687 687 added 1 changesets with 1 changes to 1 files
688 688 new changesets 0d60821d2197 (1 drafts)
689 689 (run 'hg update' to get a working copy)
690 690 $ hg book
691 691 @ 1:0d2164f0ce0d
692 692 X 1:0d2164f0ce0d
693 693 * Y 6:0d60821d2197
694 694 Z 1:0d2164f0ce0d
695 695 $ hg -R $TESTTMP/pull-race book
696 696 @ 1:0d2164f0ce0d
697 697 X 1:0d2164f0ce0d
698 698 * Y 7:714424d9e8b8
699 699 Z 1:0d2164f0ce0d
700 700
701 701 (done with this section of the test)
702 702
703 703 $ killdaemons.py
704 704 $ cd ../b
705 705
706 706 diverging a remote bookmark fails
707 707
708 708 $ hg up -q 4e3505fd9583
709 709 $ echo c4 > f2
710 710 $ hg ci -Am4
711 711 adding f2
712 712 created new head
713 713 $ echo c5 > f2
714 714 $ hg ci -Am5
715 715 $ hg log -G
716 716 @ 5:c922c0139ca0 5
717 717 |
718 718 o 4:4efff6d98829 4
719 719 |
720 720 | o 3:f6fc62dde3c0 3
721 721 |/
722 722 | o 2:0d2164f0ce0d 1
723 723 |/
724 724 | o 1:9b140be10808 2
725 725 |/
726 726 o 0:4e3505fd9583 test
727 727
728 728
729 729 $ hg book -f Y
730 730
731 731 $ cat <<EOF > ../a/.hg/hgrc
732 732 > [web]
733 733 > push_ssl = false
734 734 > allow_push = *
735 735 > EOF
736 736
737 737 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
738 738 $ cat ../hg2.pid >> $DAEMON_PIDS
739 739
740 740 $ hg push http://localhost:$HGPORT2/
741 741 pushing to http://localhost:$HGPORT2/
742 742 searching for changes
743 743 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'
744 744 (merge or see 'hg help push' for details about pushing new heads)
745 745 [20]
746 746 $ hg -R ../a book
747 747 @ 1:0d2164f0ce0d
748 748 * X 1:0d2164f0ce0d
749 749 Y 3:f6fc62dde3c0
750 750 Z 1:0d2164f0ce0d
751 751
752 752
753 753 Unrelated marker does not alter the decision
754 754
755 755 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
756 756 1 new obsolescence markers
757 757 $ hg push http://localhost:$HGPORT2/
758 758 pushing to http://localhost:$HGPORT2/
759 759 searching for changes
760 760 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'
761 761 (merge or see 'hg help push' for details about pushing new heads)
762 762 [20]
763 763 $ hg -R ../a book
764 764 @ 1:0d2164f0ce0d
765 765 * X 1:0d2164f0ce0d
766 766 Y 3:f6fc62dde3c0
767 767 Z 1:0d2164f0ce0d
768 768
769 769 Update to a successor works
770 770
771 771 $ hg id --debug -r 3
772 772 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
773 773 $ hg id --debug -r 4
774 774 4efff6d98829d9c824c621afd6e3f01865f5439f
775 775 $ hg id --debug -r 5
776 776 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
777 777 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
778 778 1 new obsolescence markers
779 779 obsoleted 1 changesets
780 780 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
781 781 1 new obsolescence markers
782 782 $ hg push http://localhost:$HGPORT2/
783 783 pushing to http://localhost:$HGPORT2/
784 784 searching for changes
785 785 remote: adding changesets
786 786 remote: adding manifests
787 787 remote: adding file changes
788 788 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
789 789 remote: 2 new obsolescence markers
790 790 remote: obsoleted 1 changesets
791 791 updating bookmark Y
792 792 $ hg -R ../a book
793 793 @ 1:0d2164f0ce0d
794 794 * X 1:0d2164f0ce0d
795 795 Y 5:c922c0139ca0
796 796 Z 1:0d2164f0ce0d
797 797
798 798 hgweb
799 799
800 800 $ cat <<EOF > .hg/hgrc
801 801 > [web]
802 802 > push_ssl = false
803 803 > allow_push = *
804 804 > EOF
805 805
806 806 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
807 807 $ cat ../hg.pid >> $DAEMON_PIDS
808 808 $ cd ../a
809 809
810 810 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
811 811 bookmarks
812 812 namespaces
813 813 obsolete
814 814 phases
815 815 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
816 816 @ 9b140be1080824d768c5a4691a564088eede71f9
817 817 X 9b140be1080824d768c5a4691a564088eede71f9
818 818 Y c922c0139ca03858f655e4a2af4dd02796a63969
819 819 Z 9b140be1080824d768c5a4691a564088eede71f9
820 820 foo 0000000000000000000000000000000000000000
821 821 foobar 9b140be1080824d768c5a4691a564088eede71f9
822 822 $ hg out -B http://localhost:$HGPORT/
823 823 comparing with http://localhost:$HGPORT/
824 824 searching for changed bookmarks
825 825 @ 0d2164f0ce0d
826 826 X 0d2164f0ce0d
827 827 Z 0d2164f0ce0d
828 828 foo
829 829 foobar
830 830 $ hg push -B Z http://localhost:$HGPORT/
831 831 pushing to http://localhost:$HGPORT/
832 832 searching for changes
833 833 no changes found
834 834 updating bookmark Z
835 835 [1]
836 836 $ hg book -d Z
837 837 $ hg in -B http://localhost:$HGPORT/
838 838 comparing with http://localhost:$HGPORT/
839 839 searching for changed bookmarks
840 840 @ 9b140be10808
841 841 X 9b140be10808
842 842 Z 0d2164f0ce0d
843 843 foo 000000000000
844 844 foobar 9b140be10808
845 845 $ hg pull -B Z http://localhost:$HGPORT/
846 846 pulling from http://localhost:$HGPORT/
847 847 no changes found
848 848 divergent bookmark @ stored as @1
849 849 divergent bookmark X stored as X@1
850 850 adding remote bookmark Z
851 851 adding remote bookmark foo
852 852 adding remote bookmark foobar
853 853 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
854 854 requesting all changes
855 855 adding changesets
856 856 adding manifests
857 857 adding file changes
858 858 added 5 changesets with 5 changes to 3 files (+2 heads)
859 859 2 new obsolescence markers
860 860 new changesets 4e3505fd9583:c922c0139ca0 (5 drafts)
861 861 updating to bookmark @
862 862 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
863 863 $ hg -R cloned-bookmarks bookmarks
864 864 * @ 1:9b140be10808
865 865 X 1:9b140be10808
866 866 Y 4:c922c0139ca0
867 867 Z 2:0d2164f0ce0d
868 868 foo -1:000000000000
869 869 foobar 1:9b140be10808
870 870
871 871 $ cd ..
872 872
873 873 Test to show result of bookmarks comparison
874 874
875 875 $ mkdir bmcomparison
876 876 $ cd bmcomparison
877 877
878 878 $ hg init source
879 879 $ hg -R source debugbuilddag '+2*2*3*4'
880 880 $ hg -R source log -G --template '{rev}:{node|short}'
881 881 o 4:e7bd5218ca15
882 882 |
883 883 | o 3:6100d3090acf
884 884 |/
885 885 | o 2:fa942426a6fd
886 886 |/
887 887 | o 1:66f7d451a68b
888 888 |/
889 889 o 0:1ea73414a91b
890 890
891 891 $ hg -R source bookmarks -r 0 SAME
892 892 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
893 893 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
894 894 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
895 895 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
896 896 $ hg -R source bookmarks -r 1 DIVERGED
897 897
898 898 $ hg clone -U source repo1
899 899
900 900 (test that incoming/outgoing exit with 1, if there is no bookmark to
901 901 be exchanged)
902 902
903 903 $ hg -R repo1 incoming -B
904 904 comparing with $TESTTMP/bmcomparison/source
905 905 searching for changed bookmarks
906 906 no changed bookmarks found
907 907 [1]
908 908 $ hg -R repo1 outgoing -B
909 909 comparing with $TESTTMP/bmcomparison/source
910 910 searching for changed bookmarks
911 911 no changed bookmarks found
912 912 [1]
913 913
914 914 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
915 915 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
916 916 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
917 917 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
918 918 $ hg -R repo1 -q --config extensions.mq= strip 4
919 919 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
920 920 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
921 921 |
922 922 | o fa942426a6fd (ADV_ON_REPO1)
923 923 |/
924 924 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
925 925 |/
926 926 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
927 927
928 928
929 929 $ hg clone -U source repo2
930 930 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
931 931 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
932 932 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
933 933 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
934 934 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
935 935 $ hg -R repo2 -q --config extensions.mq= strip 3
936 936 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
937 937 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
938 938 |
939 939 | o fa942426a6fd (DIVERGED)
940 940 |/
941 941 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
942 942 |/
943 943 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
944 944
945 945
946 946 (test that difference of bookmarks between repositories are fully shown)
947 947
948 948 $ hg -R repo1 incoming -B repo2 -v
949 949 comparing with repo2
950 950 searching for changed bookmarks
951 951 ADD_ON_REPO2 66f7d451a68b added
952 952 ADV_ON_REPO2 66f7d451a68b advanced
953 953 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
954 954 DIFF_DIVERGED e7bd5218ca15 changed
955 955 DIVERGED fa942426a6fd diverged
956 956 $ hg -R repo1 outgoing -B repo2 -v
957 957 comparing with repo2
958 958 searching for changed bookmarks
959 959 ADD_ON_REPO1 66f7d451a68b added
960 960 ADD_ON_REPO2 deleted
961 961 ADV_ON_REPO1 fa942426a6fd advanced
962 962 DIFF_ADV_ON_REPO1 6100d3090acf advanced
963 963 DIFF_ADV_ON_REPO2 1ea73414a91b changed
964 964 DIFF_DIVERGED 6100d3090acf changed
965 965 DIVERGED 66f7d451a68b diverged
966 966
967 967 $ hg -R repo2 incoming -B repo1 -v
968 968 comparing with repo1
969 969 searching for changed bookmarks
970 970 ADD_ON_REPO1 66f7d451a68b added
971 971 ADV_ON_REPO1 fa942426a6fd advanced
972 972 DIFF_ADV_ON_REPO1 6100d3090acf changed
973 973 DIFF_DIVERGED 6100d3090acf changed
974 974 DIVERGED 66f7d451a68b diverged
975 975 $ hg -R repo2 outgoing -B repo1 -v
976 976 comparing with repo1
977 977 searching for changed bookmarks
978 978 ADD_ON_REPO1 deleted
979 979 ADD_ON_REPO2 66f7d451a68b added
980 980 ADV_ON_REPO2 66f7d451a68b advanced
981 981 DIFF_ADV_ON_REPO1 1ea73414a91b changed
982 982 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
983 983 DIFF_DIVERGED e7bd5218ca15 changed
984 984 DIVERGED fa942426a6fd diverged
985 985
986 986 $ cd ..
987 987
988 988 Pushing a bookmark should only push the changes required by that
989 989 bookmark, not all outgoing changes:
990 990 $ hg clone http://localhost:$HGPORT/ addmarks
991 991 requesting all changes
992 992 adding changesets
993 993 adding manifests
994 994 adding file changes
995 995 added 5 changesets with 5 changes to 3 files (+2 heads)
996 996 2 new obsolescence markers
997 997 new changesets 4e3505fd9583:c922c0139ca0 (5 drafts)
998 998 updating to bookmark @
999 999 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1000 1000 $ cd addmarks
1001 1001 $ echo foo > foo
1002 1002 $ hg add foo
1003 1003 $ hg commit -m 'add foo'
1004 1004 $ echo bar > bar
1005 1005 $ hg add bar
1006 1006 $ hg commit -m 'add bar'
1007 1007 $ hg co "tip^"
1008 1008 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1009 1009 (leaving bookmark @)
1010 1010 $ hg book add-foo
1011 1011 $ hg book -r tip add-bar
1012 1012 Note: this push *must* push only a single changeset, as that's the point
1013 1013 of this test.
1014 1014 $ hg push -B add-foo --traceback
1015 1015 pushing to http://localhost:$HGPORT/
1016 1016 searching for changes
1017 1017 remote: adding changesets
1018 1018 remote: adding manifests
1019 1019 remote: adding file changes
1020 1020 remote: added 1 changesets with 1 changes to 1 files
1021 1021 exporting bookmark add-foo
1022 1022
1023 1023 pushing a new bookmark on a new head does not require -f if -B is specified
1024 1024
1025 1025 $ hg up -q X
1026 1026 $ hg book W
1027 1027 $ echo c5 > f2
1028 1028 $ hg ci -Am5
1029 1029 created new head
1030 1030 $ hg push -B .
1031 1031 pushing to http://localhost:$HGPORT/
1032 1032 searching for changes
1033 1033 remote: adding changesets
1034 1034 remote: adding manifests
1035 1035 remote: adding file changes
1036 1036 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
1037 1037 exporting bookmark W
1038 1038 $ hg -R ../b id -r W
1039 1039 cc978a373a53 tip W
1040 1040
1041 1041 pushing an existing but divergent bookmark with -B still requires -f
1042 1042
1043 1043 $ hg clone -q . ../r
1044 1044 $ hg up -q X
1045 1045 $ echo 1 > f2
1046 1046 $ hg ci -qAml
1047 1047
1048 1048 $ cd ../r
1049 1049 $ hg up -q X
1050 1050 $ echo 2 > f2
1051 1051 $ hg ci -qAmr
1052 1052 $ hg push -B X
1053 1053 pushing to $TESTTMP/addmarks
1054 1054 searching for changes
1055 1055 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
1056 1056 abort: push creates new remote head 54694f811df9 with bookmark 'X'
1057 1057 (pull and merge or see 'hg help push' for details about pushing new heads)
1058 1058 [20]
1059 1059 $ cd ../addmarks
1060 1060
1061 1061 Check summary output for incoming/outgoing bookmarks
1062 1062
1063 1063 $ hg bookmarks -d X
1064 1064 $ hg bookmarks -d Y
1065 1065 $ hg summary --remote | grep '^remote:'
1066 1066 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
1067 1067
1068 1068 $ cd ..
1069 1069
1070 1070 pushing an unchanged bookmark should result in no changes
1071 1071
1072 1072 $ hg init unchanged-a
1073 1073 $ hg init unchanged-b
1074 1074 $ cd unchanged-a
1075 1075 $ echo initial > foo
1076 1076 $ hg commit -A -m initial
1077 1077 adding foo
1078 1078 $ hg bookmark @
1079 1079 $ hg push -B @ ../unchanged-b
1080 1080 pushing to ../unchanged-b
1081 1081 searching for changes
1082 1082 adding changesets
1083 1083 adding manifests
1084 1084 adding file changes
1085 1085 added 1 changesets with 1 changes to 1 files
1086 1086 exporting bookmark @
1087 1087
1088 1088 $ hg push -B @ ../unchanged-b
1089 1089 pushing to ../unchanged-b
1090 1090 searching for changes
1091 1091 no changes found
1092 1092 [1]
1093 1093
1094 1094 Pushing a really long bookmark should work fine (issue5165)
1095 1095 ===============================================
1096 1096
1097 1097 #if b2-binary
1098 1098 >>> with open('longname', 'w') as f:
1099 1099 ... f.write('wat' * 100) and None
1100 1100 $ hg book `cat longname`
1101 1101 $ hg push -B `cat longname` ../unchanged-b
1102 1102 pushing to ../unchanged-b
1103 1103 searching for changes
1104 1104 no changes found
1105 1105 exporting bookmark (wat){100} (re)
1106 1106 [1]
1107 1107 $ hg -R ../unchanged-b book --delete `cat longname`
1108 1108
1109 1109 Test again but forcing bundle2 exchange to make sure that doesn't regress.
1110 1110
1111 1111 $ hg push -B `cat longname` ../unchanged-b --config devel.legacy.exchange=bundle1
1112 1112 pushing to ../unchanged-b
1113 1113 searching for changes
1114 1114 no changes found
1115 1115 exporting bookmark (wat){100} (re)
1116 1116 [1]
1117 1117 $ hg -R ../unchanged-b book --delete `cat longname`
1118 1118 $ hg book --delete `cat longname`
1119 1119 $ hg co @
1120 1120 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1121 1121 (activating bookmark @)
1122 1122 #endif
1123 1123
1124 1124 Check hook preventing push (issue4455)
1125 1125 ======================================
1126 1126
1127 1127 $ hg bookmarks
1128 1128 * @ 0:55482a6fb4b1
1129 1129 $ hg log -G
1130 1130 @ 0:55482a6fb4b1 initial
1131 1131
1132 1132 $ hg init ../issue4455-dest
1133 1133 $ hg push ../issue4455-dest # changesets only
1134 1134 pushing to ../issue4455-dest
1135 1135 searching for changes
1136 1136 adding changesets
1137 1137 adding manifests
1138 1138 adding file changes
1139 1139 added 1 changesets with 1 changes to 1 files
1140 1140 $ cat >> .hg/hgrc << EOF
1141 1141 > [paths]
1142 1142 > local=../issue4455-dest/
1143 1143 > ssh=ssh://user@dummy/issue4455-dest
1144 1144 > http=http://localhost:$HGPORT/
1145 1145 > [ui]
1146 1146 > ssh="$PYTHON" "$TESTDIR/dummyssh"
1147 1147 > EOF
1148 1148 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
1149 1149 > [hooks]
1150 1150 > prepushkey=false
1151 1151 > [web]
1152 1152 > push_ssl = false
1153 1153 > allow_push = *
1154 1154 > EOF
1155 1155 $ killdaemons.py
1156 1156 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
1157 1157 $ cat ../issue4455.pid >> $DAEMON_PIDS
1158 1158
1159 1159 Local push
1160 1160 ----------
1161 1161
1162 1162 #if b2-pushkey
1163 1163
1164 1164 $ hg push -B @ local
1165 1165 pushing to $TESTTMP/issue4455-dest
1166 1166 searching for changes
1167 1167 no changes found
1168 1168 pushkey-abort: prepushkey hook exited with status 1
1169 1169 abort: exporting bookmark @ failed
1170 1170 [255]
1171 1171
1172 1172 #endif
1173 1173 #if b2-binary
1174 1174
1175 1175 $ hg push -B @ local
1176 1176 pushing to $TESTTMP/issue4455-dest
1177 1177 searching for changes
1178 1178 no changes found
1179 1179 abort: prepushkey hook exited with status 1
1180 1180 [40]
1181 1181
1182 1182 #endif
1183 1183
1184 1184 $ hg -R ../issue4455-dest/ bookmarks
1185 1185 no bookmarks set
1186 1186
1187 1187 Using ssh
1188 1188 ---------
1189 1189
1190 1190 #if b2-pushkey
1191 1191
1192 1192 $ hg push -B @ ssh # bundle2+
1193 1193 pushing to ssh://user@dummy/issue4455-dest
1194 1194 searching for changes
1195 1195 no changes found
1196 1196 remote: pushkey-abort: prepushkey hook exited with status 1
1197 1197 abort: exporting bookmark @ failed
1198 1198 [255]
1199 1199
1200 1200 $ hg -R ../issue4455-dest/ bookmarks
1201 1201 no bookmarks set
1202 1202
1203 1203 $ hg push -B @ ssh --config devel.legacy.exchange=bundle1
1204 1204 pushing to ssh://user@dummy/issue4455-dest
1205 1205 searching for changes
1206 1206 no changes found
1207 1207 remote: pushkey-abort: prepushkey hook exited with status 1
1208 1208 exporting bookmark @ failed
1209 1209 [1]
1210 1210
1211 1211 #endif
1212 1212 #if b2-binary
1213 1213
1214 1214 $ hg push -B @ ssh # bundle2+
1215 1215 pushing to ssh://user@dummy/issue4455-dest
1216 1216 searching for changes
1217 1217 no changes found
1218 1218 remote: prepushkey hook exited with status 1
1219 1219 abort: push failed on remote
1220 1220 [255]
1221 1221
1222 1222 #endif
1223 1223
1224 1224 $ hg -R ../issue4455-dest/ bookmarks
1225 1225 no bookmarks set
1226 1226
1227 1227 Using http
1228 1228 ----------
1229 1229
1230 1230 #if b2-pushkey
1231 1231 $ hg push -B @ http # bundle2+
1232 1232 pushing to http://localhost:$HGPORT/
1233 1233 searching for changes
1234 1234 no changes found
1235 1235 remote: pushkey-abort: prepushkey hook exited with status 1
1236 1236 abort: exporting bookmark @ failed
1237 1237 [255]
1238 1238
1239 1239 $ hg -R ../issue4455-dest/ bookmarks
1240 1240 no bookmarks set
1241 1241
1242 1242 $ hg push -B @ http --config devel.legacy.exchange=bundle1
1243 1243 pushing to http://localhost:$HGPORT/
1244 1244 searching for changes
1245 1245 no changes found
1246 1246 remote: pushkey-abort: prepushkey hook exited with status 1
1247 1247 exporting bookmark @ failed
1248 1248 [1]
1249 1249
1250 1250 #endif
1251 1251
1252 1252 #if b2-binary
1253 1253
1254 1254 $ hg push -B @ ssh # bundle2+
1255 1255 pushing to ssh://user@dummy/issue4455-dest
1256 1256 searching for changes
1257 1257 no changes found
1258 1258 remote: prepushkey hook exited with status 1
1259 1259 abort: push failed on remote
1260 1260 [255]
1261 1261
1262 1262 #endif
1263 1263
1264 1264 $ hg -R ../issue4455-dest/ bookmarks
1265 1265 no bookmarks set
1266 1266
1267 1267 $ cd ..
1268 1268
1269 1269 Test that pre-pushkey compat for bookmark works as expected (issue5777)
1270 1270
1271 1271 $ cat << EOF >> $HGRCPATH
1272 1272 > [ui]
1273 1273 > ssh="$PYTHON" "$TESTDIR/dummyssh"
1274 1274 > [server]
1275 1275 > bookmarks-pushkey-compat = yes
1276 1276 > EOF
1277 1277
1278 1278 $ hg init server
1279 1279 $ echo foo > server/a
1280 1280 $ hg -R server book foo
1281 1281 $ hg -R server commit -Am a
1282 1282 adding a
1283 1283 $ hg clone ssh://user@dummy/server client
1284 1284 requesting all changes
1285 1285 adding changesets
1286 1286 adding manifests
1287 1287 adding file changes
1288 1288 added 1 changesets with 1 changes to 1 files
1289 1289 new changesets 79513d0d7716 (1 drafts)
1290 1290 updating to branch default
1291 1291 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1292 1292
1293 1293 Forbid bookmark move on the server
1294 1294
1295 1295 $ cat << EOF >> $TESTTMP/no-bm-move.sh
1296 1296 > #!/bin/sh
1297 1297 > echo \$HG_NAMESPACE | grep -v bookmarks
1298 1298 > EOF
1299 1299 $ cat << EOF >> server/.hg/hgrc
1300 1300 > [hooks]
1301 1301 > prepushkey.no-bm-move= sh $TESTTMP/no-bm-move.sh
1302 1302 > EOF
1303 1303
1304 1304 pushing changeset is okay
1305 1305
1306 1306 $ echo bar >> client/a
1307 1307 $ hg -R client commit -m b
1308 1308 $ hg -R client push
1309 1309 pushing to ssh://user@dummy/server
1310 1310 searching for changes
1311 1311 remote: adding changesets
1312 1312 remote: adding manifests
1313 1313 remote: adding file changes
1314 1314 remote: added 1 changesets with 1 changes to 1 files
1315 1315
1316 1316 attempt to move the bookmark is rejected
1317 1317
1318 1318 $ hg -R client book foo -r .
1319 1319 moving bookmark 'foo' forward from 79513d0d7716
1320 1320
1321 1321 #if b2-pushkey
1322 1322 $ hg -R client push
1323 1323 pushing to ssh://user@dummy/server
1324 1324 searching for changes
1325 1325 no changes found
1326 1326 remote: pushkey-abort: prepushkey.no-bm-move hook exited with status 1
1327 1327 abort: updating bookmark foo failed
1328 1328 [255]
1329 1329 #endif
1330 1330 #if b2-binary
1331 1331 $ hg -R client push
1332 1332 pushing to ssh://user@dummy/server
1333 1333 searching for changes
1334 1334 no changes found
1335 1335 remote: prepushkey.no-bm-move hook exited with status 1
1336 1336 abort: push failed on remote
1337 1337 [255]
1338 1338 #endif
1339 1339
1340 1340 -- test for pushing bookmarks pointing to secret changesets
1341 1341
1342 1342 Set up a "remote" repo
1343 1343 $ hg init issue6159remote
1344 1344 $ cd issue6159remote
1345 1345 $ echo a > a
1346 1346 $ hg add a
1347 1347 $ hg commit -m_
1348 1348 $ hg bookmark foo
1349 1349 $ cd ..
1350 1350
1351 1351 Clone a local repo
1352 1352 $ hg clone -q issue6159remote issue6159local
1353 1353 $ cd issue6159local
1354 1354 $ hg up -qr foo
1355 1355 $ echo b > b
1356 1356
1357 1357 Move the bookmark "foo" to point at a secret changeset
1358 1358 $ hg commit -qAm_ --config phases.new-commit=secret
1359 1359
1360 1360 Pushing the bookmark "foo" now fails as it contains a secret changeset
1361 1361 $ hg push -r foo
1362 1362 pushing to $TESTTMP/issue6159remote
1363 1363 searching for changes
1364 1364 no changes found (ignored 1 secret changesets)
1365 1365 abort: cannot push bookmark foo as it points to a secret changeset
1366 1366 [255]
1367 1367
1368 1368 Test pushing all bookmarks
1369 1369
1370 1370 $ hg init $TESTTMP/ab1
1371 1371 $ cd $TESTTMP/ab1
1372 1372 $ "$PYTHON" $TESTDIR/seq.py 1 5 | while read i; do
1373 1373 > echo $i > test && hg ci -Am test
1374 1374 > done
1375 1375 adding test
1376 1376 $ hg clone -U . ../ab2
1377 1377 $ hg book -r 1 A; hg book -r 2 B; hg book -r 3 C
1378 1378 $ hg push ../ab2
1379 1379 pushing to ../ab2
1380 1380 searching for changes
1381 1381 no changes found
1382 1382 [1]
1383 1383 $ hg push --all-bookmarks -r 1 ../ab2
1384 1384 abort: cannot specify both --all-bookmarks and --rev
1385 1385 [10]
1386 1386 $ hg push --all-bookmarks -B A ../ab2
1387 1387 abort: cannot specify both --all-bookmarks and --bookmark
1388 1388 [10]
1389 1389 $ hg push --all-bookmarks ../ab2
1390 1390 pushing to ../ab2
1391 1391 searching for changes
1392 1392 no changes found
1393 1393 exporting bookmark A
1394 1394 exporting bookmark B
1395 1395 exporting bookmark C
1396 1396 [1]
@@ -1,582 +1,580 b''
1 1 #require serve no-reposimplestore no-chg
2 2
3 3 #testcases stream-legacy stream-bundle2
4 4
5 5 #if stream-legacy
6 6 $ cat << EOF >> $HGRCPATH
7 7 > [server]
8 8 > bundle2.stream = no
9 9 > EOF
10 10 #endif
11 11
12 12 Initialize repository
13 13 the status call is to check for issue5130
14 14
15 15 $ hg init server
16 16 $ cd server
17 17 $ touch foo
18 18 $ hg -q commit -A -m initial
19 19 >>> for i in range(1024):
20 20 ... with open(str(i), 'wb') as fh:
21 21 ... fh.write(b"%d" % i) and None
22 22 $ hg -q commit -A -m 'add a lot of files'
23 23 $ hg st
24 24 $ hg --config server.uncompressed=false serve -p $HGPORT -d --pid-file=hg.pid
25 25 $ cat hg.pid > $DAEMON_PIDS
26 26 $ cd ..
27 27
28 28 Cannot stream clone when server.uncompressed is set
29 29
30 30 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out'
31 31 200 Script output follows
32 32
33 33 1
34 34
35 35 #if stream-legacy
36 36 $ hg debugcapabilities http://localhost:$HGPORT
37 37 Main capabilities:
38 38 batch
39 39 branchmap
40 40 $USUAL_BUNDLE2_CAPS_SERVER$
41 41 changegroupsubset
42 42 compression=$BUNDLE2_COMPRESSIONS$
43 43 getbundle
44 44 httpheader=1024
45 45 httpmediatype=0.1rx,0.1tx,0.2tx
46 46 known
47 47 lookup
48 48 pushkey
49 49 unbundle=HG10GZ,HG10BZ,HG10UN
50 50 unbundlehash
51 51 Bundle2 capabilities:
52 52 HG20
53 53 bookmarks
54 54 changegroup
55 55 01
56 56 02
57 57 checkheads
58 58 related
59 59 digests
60 60 md5
61 61 sha1
62 62 sha512
63 63 error
64 64 abort
65 65 unsupportedcontent
66 66 pushraced
67 67 pushkey
68 68 hgtagsfnodes
69 69 listkeys
70 70 phases
71 71 heads
72 72 pushkey
73 73 remote-changegroup
74 74 http
75 75 https
76 rev-branch-cache
77 76
78 77 $ hg clone --stream -U http://localhost:$HGPORT server-disabled
79 78 warning: stream clone requested but server has them disabled
80 79 requesting all changes
81 80 adding changesets
82 81 adding manifests
83 82 adding file changes
84 83 added 2 changesets with 1025 changes to 1025 files
85 84 new changesets 96ee1d7354c4:c17445101a72
86 85
87 86 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
88 87 200 Script output follows
89 88 content-type: application/mercurial-0.2
90 89
91 90
92 91 $ f --size body --hexdump --bytes 100
93 92 body: size=232
94 93 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
95 94 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...|
96 95 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest|
97 96 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques|
98 97 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d|
99 98 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th|
100 99 0060: 69 73 20 66 |is f|
101 100
102 101 #endif
103 102 #if stream-bundle2
104 103 $ hg debugcapabilities http://localhost:$HGPORT
105 104 Main capabilities:
106 105 batch
107 106 branchmap
108 107 $USUAL_BUNDLE2_CAPS_SERVER$
109 108 changegroupsubset
110 109 compression=$BUNDLE2_COMPRESSIONS$
111 110 getbundle
112 111 httpheader=1024
113 112 httpmediatype=0.1rx,0.1tx,0.2tx
114 113 known
115 114 lookup
116 115 pushkey
117 116 unbundle=HG10GZ,HG10BZ,HG10UN
118 117 unbundlehash
119 118 Bundle2 capabilities:
120 119 HG20
121 120 bookmarks
122 121 changegroup
123 122 01
124 123 02
125 124 checkheads
126 125 related
127 126 digests
128 127 md5
129 128 sha1
130 129 sha512
131 130 error
132 131 abort
133 132 unsupportedcontent
134 133 pushraced
135 134 pushkey
136 135 hgtagsfnodes
137 136 listkeys
138 137 phases
139 138 heads
140 139 pushkey
141 140 remote-changegroup
142 141 http
143 142 https
144 rev-branch-cache
145 143
146 144 $ hg clone --stream -U http://localhost:$HGPORT server-disabled
147 145 warning: stream clone requested but server has them disabled
148 146 requesting all changes
149 147 adding changesets
150 148 adding manifests
151 149 adding file changes
152 150 added 2 changesets with 1025 changes to 1025 files
153 151 new changesets 96ee1d7354c4:c17445101a72
154 152
155 153 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
156 154 200 Script output follows
157 155 content-type: application/mercurial-0.2
158 156
159 157
160 158 $ f --size body --hexdump --bytes 100
161 159 body: size=232
162 160 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
163 161 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...|
164 162 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest|
165 163 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques|
166 164 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d|
167 165 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th|
168 166 0060: 69 73 20 66 |is f|
169 167
170 168 #endif
171 169
172 170 $ killdaemons.py
173 171 $ cd server
174 172 $ hg serve -p $HGPORT -d --pid-file=hg.pid
175 173 $ cat hg.pid > $DAEMON_PIDS
176 174 $ cd ..
177 175
178 176 Basic clone
179 177
180 178 #if stream-legacy
181 179 $ hg clone --stream -U http://localhost:$HGPORT clone1
182 180 streaming all changes
183 181 1027 files to transfer, 96.3 KB of data
184 182 transferred 96.3 KB in * seconds (*/sec) (glob)
185 183 searching for changes
186 184 no changes found
187 185 #endif
188 186 #if stream-bundle2
189 187 $ hg clone --stream -U http://localhost:$HGPORT clone1
190 188 streaming all changes
191 189 1030 files to transfer, 96.5 KB of data
192 190 transferred 96.5 KB in * seconds (* */sec) (glob)
193 191
194 192 $ ls -1 clone1/.hg/cache
195 193 branch2-base
196 194 branch2-immutable
197 195 branch2-served
198 196 branch2-served.hidden
199 197 branch2-visible
200 198 branch2-visible-hidden
201 199 hgtagsfnodes1
202 200 rbc-names-v1
203 201 rbc-revs-v1
204 202 tags2
205 203 tags2-served
206 204 #endif
207 205
208 206 getbundle requests with stream=1 are uncompressed
209 207
210 208 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto '0.1 0.2 comp=zlib,none' --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
211 209 200 Script output follows
212 210 content-type: application/mercurial-0.2
213 211
214 212
215 213 $ f --size --hex --bytes 256 body
216 214 body: size=112262
217 215 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
218 216 0010: 7f 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |..STREAM2.......|
219 217 0020: 05 09 04 0c 44 62 79 74 65 63 6f 75 6e 74 39 38 |....Dbytecount98|
220 218 0030: 37 37 35 66 69 6c 65 63 6f 75 6e 74 31 30 33 30 |775filecount1030|
221 219 0040: 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 65 |requirementsdote|
222 220 0050: 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 25 |ncode%2Cfncache%|
223 221 0060: 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 32 |2Cgeneraldelta%2|
224 222 0070: 43 72 65 76 6c 6f 67 76 31 25 32 43 73 70 61 72 |Crevlogv1%2Cspar|
225 223 0080: 73 65 72 65 76 6c 6f 67 25 32 43 73 74 6f 72 65 |serevlog%2Cstore|
226 224 0090: 00 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 00 |....s.Bdata/0.i.|
227 225 00a0: 03 00 01 00 00 00 00 00 00 00 02 00 00 00 01 00 |................|
228 226 00b0: 00 00 00 00 00 00 01 ff ff ff ff ff ff ff ff 80 |................|
229 227 00c0: 29 63 a0 49 d3 23 87 bf ce fe 56 67 92 67 2c 69 |)c.I.#....Vg.g,i|
230 228 00d0: d1 ec 39 00 00 00 00 00 00 00 00 00 00 00 00 75 |..9............u|
231 229 00e0: 30 73 08 42 64 61 74 61 2f 31 2e 69 00 03 00 01 |0s.Bdata/1.i....|
232 230 00f0: 00 00 00 00 00 00 00 02 00 00 00 01 00 00 00 00 |................|
233 231
234 232 --uncompressed is an alias to --stream
235 233
236 234 #if stream-legacy
237 235 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed
238 236 streaming all changes
239 237 1027 files to transfer, 96.3 KB of data
240 238 transferred 96.3 KB in * seconds (*/sec) (glob)
241 239 searching for changes
242 240 no changes found
243 241 #endif
244 242 #if stream-bundle2
245 243 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed
246 244 streaming all changes
247 245 1030 files to transfer, 96.5 KB of data
248 246 transferred 96.5 KB in * seconds (* */sec) (glob)
249 247 #endif
250 248
251 249 Clone with background file closing enabled
252 250
253 251 #if stream-legacy
254 252 $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding
255 253 using http://localhost:$HGPORT/
256 254 sending capabilities command
257 255 sending branchmap command
258 256 streaming all changes
259 257 sending stream_out command
260 258 1027 files to transfer, 96.3 KB of data
261 259 starting 4 threads for background file closing
262 260 updating the branch cache
263 261 transferred 96.3 KB in * seconds (*/sec) (glob)
264 262 query 1; heads
265 263 sending batch command
266 264 searching for changes
267 265 all remote heads known locally
268 266 no changes found
269 267 sending getbundle command
270 268 bundle2-input-bundle: with-transaction
271 269 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
272 270 bundle2-input-part: "phase-heads" supported
273 271 bundle2-input-part: total payload size 24
274 272 bundle2-input-bundle: 2 parts total
275 273 checking for updated bookmarks
276 274 updating the branch cache
277 275 (sent 5 HTTP requests and * bytes; received * bytes in responses) (glob)
278 276 #endif
279 277 #if stream-bundle2
280 278 $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding
281 279 using http://localhost:$HGPORT/
282 280 sending capabilities command
283 281 query 1; heads
284 282 sending batch command
285 283 streaming all changes
286 284 sending getbundle command
287 285 bundle2-input-bundle: with-transaction
288 286 bundle2-input-part: "stream2" (params: 3 mandatory) supported
289 287 applying stream bundle
290 288 1030 files to transfer, 96.5 KB of data
291 289 starting 4 threads for background file closing
292 290 starting 4 threads for background file closing
293 291 updating the branch cache
294 292 transferred 96.5 KB in * seconds (* */sec) (glob)
295 293 bundle2-input-part: total payload size 112094
296 294 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
297 295 bundle2-input-bundle: 2 parts total
298 296 checking for updated bookmarks
299 297 updating the branch cache
300 298 (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob)
301 299 #endif
302 300
303 301 Cannot stream clone when there are secret changesets
304 302
305 303 $ hg -R server phase --force --secret -r tip
306 304 $ hg clone --stream -U http://localhost:$HGPORT secret-denied
307 305 warning: stream clone requested but server has them disabled
308 306 requesting all changes
309 307 adding changesets
310 308 adding manifests
311 309 adding file changes
312 310 added 1 changesets with 1 changes to 1 files
313 311 new changesets 96ee1d7354c4
314 312
315 313 $ killdaemons.py
316 314
317 315 Streaming of secrets can be overridden by server config
318 316
319 317 $ cd server
320 318 $ hg serve --config server.uncompressedallowsecret=true -p $HGPORT -d --pid-file=hg.pid
321 319 $ cat hg.pid > $DAEMON_PIDS
322 320 $ cd ..
323 321
324 322 #if stream-legacy
325 323 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed
326 324 streaming all changes
327 325 1027 files to transfer, 96.3 KB of data
328 326 transferred 96.3 KB in * seconds (*/sec) (glob)
329 327 searching for changes
330 328 no changes found
331 329 #endif
332 330 #if stream-bundle2
333 331 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed
334 332 streaming all changes
335 333 1030 files to transfer, 96.5 KB of data
336 334 transferred 96.5 KB in * seconds (* */sec) (glob)
337 335 #endif
338 336
339 337 $ killdaemons.py
340 338
341 339 Verify interaction between preferuncompressed and secret presence
342 340
343 341 $ cd server
344 342 $ hg serve --config server.preferuncompressed=true -p $HGPORT -d --pid-file=hg.pid
345 343 $ cat hg.pid > $DAEMON_PIDS
346 344 $ cd ..
347 345
348 346 $ hg clone -U http://localhost:$HGPORT preferuncompressed-secret
349 347 requesting all changes
350 348 adding changesets
351 349 adding manifests
352 350 adding file changes
353 351 added 1 changesets with 1 changes to 1 files
354 352 new changesets 96ee1d7354c4
355 353
356 354 $ killdaemons.py
357 355
358 356 Clone not allowed when full bundles disabled and can't serve secrets
359 357
360 358 $ cd server
361 359 $ hg serve --config server.disablefullbundle=true -p $HGPORT -d --pid-file=hg.pid
362 360 $ cat hg.pid > $DAEMON_PIDS
363 361 $ cd ..
364 362
365 363 $ hg clone --stream http://localhost:$HGPORT secret-full-disabled
366 364 warning: stream clone requested but server has them disabled
367 365 requesting all changes
368 366 remote: abort: server has pull-based clones disabled
369 367 abort: pull failed on remote
370 368 (remove --pull if specified or upgrade Mercurial)
371 369 [255]
372 370
373 371 Local stream clone with secrets involved
374 372 (This is just a test over behavior: if you have access to the repo's files,
375 373 there is no security so it isn't important to prevent a clone here.)
376 374
377 375 $ hg clone -U --stream server local-secret
378 376 warning: stream clone requested but server has them disabled
379 377 requesting all changes
380 378 adding changesets
381 379 adding manifests
382 380 adding file changes
383 381 added 1 changesets with 1 changes to 1 files
384 382 new changesets 96ee1d7354c4
385 383
386 384 Stream clone while repo is changing:
387 385
388 386 $ mkdir changing
389 387 $ cd changing
390 388
391 389 extension for delaying the server process so we reliably can modify the repo
392 390 while cloning
393 391
394 392 $ cat > delayer.py <<EOF
395 393 > import time
396 394 > from mercurial import extensions, vfs
397 395 > def __call__(orig, self, path, *args, **kwargs):
398 396 > if path == 'data/f1.i':
399 397 > time.sleep(2)
400 398 > return orig(self, path, *args, **kwargs)
401 399 > extensions.wrapfunction(vfs.vfs, '__call__', __call__)
402 400 > EOF
403 401
404 402 prepare repo with small and big file to cover both code paths in emitrevlogdata
405 403
406 404 $ hg init repo
407 405 $ touch repo/f1
408 406 $ $TESTDIR/seq.py 50000 > repo/f2
409 407 $ hg -R repo ci -Aqm "0"
410 408 $ hg serve -R repo -p $HGPORT1 -d --pid-file=hg.pid --config extensions.delayer=delayer.py
411 409 $ cat hg.pid >> $DAEMON_PIDS
412 410
413 411 clone while modifying the repo between stating file with write lock and
414 412 actually serving file content
415 413
416 414 $ hg clone -q --stream -U http://localhost:$HGPORT1 clone &
417 415 $ sleep 1
418 416 $ echo >> repo/f1
419 417 $ echo >> repo/f2
420 418 $ hg -R repo ci -m "1" --config ui.timeout.warn=-1
421 419 $ wait
422 420 $ hg -R clone id
423 421 000000000000
424 422 $ cd ..
425 423
426 424 Stream repository with bookmarks
427 425 --------------------------------
428 426
429 427 (revert introduction of secret changeset)
430 428
431 429 $ hg -R server phase --draft 'secret()'
432 430
433 431 add a bookmark
434 432
435 433 $ hg -R server bookmark -r tip some-bookmark
436 434
437 435 clone it
438 436
439 437 #if stream-legacy
440 438 $ hg clone --stream http://localhost:$HGPORT with-bookmarks
441 439 streaming all changes
442 440 1027 files to transfer, 96.3 KB of data
443 441 transferred 96.3 KB in * seconds (*) (glob)
444 442 searching for changes
445 443 no changes found
446 444 updating to branch default
447 445 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
448 446 #endif
449 447 #if stream-bundle2
450 448 $ hg clone --stream http://localhost:$HGPORT with-bookmarks
451 449 streaming all changes
452 450 1033 files to transfer, 96.6 KB of data
453 451 transferred 96.6 KB in * seconds (* */sec) (glob)
454 452 updating to branch default
455 453 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
456 454 #endif
457 455 $ hg -R with-bookmarks bookmarks
458 456 some-bookmark 1:c17445101a72
459 457
460 458 Stream repository with phases
461 459 -----------------------------
462 460
463 461 Clone as publishing
464 462
465 463 $ hg -R server phase -r 'all()'
466 464 0: draft
467 465 1: draft
468 466
469 467 #if stream-legacy
470 468 $ hg clone --stream http://localhost:$HGPORT phase-publish
471 469 streaming all changes
472 470 1027 files to transfer, 96.3 KB of data
473 471 transferred 96.3 KB in * seconds (*) (glob)
474 472 searching for changes
475 473 no changes found
476 474 updating to branch default
477 475 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
478 476 #endif
479 477 #if stream-bundle2
480 478 $ hg clone --stream http://localhost:$HGPORT phase-publish
481 479 streaming all changes
482 480 1033 files to transfer, 96.6 KB of data
483 481 transferred 96.6 KB in * seconds (* */sec) (glob)
484 482 updating to branch default
485 483 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
486 484 #endif
487 485 $ hg -R phase-publish phase -r 'all()'
488 486 0: public
489 487 1: public
490 488
491 489 Clone as non publishing
492 490
493 491 $ cat << EOF >> server/.hg/hgrc
494 492 > [phases]
495 493 > publish = False
496 494 > EOF
497 495 $ killdaemons.py
498 496 $ hg -R server serve -p $HGPORT -d --pid-file=hg.pid
499 497 $ cat hg.pid > $DAEMON_PIDS
500 498
501 499 #if stream-legacy
502 500
503 501 With v1 of the stream protocol, changeset are always cloned as public. It make
504 502 stream v1 unsuitable for non-publishing repository.
505 503
506 504 $ hg clone --stream http://localhost:$HGPORT phase-no-publish
507 505 streaming all changes
508 506 1027 files to transfer, 96.3 KB of data
509 507 transferred 96.3 KB in * seconds (*) (glob)
510 508 searching for changes
511 509 no changes found
512 510 updating to branch default
513 511 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
514 512 $ hg -R phase-no-publish phase -r 'all()'
515 513 0: public
516 514 1: public
517 515 #endif
518 516 #if stream-bundle2
519 517 $ hg clone --stream http://localhost:$HGPORT phase-no-publish
520 518 streaming all changes
521 519 1034 files to transfer, 96.7 KB of data
522 520 transferred 96.7 KB in * seconds (* */sec) (glob)
523 521 updating to branch default
524 522 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
525 523 $ hg -R phase-no-publish phase -r 'all()'
526 524 0: draft
527 525 1: draft
528 526 #endif
529 527
530 528 $ killdaemons.py
531 529
532 530 #if stream-legacy
533 531
534 532 With v1 of the stream protocol, changeset are always cloned as public. There's
535 533 no obsolescence markers exchange in stream v1.
536 534
537 535 #endif
538 536 #if stream-bundle2
539 537
540 538 Stream repository with obsolescence
541 539 -----------------------------------
542 540
543 541 Clone non-publishing with obsolescence
544 542
545 543 $ cat >> $HGRCPATH << EOF
546 544 > [experimental]
547 545 > evolution=all
548 546 > EOF
549 547
550 548 $ cd server
551 549 $ echo foo > foo
552 550 $ hg -q commit -m 'about to be pruned'
553 551 $ hg debugobsolete `hg log -r . -T '{node}'` -d '0 0' -u test --record-parents
554 552 1 new obsolescence markers
555 553 obsoleted 1 changesets
556 554 $ hg up null -q
557 555 $ hg log -T '{rev}: {phase}\n'
558 556 1: draft
559 557 0: draft
560 558 $ hg serve -p $HGPORT -d --pid-file=hg.pid
561 559 $ cat hg.pid > $DAEMON_PIDS
562 560 $ cd ..
563 561
564 562 $ hg clone -U --stream http://localhost:$HGPORT with-obsolescence
565 563 streaming all changes
566 564 1035 files to transfer, 97.1 KB of data
567 565 transferred 97.1 KB in * seconds (* */sec) (glob)
568 566 $ hg -R with-obsolescence log -T '{rev}: {phase}\n'
569 567 1: draft
570 568 0: draft
571 569 $ hg debugobsolete -R with-obsolescence
572 570 50382b884f66690b7045cac93a540cba4d4c906f 0 {c17445101a72edac06facd130d14808dfbd5c7c2} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
573 571
574 572 $ hg clone -U --stream --config experimental.evolution=0 http://localhost:$HGPORT with-obsolescence-no-evolution
575 573 streaming all changes
576 574 remote: abort: server has obsolescence markers, but client cannot receive them via stream clone
577 575 abort: pull failed on remote
578 576 [255]
579 577
580 578 $ killdaemons.py
581 579
582 580 #endif
@@ -1,640 +1,638 b''
1 1 #require no-reposimplestore no-chg
2 2
3 3 Set up a server
4 4
5 5 $ hg init server
6 6 $ cd server
7 7 $ cat >> .hg/hgrc << EOF
8 8 > [extensions]
9 9 > clonebundles =
10 10 > EOF
11 11
12 12 $ touch foo
13 13 $ hg -q commit -A -m 'add foo'
14 14 $ touch bar
15 15 $ hg -q commit -A -m 'add bar'
16 16
17 17 $ hg serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
18 18 $ cat hg.pid >> $DAEMON_PIDS
19 19 $ cd ..
20 20
21 21 Missing manifest should not result in server lookup
22 22
23 23 $ hg --verbose clone -U http://localhost:$HGPORT no-manifest
24 24 requesting all changes
25 25 adding changesets
26 26 adding manifests
27 27 adding file changes
28 28 added 2 changesets with 2 changes to 2 files
29 29 new changesets 53245c60e682:aaff8d2ffbbf
30 30 (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob)
31 31
32 32 $ cat server/access.log
33 33 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
34 34 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
35 35 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=aaff8d2ffbbf07a46dd1f05d8ae7877e3f56e2a2&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
36 36
37 37 Empty manifest file results in retrieval
38 38 (the extension only checks if the manifest file exists)
39 39
40 40 $ touch server/.hg/clonebundles.manifest
41 41 $ hg --verbose clone -U http://localhost:$HGPORT empty-manifest
42 42 no clone bundles available on remote; falling back to regular clone
43 43 requesting all changes
44 44 adding changesets
45 45 adding manifests
46 46 adding file changes
47 47 added 2 changesets with 2 changes to 2 files
48 48 new changesets 53245c60e682:aaff8d2ffbbf
49 49 (sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)
50 50
51 51 Manifest file with invalid URL aborts
52 52
53 53 $ echo 'http://does.not.exist/bundle.hg' > server/.hg/clonebundles.manifest
54 54 $ hg clone http://localhost:$HGPORT 404-url
55 55 applying clone bundle from http://does.not.exist/bundle.hg
56 56 error fetching bundle: (.* not known|(\[Errno -?\d+] )?([Nn]o address associated with (host)?name|Temporary failure in name resolution|Name does not resolve)) (re) (no-windows !)
57 57 error fetching bundle: [Errno 1100*] getaddrinfo failed (glob) (windows !)
58 58 abort: error applying bundle
59 59 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
60 60 [255]
61 61
62 62 Server is not running aborts
63 63
64 64 $ echo "http://localhost:$HGPORT1/bundle.hg" > server/.hg/clonebundles.manifest
65 65 $ hg clone http://localhost:$HGPORT server-not-runner
66 66 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
67 67 error fetching bundle: (.* refused.*|Protocol not supported|(.* )?\$EADDRNOTAVAIL\$|.* No route to host) (re)
68 68 abort: error applying bundle
69 69 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
70 70 [255]
71 71
72 72 Server returns 404
73 73
74 74 $ "$PYTHON" $TESTDIR/dumbhttp.py -p $HGPORT1 --pid http.pid
75 75 $ cat http.pid >> $DAEMON_PIDS
76 76 $ hg clone http://localhost:$HGPORT running-404
77 77 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
78 78 HTTP error fetching bundle: HTTP Error 404: File not found
79 79 abort: error applying bundle
80 80 (if this error persists, consider contacting the server operator or disable clone bundles via "--config ui.clonebundles=false")
81 81 [255]
82 82
83 83 We can override failure to fall back to regular clone
84 84
85 85 $ hg --config ui.clonebundlefallback=true clone -U http://localhost:$HGPORT 404-fallback
86 86 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
87 87 HTTP error fetching bundle: HTTP Error 404: File not found
88 88 falling back to normal clone
89 89 requesting all changes
90 90 adding changesets
91 91 adding manifests
92 92 adding file changes
93 93 added 2 changesets with 2 changes to 2 files
94 94 new changesets 53245c60e682:aaff8d2ffbbf
95 95
96 96 Bundle with partial content works
97 97
98 98 $ hg -R server bundle --type gzip-v1 --base null -r 53245c60e682 partial.hg
99 99 1 changesets found
100 100
101 101 We verify exact bundle content as an extra check against accidental future
102 102 changes. If this output changes, we could break old clients.
103 103
104 104 $ f --size --hexdump partial.hg
105 105 partial.hg: size=207
106 106 0000: 48 47 31 30 47 5a 78 9c 63 60 60 98 17 ac 12 93 |HG10GZx.c``.....|
107 107 0010: f0 ac a9 23 45 70 cb bf 0d 5f 59 4e 4a 7f 79 21 |...#Ep..._YNJ.y!|
108 108 0020: 9b cc 40 24 20 a0 d7 ce 2c d1 38 25 cd 24 25 d5 |..@$ ...,.8%.$%.|
109 109 0030: d8 c2 22 cd 38 d9 24 cd 22 d5 c8 22 cd 24 cd 32 |..".8.$."..".$.2|
110 110 0040: d1 c2 d0 c4 c8 d2 32 d1 38 39 29 c9 34 cd d4 80 |......2.89).4...|
111 111 0050: ab 24 b5 b8 84 cb 40 c1 80 2b 2d 3f 9f 8b 2b 31 |.$....@..+-?..+1|
112 112 0060: 25 45 01 c8 80 9a d2 9b 65 fb e5 9e 45 bf 8d 7f |%E......e...E...|
113 113 0070: 9f c6 97 9f 2b 44 34 67 d9 ec 8e 0f a0 92 0b 75 |....+D4g.......u|
114 114 0080: 41 d6 24 59 18 a4 a4 9a a6 18 1a 5b 98 9b 5a 98 |A.$Y.......[..Z.|
115 115 0090: 9a 18 26 9b a6 19 98 1a 99 99 26 a6 18 9a 98 24 |..&.......&....$|
116 116 00a0: 26 59 a6 25 5a 98 a5 18 a6 24 71 41 35 b1 43 dc |&Y.%Z....$qA5.C.|
117 117 00b0: 16 b2 83 f7 e9 45 8b d2 56 c7 a3 1f 82 52 d7 8a |.....E..V....R..|
118 118 00c0: 78 ed fc d5 76 f1 36 35 dc 05 00 36 ed 5e c7 |x...v.65...6.^.|
119 119
120 120 $ echo "http://localhost:$HGPORT1/partial.hg" > server/.hg/clonebundles.manifest
121 121 $ hg clone -U http://localhost:$HGPORT partial-bundle
122 122 applying clone bundle from http://localhost:$HGPORT1/partial.hg
123 123 adding changesets
124 124 adding manifests
125 125 adding file changes
126 126 added 1 changesets with 1 changes to 1 files
127 127 finished applying clone bundle
128 128 searching for changes
129 129 adding changesets
130 130 adding manifests
131 131 adding file changes
132 132 added 1 changesets with 1 changes to 1 files
133 133 new changesets aaff8d2ffbbf
134 134 1 local changesets published
135 135
136 136 Incremental pull doesn't fetch bundle
137 137
138 138 $ hg clone -r 53245c60e682 -U http://localhost:$HGPORT partial-clone
139 139 adding changesets
140 140 adding manifests
141 141 adding file changes
142 142 added 1 changesets with 1 changes to 1 files
143 143 new changesets 53245c60e682
144 144
145 145 $ cd partial-clone
146 146 $ hg pull
147 147 pulling from http://localhost:$HGPORT/
148 148 searching for changes
149 149 adding changesets
150 150 adding manifests
151 151 adding file changes
152 152 added 1 changesets with 1 changes to 1 files
153 153 new changesets aaff8d2ffbbf
154 154 (run 'hg update' to get a working copy)
155 155 $ cd ..
156 156
157 157 Bundle with full content works
158 158
159 159 $ hg -R server bundle --type gzip-v2 --base null -r tip full.hg
160 160 2 changesets found
161 161
162 162 Again, we perform an extra check against bundle content changes. If this content
163 163 changes, clone bundles produced by new Mercurial versions may not be readable
164 164 by old clients.
165 165
166 166 $ f --size --hexdump full.hg
167 167 full.hg: size=442
168 168 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
169 169 0010: 69 6f 6e 3d 47 5a 78 9c 63 60 60 d0 e4 76 f6 70 |ion=GZx.c``..v.p|
170 170 0020: f4 73 77 75 0f f2 0f 0d 60 00 02 46 46 76 26 4e |.swu....`..FFv&N|
171 171 0030: c6 b2 d4 a2 e2 cc fc 3c 03 a3 bc a4 e4 8c c4 bc |.......<........|
172 172 0040: f4 d4 62 23 06 06 e6 19 40 f9 4d c1 2a 31 09 cf |..b#....@.M.*1..|
173 173 0050: 9a 3a 52 04 b7 fc db f0 95 e5 a4 f4 97 17 b2 c9 |.:R.............|
174 174 0060: 0c 14 00 02 e6 d9 99 25 1a a7 a4 99 a4 a4 1a 5b |.......%.......[|
175 175 0070: 58 a4 19 27 9b a4 59 a4 1a 59 a4 99 a4 59 26 5a |X..'..Y..Y...Y&Z|
176 176 0080: 18 9a 18 59 5a 26 1a 27 27 25 99 a6 99 1a 70 95 |...YZ&.''%....p.|
177 177 0090: a4 16 97 70 19 28 18 70 a5 e5 e7 73 71 25 a6 a4 |...p.(.p...sq%..|
178 178 00a0: 28 00 19 20 17 af fa df ab ff 7b 3f fb 92 dc 8b |(.. ......{?....|
179 179 00b0: 1f 62 bb 9e b7 d7 d9 87 3d 5a 44 89 2f b0 99 87 |.b......=ZD./...|
180 180 00c0: ec e2 54 63 43 e3 b4 64 43 73 23 33 43 53 0b 63 |..TcC..dCs#3CS.c|
181 181 00d0: d3 14 23 03 a0 fb 2c 2c 0c d3 80 1e 30 49 49 b1 |..#...,,....0II.|
182 182 00e0: 4c 4a 32 48 33 30 b0 34 42 b8 38 29 b1 08 e2 62 |LJ2H30.4B.8)...b|
183 183 00f0: 20 03 6a ca c2 2c db 2f f7 2c fa 6d fc fb 34 be | .j..,./.,.m..4.|
184 184 0100: fc 5c 21 a2 39 cb 66 77 7c 00 0d c3 59 17 14 58 |.\!.9.fw|...Y..X|
185 185 0110: 49 16 06 29 a9 a6 29 86 c6 16 e6 a6 16 a6 26 86 |I..)..).......&.|
186 186 0120: c9 a6 69 06 a6 46 66 a6 89 29 86 26 26 89 49 96 |..i..Ff..).&&.I.|
187 187 0130: 69 89 16 66 29 86 29 49 5c 20 07 3e 16 fe 23 ae |i..f).)I\ .>..#.|
188 188 0140: 26 da 1c ab 10 1f d1 f8 e3 b3 ef cd dd fc 0c 93 |&...............|
189 189 0150: 88 75 34 36 75 04 82 55 17 14 36 a4 38 10 04 d8 |.u46u..U..6.8...|
190 190 0160: 21 01 9a b1 83 f7 e9 45 8b d2 56 c7 a3 1f 82 52 |!......E..V....R|
191 191 0170: d7 8a 78 ed fc d5 76 f1 36 25 81 89 c7 ad ec 90 |..x...v.6%......|
192 192 0180: 54 47 75 2b 89 48 b1 b2 62 c9 89 c9 19 a9 56 45 |TGu+.H..b.....VE|
193 193 0190: a9 65 ba 49 45 89 79 c9 19 ba 60 01 a0 14 23 58 |.e.IE.y...`...#X|
194 194 01a0: 81 35 c8 7d 40 cc 04 e2 a4 a4 a6 25 96 e6 94 60 |.5.}@......%...`|
195 195 01b0: 33 17 5f 54 00 00 d3 1b 0d 4c |3._T.....L|
196 196
197 197 $ echo "http://localhost:$HGPORT1/full.hg" > server/.hg/clonebundles.manifest
198 198 $ hg clone -U http://localhost:$HGPORT full-bundle
199 199 applying clone bundle from http://localhost:$HGPORT1/full.hg
200 200 adding changesets
201 201 adding manifests
202 202 adding file changes
203 203 added 2 changesets with 2 changes to 2 files
204 204 finished applying clone bundle
205 205 searching for changes
206 206 no changes found
207 207 2 local changesets published
208 208
209 209 Feature works over SSH
210 210
211 211 $ hg clone -U -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/server ssh-full-clone
212 212 applying clone bundle from http://localhost:$HGPORT1/full.hg
213 213 adding changesets
214 214 adding manifests
215 215 adding file changes
216 216 added 2 changesets with 2 changes to 2 files
217 217 finished applying clone bundle
218 218 searching for changes
219 219 no changes found
220 220 2 local changesets published
221 221
222 222 Entry with unknown BUNDLESPEC is filtered and not used
223 223
224 224 $ cat > server/.hg/clonebundles.manifest << EOF
225 225 > http://bad.entry1 BUNDLESPEC=UNKNOWN
226 226 > http://bad.entry2 BUNDLESPEC=xz-v1
227 227 > http://bad.entry3 BUNDLESPEC=none-v100
228 228 > http://localhost:$HGPORT1/full.hg BUNDLESPEC=gzip-v2
229 229 > EOF
230 230
231 231 $ hg clone -U http://localhost:$HGPORT filter-unknown-type
232 232 applying clone bundle from http://localhost:$HGPORT1/full.hg
233 233 adding changesets
234 234 adding manifests
235 235 adding file changes
236 236 added 2 changesets with 2 changes to 2 files
237 237 finished applying clone bundle
238 238 searching for changes
239 239 no changes found
240 240 2 local changesets published
241 241
242 242 Automatic fallback when all entries are filtered
243 243
244 244 $ cat > server/.hg/clonebundles.manifest << EOF
245 245 > http://bad.entry BUNDLESPEC=UNKNOWN
246 246 > EOF
247 247
248 248 $ hg clone -U http://localhost:$HGPORT filter-all
249 249 no compatible clone bundles available on server; falling back to regular clone
250 250 (you may want to report this to the server operator)
251 251 requesting all changes
252 252 adding changesets
253 253 adding manifests
254 254 adding file changes
255 255 added 2 changesets with 2 changes to 2 files
256 256 new changesets 53245c60e682:aaff8d2ffbbf
257 257
258 258 We require a Python version that supports SNI. Therefore, URLs requiring SNI
259 259 are not filtered.
260 260
261 261 $ cp full.hg sni.hg
262 262 $ cat > server/.hg/clonebundles.manifest << EOF
263 263 > http://localhost:$HGPORT1/sni.hg REQUIRESNI=true
264 264 > http://localhost:$HGPORT1/full.hg
265 265 > EOF
266 266
267 267 $ hg clone -U http://localhost:$HGPORT sni-supported
268 268 applying clone bundle from http://localhost:$HGPORT1/sni.hg
269 269 adding changesets
270 270 adding manifests
271 271 adding file changes
272 272 added 2 changesets with 2 changes to 2 files
273 273 finished applying clone bundle
274 274 searching for changes
275 275 no changes found
276 276 2 local changesets published
277 277
278 278 Stream clone bundles are supported
279 279
280 280 $ hg -R server debugcreatestreamclonebundle packed.hg
281 281 writing 613 bytes for 4 files
282 282 bundle requirements: generaldelta, revlogv1, sparserevlog
283 283
284 284 No bundle spec should work
285 285
286 286 $ cat > server/.hg/clonebundles.manifest << EOF
287 287 > http://localhost:$HGPORT1/packed.hg
288 288 > EOF
289 289
290 290 $ hg clone -U http://localhost:$HGPORT stream-clone-no-spec
291 291 applying clone bundle from http://localhost:$HGPORT1/packed.hg
292 292 4 files to transfer, 613 bytes of data
293 293 transferred 613 bytes in *.* seconds (*) (glob)
294 294 finished applying clone bundle
295 295 searching for changes
296 296 no changes found
297 297
298 298 Bundle spec without parameters should work
299 299
300 300 $ cat > server/.hg/clonebundles.manifest << EOF
301 301 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1
302 302 > EOF
303 303
304 304 $ hg clone -U http://localhost:$HGPORT stream-clone-vanilla-spec
305 305 applying clone bundle from http://localhost:$HGPORT1/packed.hg
306 306 4 files to transfer, 613 bytes of data
307 307 transferred 613 bytes in *.* seconds (*) (glob)
308 308 finished applying clone bundle
309 309 searching for changes
310 310 no changes found
311 311
312 312 Bundle spec with format requirements should work
313 313
314 314 $ cat > server/.hg/clonebundles.manifest << EOF
315 315 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv1
316 316 > EOF
317 317
318 318 $ hg clone -U http://localhost:$HGPORT stream-clone-supported-requirements
319 319 applying clone bundle from http://localhost:$HGPORT1/packed.hg
320 320 4 files to transfer, 613 bytes of data
321 321 transferred 613 bytes in *.* seconds (*) (glob)
322 322 finished applying clone bundle
323 323 searching for changes
324 324 no changes found
325 325
326 326 Stream bundle spec with unknown requirements should be filtered out
327 327
328 328 $ cat > server/.hg/clonebundles.manifest << EOF
329 329 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv42
330 330 > EOF
331 331
332 332 $ hg clone -U http://localhost:$HGPORT stream-clone-unsupported-requirements
333 333 no compatible clone bundles available on server; falling back to regular clone
334 334 (you may want to report this to the server operator)
335 335 requesting all changes
336 336 adding changesets
337 337 adding manifests
338 338 adding file changes
339 339 added 2 changesets with 2 changes to 2 files
340 340 new changesets 53245c60e682:aaff8d2ffbbf
341 341
342 342 Set up manifest for testing preferences
343 343 (Remember, the TYPE does not have to match reality - the URL is
344 344 important)
345 345
346 346 $ cp full.hg gz-a.hg
347 347 $ cp full.hg gz-b.hg
348 348 $ cp full.hg bz2-a.hg
349 349 $ cp full.hg bz2-b.hg
350 350 $ cat > server/.hg/clonebundles.manifest << EOF
351 351 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2 extra=a
352 352 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2 extra=a
353 353 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
354 354 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
355 355 > EOF
356 356
357 357 Preferring an undefined attribute will take first entry
358 358
359 359 $ hg --config ui.clonebundleprefers=foo=bar clone -U http://localhost:$HGPORT prefer-foo
360 360 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
361 361 adding changesets
362 362 adding manifests
363 363 adding file changes
364 364 added 2 changesets with 2 changes to 2 files
365 365 finished applying clone bundle
366 366 searching for changes
367 367 no changes found
368 368 2 local changesets published
369 369
370 370 Preferring bz2 type will download first entry of that type
371 371
372 372 $ hg --config ui.clonebundleprefers=COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-bz
373 373 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
374 374 adding changesets
375 375 adding manifests
376 376 adding file changes
377 377 added 2 changesets with 2 changes to 2 files
378 378 finished applying clone bundle
379 379 searching for changes
380 380 no changes found
381 381 2 local changesets published
382 382
383 383 Preferring multiple values of an option works
384 384
385 385 $ hg --config ui.clonebundleprefers=COMPRESSION=unknown,COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-multiple-bz
386 386 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
387 387 adding changesets
388 388 adding manifests
389 389 adding file changes
390 390 added 2 changesets with 2 changes to 2 files
391 391 finished applying clone bundle
392 392 searching for changes
393 393 no changes found
394 394 2 local changesets published
395 395
396 396 Sorting multiple values should get us back to original first entry
397 397
398 398 $ hg --config ui.clonebundleprefers=BUNDLESPEC=unknown,BUNDLESPEC=gzip-v2,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-multiple-gz
399 399 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
400 400 adding changesets
401 401 adding manifests
402 402 adding file changes
403 403 added 2 changesets with 2 changes to 2 files
404 404 finished applying clone bundle
405 405 searching for changes
406 406 no changes found
407 407 2 local changesets published
408 408
409 409 Preferring multiple attributes has correct order
410 410
411 411 $ hg --config ui.clonebundleprefers=extra=b,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-separate-attributes
412 412 applying clone bundle from http://localhost:$HGPORT1/bz2-b.hg
413 413 adding changesets
414 414 adding manifests
415 415 adding file changes
416 416 added 2 changesets with 2 changes to 2 files
417 417 finished applying clone bundle
418 418 searching for changes
419 419 no changes found
420 420 2 local changesets published
421 421
422 422 Test where attribute is missing from some entries
423 423
424 424 $ cat > server/.hg/clonebundles.manifest << EOF
425 425 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
426 426 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2
427 427 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
428 428 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
429 429 > EOF
430 430
431 431 $ hg --config ui.clonebundleprefers=extra=b clone -U http://localhost:$HGPORT prefer-partially-defined-attribute
432 432 applying clone bundle from http://localhost:$HGPORT1/gz-b.hg
433 433 adding changesets
434 434 adding manifests
435 435 adding file changes
436 436 added 2 changesets with 2 changes to 2 files
437 437 finished applying clone bundle
438 438 searching for changes
439 439 no changes found
440 440 2 local changesets published
441 441
442 442 Test a bad attribute list
443 443
444 444 $ hg --config ui.clonebundleprefers=bad clone -U http://localhost:$HGPORT bad-input
445 445 abort: invalid ui.clonebundleprefers item: bad
446 446 (each comma separated item should be key=value pairs)
447 447 [255]
448 448 $ hg --config ui.clonebundleprefers=key=val,bad,key2=val2 clone \
449 449 > -U http://localhost:$HGPORT bad-input
450 450 abort: invalid ui.clonebundleprefers item: bad
451 451 (each comma separated item should be key=value pairs)
452 452 [255]
453 453
454 454
455 455 Test interaction between clone bundles and --stream
456 456
457 457 A manifest with just a gzip bundle
458 458
459 459 $ cat > server/.hg/clonebundles.manifest << EOF
460 460 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
461 461 > EOF
462 462
463 463 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip
464 464 no compatible clone bundles available on server; falling back to regular clone
465 465 (you may want to report this to the server operator)
466 466 streaming all changes
467 467 9 files to transfer, 816 bytes of data
468 468 transferred 816 bytes in * seconds (*) (glob)
469 469
470 470 A manifest with a stream clone but no BUNDLESPEC
471 471
472 472 $ cat > server/.hg/clonebundles.manifest << EOF
473 473 > http://localhost:$HGPORT1/packed.hg
474 474 > EOF
475 475
476 476 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-no-bundlespec
477 477 no compatible clone bundles available on server; falling back to regular clone
478 478 (you may want to report this to the server operator)
479 479 streaming all changes
480 480 9 files to transfer, 816 bytes of data
481 481 transferred 816 bytes in * seconds (*) (glob)
482 482
483 483 A manifest with a gzip bundle and a stream clone
484 484
485 485 $ cat > server/.hg/clonebundles.manifest << EOF
486 486 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
487 487 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1
488 488 > EOF
489 489
490 490 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip-packed
491 491 applying clone bundle from http://localhost:$HGPORT1/packed.hg
492 492 4 files to transfer, 613 bytes of data
493 493 transferred 613 bytes in * seconds (*) (glob)
494 494 finished applying clone bundle
495 495 searching for changes
496 496 no changes found
497 497
498 498 A manifest with a gzip bundle and stream clone with supported requirements
499 499
500 500 $ cat > server/.hg/clonebundles.manifest << EOF
501 501 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
502 502 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv1
503 503 > EOF
504 504
505 505 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip-packed-requirements
506 506 applying clone bundle from http://localhost:$HGPORT1/packed.hg
507 507 4 files to transfer, 613 bytes of data
508 508 transferred 613 bytes in * seconds (*) (glob)
509 509 finished applying clone bundle
510 510 searching for changes
511 511 no changes found
512 512
513 513 A manifest with a gzip bundle and a stream clone with unsupported requirements
514 514
515 515 $ cat > server/.hg/clonebundles.manifest << EOF
516 516 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
517 517 > http://localhost:$HGPORT1/packed.hg BUNDLESPEC=none-packed1;requirements%3Drevlogv42
518 518 > EOF
519 519
520 520 $ hg clone -U --stream http://localhost:$HGPORT uncompressed-gzip-packed-unsupported-requirements
521 521 no compatible clone bundles available on server; falling back to regular clone
522 522 (you may want to report this to the server operator)
523 523 streaming all changes
524 524 9 files to transfer, 816 bytes of data
525 525 transferred 816 bytes in * seconds (*) (glob)
526 526
527 527 Test clone bundle retrieved through bundle2
528 528
529 529 $ cat << EOF >> $HGRCPATH
530 530 > [extensions]
531 531 > largefiles=
532 532 > EOF
533 533 $ killdaemons.py
534 534 $ hg -R server serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
535 535 $ cat hg.pid >> $DAEMON_PIDS
536 536
537 537 $ hg -R server debuglfput gz-a.hg
538 538 1f74b3d08286b9b3a16fb3fa185dd29219cbc6ae
539 539
540 540 $ cat > server/.hg/clonebundles.manifest << EOF
541 541 > largefile://1f74b3d08286b9b3a16fb3fa185dd29219cbc6ae BUNDLESPEC=gzip-v2
542 542 > EOF
543 543
544 544 $ hg clone -U http://localhost:$HGPORT largefile-provided --traceback
545 545 applying clone bundle from largefile://1f74b3d08286b9b3a16fb3fa185dd29219cbc6ae
546 546 adding changesets
547 547 adding manifests
548 548 adding file changes
549 549 added 2 changesets with 2 changes to 2 files
550 550 finished applying clone bundle
551 551 searching for changes
552 552 no changes found
553 553 2 local changesets published
554 554 $ killdaemons.py
555 555
556 556 A manifest with a gzip bundle requiring too much memory for a 16MB system and working
557 557 on a 32MB system.
558 558
559 559 $ "$PYTHON" $TESTDIR/dumbhttp.py -p $HGPORT1 --pid http.pid
560 560 $ cat http.pid >> $DAEMON_PIDS
561 561 $ hg -R server serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
562 562 $ cat hg.pid >> $DAEMON_PIDS
563 563
564 564 $ cat > server/.hg/clonebundles.manifest << EOF
565 565 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2 REQUIREDRAM=12MB
566 566 > EOF
567 567
568 568 $ hg clone -U --debug --config ui.available-memory=16MB http://localhost:$HGPORT gzip-too-large
569 569 using http://localhost:$HGPORT/
570 570 sending capabilities command
571 571 sending clonebundles command
572 572 filtering http://localhost:$HGPORT1/gz-a.hg as it needs more than 2/3 of system memory
573 573 no compatible clone bundles available on server; falling back to regular clone
574 574 (you may want to report this to the server operator)
575 575 query 1; heads
576 576 sending batch command
577 577 requesting all changes
578 578 sending getbundle command
579 579 bundle2-input-bundle: with-transaction
580 580 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
581 581 adding changesets
582 582 add changeset 53245c60e682
583 583 add changeset aaff8d2ffbbf
584 584 adding manifests
585 585 adding file changes
586 586 adding bar revisions
587 587 adding foo revisions
588 588 bundle2-input-part: total payload size 920
589 589 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
590 590 bundle2-input-part: "phase-heads" supported
591 591 bundle2-input-part: total payload size 24
592 bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
593 bundle2-input-part: total payload size 59
594 bundle2-input-bundle: 4 parts total
592 bundle2-input-bundle: 3 parts total
595 593 checking for updated bookmarks
596 594 updating the branch cache
597 595 added 2 changesets with 2 changes to 2 files
598 596 new changesets 53245c60e682:aaff8d2ffbbf
599 597 calling hook changegroup.lfiles: hgext.largefiles.reposetup.checkrequireslfiles
600 598 updating the branch cache
601 599 (sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)
602 600
603 601 $ hg clone -U --debug --config ui.available-memory=32MB http://localhost:$HGPORT gzip-too-large2
604 602 using http://localhost:$HGPORT/
605 603 sending capabilities command
606 604 sending clonebundles command
607 605 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
608 606 bundle2-input-bundle: 1 params with-transaction
609 607 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
610 608 adding changesets
611 609 add changeset 53245c60e682
612 610 add changeset aaff8d2ffbbf
613 611 adding manifests
614 612 adding file changes
615 613 adding bar revisions
616 614 adding foo revisions
617 615 bundle2-input-part: total payload size 920
618 616 bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
619 617 bundle2-input-part: total payload size 59
620 618 bundle2-input-bundle: 2 parts total
621 619 updating the branch cache
622 620 added 2 changesets with 2 changes to 2 files
623 621 finished applying clone bundle
624 622 query 1; heads
625 623 sending batch command
626 624 searching for changes
627 625 all remote heads known locally
628 626 no changes found
629 627 sending getbundle command
630 628 bundle2-input-bundle: with-transaction
631 629 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
632 630 bundle2-input-part: "phase-heads" supported
633 631 bundle2-input-part: total payload size 24
634 632 bundle2-input-bundle: 2 parts total
635 633 checking for updated bookmarks
636 634 2 local changesets published
637 635 calling hook changegroup.lfiles: hgext.largefiles.reposetup.checkrequireslfiles
638 636 updating the branch cache
639 637 (sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)
640 638 $ killdaemons.py
@@ -1,665 +1,664 b''
1 1 $ cat << EOF >> $HGRCPATH
2 2 > [ui]
3 3 > interactive=yes
4 4 > EOF
5 5
6 6 $ hg init debugrevlog
7 7 $ cd debugrevlog
8 8 $ echo a > a
9 9 $ hg ci -Am adda
10 10 adding a
11 11 $ hg rm .
12 12 removing a
13 13 $ hg ci -Am make-it-empty
14 14 $ hg revert --all -r 0
15 15 adding a
16 16 $ hg ci -Am make-it-full
17 17 #if reporevlogstore
18 18 $ hg debugrevlog -c
19 19 format : 1
20 20 flags : inline
21 21
22 22 revisions : 3
23 23 merges : 0 ( 0.00%)
24 24 normal : 3 (100.00%)
25 25 revisions : 3
26 26 empty : 0 ( 0.00%)
27 27 text : 0 (100.00%)
28 28 delta : 0 (100.00%)
29 29 snapshot : 3 (100.00%)
30 30 lvl-0 : 3 (100.00%)
31 31 deltas : 0 ( 0.00%)
32 32 revision size : 191
33 33 snapshot : 191 (100.00%)
34 34 lvl-0 : 191 (100.00%)
35 35 deltas : 0 ( 0.00%)
36 36
37 37 chunks : 3
38 38 0x75 (u) : 3 (100.00%)
39 39 chunks size : 191
40 40 0x75 (u) : 191 (100.00%)
41 41
42 42 avg chain length : 0
43 43 max chain length : 0
44 44 max chain reach : 67
45 45 compression ratio : 0
46 46
47 47 uncompressed data size (min/max/avg) : 57 / 66 / 62
48 48 full revision size (min/max/avg) : 58 / 67 / 63
49 49 inter-snapshot size (min/max/avg) : 0 / 0 / 0
50 50 delta size (min/max/avg) : 0 / 0 / 0
51 51 $ hg debugrevlog -m
52 52 format : 1
53 53 flags : inline, generaldelta
54 54
55 55 revisions : 3
56 56 merges : 0 ( 0.00%)
57 57 normal : 3 (100.00%)
58 58 revisions : 3
59 59 empty : 1 (33.33%)
60 60 text : 1 (100.00%)
61 61 delta : 0 ( 0.00%)
62 62 snapshot : 2 (66.67%)
63 63 lvl-0 : 2 (66.67%)
64 64 deltas : 0 ( 0.00%)
65 65 revision size : 88
66 66 snapshot : 88 (100.00%)
67 67 lvl-0 : 88 (100.00%)
68 68 deltas : 0 ( 0.00%)
69 69
70 70 chunks : 3
71 71 empty : 1 (33.33%)
72 72 0x75 (u) : 2 (66.67%)
73 73 chunks size : 88
74 74 empty : 0 ( 0.00%)
75 75 0x75 (u) : 88 (100.00%)
76 76
77 77 avg chain length : 0
78 78 max chain length : 0
79 79 max chain reach : 44
80 80 compression ratio : 0
81 81
82 82 uncompressed data size (min/max/avg) : 0 / 43 / 28
83 83 full revision size (min/max/avg) : 44 / 44 / 44
84 84 inter-snapshot size (min/max/avg) : 0 / 0 / 0
85 85 delta size (min/max/avg) : 0 / 0 / 0
86 86 $ hg debugrevlog a
87 87 format : 1
88 88 flags : inline, generaldelta
89 89
90 90 revisions : 1
91 91 merges : 0 ( 0.00%)
92 92 normal : 1 (100.00%)
93 93 revisions : 1
94 94 empty : 0 ( 0.00%)
95 95 text : 0 (100.00%)
96 96 delta : 0 (100.00%)
97 97 snapshot : 1 (100.00%)
98 98 lvl-0 : 1 (100.00%)
99 99 deltas : 0 ( 0.00%)
100 100 revision size : 3
101 101 snapshot : 3 (100.00%)
102 102 lvl-0 : 3 (100.00%)
103 103 deltas : 0 ( 0.00%)
104 104
105 105 chunks : 1
106 106 0x75 (u) : 1 (100.00%)
107 107 chunks size : 3
108 108 0x75 (u) : 3 (100.00%)
109 109
110 110 avg chain length : 0
111 111 max chain length : 0
112 112 max chain reach : 3
113 113 compression ratio : 0
114 114
115 115 uncompressed data size (min/max/avg) : 2 / 2 / 2
116 116 full revision size (min/max/avg) : 3 / 3 / 3
117 117 inter-snapshot size (min/max/avg) : 0 / 0 / 0
118 118 delta size (min/max/avg) : 0 / 0 / 0
119 119 #endif
120 120
121 121 Test debugindex, with and without the --verbose/--debug flag
122 122 $ hg debugrevlogindex a
123 123 rev linkrev nodeid p1 p2
124 124 0 0 b789fdd96dc2 000000000000 000000000000
125 125
126 126 #if no-reposimplestore
127 127 $ hg --verbose debugrevlogindex a
128 128 rev offset length linkrev nodeid p1 p2
129 129 0 0 3 0 b789fdd96dc2 000000000000 000000000000
130 130
131 131 $ hg --debug debugrevlogindex a
132 132 rev offset length linkrev nodeid p1 p2
133 133 0 0 3 0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
134 134 #endif
135 135
136 136 $ hg debugrevlogindex -f 1 a
137 137 rev flag size link p1 p2 nodeid
138 138 0 0000 2 0 -1 -1 b789fdd96dc2
139 139
140 140 #if no-reposimplestore
141 141 $ hg --verbose debugrevlogindex -f 1 a
142 142 rev flag offset length size link p1 p2 nodeid
143 143 0 0000 0 3 2 0 -1 -1 b789fdd96dc2
144 144
145 145 $ hg --debug debugrevlogindex -f 1 a
146 146 rev flag offset length size link p1 p2 nodeid
147 147 0 0000 0 3 2 0 -1 -1 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
148 148 #endif
149 149
150 150 $ hg debugindex -c
151 151 rev linkrev nodeid p1 p2
152 152 0 0 07f494440405 000000000000 000000000000
153 153 1 1 8cccb4b5fec2 07f494440405 000000000000
154 154 2 2 b1e228c512c5 8cccb4b5fec2 000000000000
155 155 $ hg debugindex -c --debug
156 156 rev linkrev nodeid p1 p2
157 157 0 0 07f4944404050f47db2e5c5071e0e84e7a27bba9 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
158 158 1 1 8cccb4b5fec20cafeb99dd01c26d4dee8ea4388a 07f4944404050f47db2e5c5071e0e84e7a27bba9 0000000000000000000000000000000000000000
159 159 2 2 b1e228c512c5d7066d70562ed839c3323a62d6d2 8cccb4b5fec20cafeb99dd01c26d4dee8ea4388a 0000000000000000000000000000000000000000
160 160 $ hg debugindex -m
161 161 rev linkrev nodeid p1 p2
162 162 0 0 a0c8bcbbb45c 000000000000 000000000000
163 163 1 1 57faf8a737ae a0c8bcbbb45c 000000000000
164 164 2 2 a35b10320954 57faf8a737ae 000000000000
165 165 $ hg debugindex -m --debug
166 166 rev linkrev nodeid p1 p2
167 167 0 0 a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
168 168 1 1 57faf8a737ae7faf490582941a82319ba6529dca a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 0000000000000000000000000000000000000000
169 169 2 2 a35b103209548032201c16c7688cb2657f037a38 57faf8a737ae7faf490582941a82319ba6529dca 0000000000000000000000000000000000000000
170 170 $ hg debugindex a
171 171 rev linkrev nodeid p1 p2
172 172 0 0 b789fdd96dc2 000000000000 000000000000
173 173 $ hg debugindex --debug a
174 174 rev linkrev nodeid p1 p2
175 175 0 0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
176 176
177 177 debugdelta chain basic output
178 178
179 179 #if reporevlogstore pure
180 180 $ hg debugindexstats
181 181 abort: debugindexstats only works with native code
182 182 [255]
183 183 #endif
184 184 #if reporevlogstore no-pure
185 185 $ hg debugindexstats
186 186 node trie capacity: 4
187 187 node trie count: 2
188 188 node trie depth: 1
189 189 node trie last rev scanned: -1
190 190 node trie lookups: 4
191 191 node trie misses: 1
192 192 node trie splits: 1
193 193 revs in memory: 3
194 194 #endif
195 195
196 196 #if reporevlogstore no-pure
197 197 $ hg debugdeltachain -m
198 198 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
199 199 0 1 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
200 200 1 2 1 -1 base 0 0 0 0.00000 0 0 0.00000 0 0 1.00000 1
201 201 2 3 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
202 202
203 203 $ hg debugdeltachain -m -T '{rev} {chainid} {chainlen}\n'
204 204 0 1 1
205 205 1 2 1
206 206 2 3 1
207 207
208 208 $ hg debugdeltachain -m -Tjson
209 209 [
210 210 {
211 211 "chainid": 1,
212 212 "chainlen": 1,
213 213 "chainratio": 1.02325581395, (no-py3 !)
214 214 "chainratio": 1.0232558139534884, (py3 !)
215 215 "chainsize": 44,
216 216 "compsize": 44,
217 217 "deltatype": "base",
218 218 "extradist": 0,
219 219 "extraratio": 0.0,
220 220 "largestblock": 44,
221 221 "lindist": 44,
222 222 "prevrev": -1,
223 223 "readdensity": 1.0,
224 224 "readsize": 44,
225 225 "rev": 0,
226 226 "srchunks": 1,
227 227 "uncompsize": 43
228 228 },
229 229 {
230 230 "chainid": 2,
231 231 "chainlen": 1,
232 232 "chainratio": 0,
233 233 "chainsize": 0,
234 234 "compsize": 0,
235 235 "deltatype": "base",
236 236 "extradist": 0,
237 237 "extraratio": 0,
238 238 "largestblock": 0,
239 239 "lindist": 0,
240 240 "prevrev": -1,
241 241 "readdensity": 1,
242 242 "readsize": 0,
243 243 "rev": 1,
244 244 "srchunks": 1,
245 245 "uncompsize": 0
246 246 },
247 247 {
248 248 "chainid": 3,
249 249 "chainlen": 1,
250 250 "chainratio": 1.02325581395, (no-py3 !)
251 251 "chainratio": 1.0232558139534884, (py3 !)
252 252 "chainsize": 44,
253 253 "compsize": 44,
254 254 "deltatype": "base",
255 255 "extradist": 0,
256 256 "extraratio": 0.0,
257 257 "largestblock": 44,
258 258 "lindist": 44,
259 259 "prevrev": -1,
260 260 "readdensity": 1.0,
261 261 "readsize": 44,
262 262 "rev": 2,
263 263 "srchunks": 1,
264 264 "uncompsize": 43
265 265 }
266 266 ]
267 267
268 268 debugdelta chain with sparse read enabled
269 269
270 270 $ cat >> $HGRCPATH <<EOF
271 271 > [experimental]
272 272 > sparse-read = True
273 273 > EOF
274 274 $ hg debugdeltachain -m
275 275 rev chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
276 276 0 1 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
277 277 1 2 1 -1 base 0 0 0 0.00000 0 0 0.00000 0 0 1.00000 1
278 278 2 3 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
279 279
280 280 $ hg debugdeltachain -m -T '{rev} {chainid} {chainlen} {readsize} {largestblock} {readdensity}\n'
281 281 0 1 1 44 44 1.0
282 282 1 2 1 0 0 1
283 283 2 3 1 44 44 1.0
284 284
285 285 $ hg debugdeltachain -m -Tjson
286 286 [
287 287 {
288 288 "chainid": 1,
289 289 "chainlen": 1,
290 290 "chainratio": 1.02325581395, (no-py3 !)
291 291 "chainratio": 1.0232558139534884, (py3 !)
292 292 "chainsize": 44,
293 293 "compsize": 44,
294 294 "deltatype": "base",
295 295 "extradist": 0,
296 296 "extraratio": 0.0,
297 297 "largestblock": 44,
298 298 "lindist": 44,
299 299 "prevrev": -1,
300 300 "readdensity": 1.0,
301 301 "readsize": 44,
302 302 "rev": 0,
303 303 "srchunks": 1,
304 304 "uncompsize": 43
305 305 },
306 306 {
307 307 "chainid": 2,
308 308 "chainlen": 1,
309 309 "chainratio": 0,
310 310 "chainsize": 0,
311 311 "compsize": 0,
312 312 "deltatype": "base",
313 313 "extradist": 0,
314 314 "extraratio": 0,
315 315 "largestblock": 0,
316 316 "lindist": 0,
317 317 "prevrev": -1,
318 318 "readdensity": 1,
319 319 "readsize": 0,
320 320 "rev": 1,
321 321 "srchunks": 1,
322 322 "uncompsize": 0
323 323 },
324 324 {
325 325 "chainid": 3,
326 326 "chainlen": 1,
327 327 "chainratio": 1.02325581395, (no-py3 !)
328 328 "chainratio": 1.0232558139534884, (py3 !)
329 329 "chainsize": 44,
330 330 "compsize": 44,
331 331 "deltatype": "base",
332 332 "extradist": 0,
333 333 "extraratio": 0.0,
334 334 "largestblock": 44,
335 335 "lindist": 44,
336 336 "prevrev": -1,
337 337 "readdensity": 1.0,
338 338 "readsize": 44,
339 339 "rev": 2,
340 340 "srchunks": 1,
341 341 "uncompsize": 43
342 342 }
343 343 ]
344 344
345 345 $ printf "This test checks things.\n" >> a
346 346 $ hg ci -m a
347 347 $ hg branch other
348 348 marked working directory as branch other
349 349 (branches are permanent and global, did you want a bookmark?)
350 350 $ for i in `$TESTDIR/seq.py 5`; do
351 351 > printf "shorter ${i}" >> a
352 352 > hg ci -m "a other:$i"
353 353 > hg up -q default
354 354 > printf "for the branch default we want longer chains: ${i}" >> a
355 355 > hg ci -m "a default:$i"
356 356 > hg up -q other
357 357 > done
358 358 $ hg debugdeltachain a -T '{rev} {srchunks}\n' \
359 359 > --config experimental.sparse-read.density-threshold=0.50 \
360 360 > --config experimental.sparse-read.min-gap-size=0
361 361 0 1
362 362 1 1
363 363 2 1
364 364 3 1
365 365 4 1
366 366 5 1
367 367 6 1
368 368 7 1
369 369 8 1
370 370 9 1
371 371 10 2
372 372 11 1
373 373 $ hg --config extensions.strip= strip --no-backup -r 1
374 374 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 375
376 376 Test max chain len
377 377 $ cat >> $HGRCPATH << EOF
378 378 > [format]
379 379 > maxchainlen=4
380 380 > EOF
381 381
382 382 $ printf "This test checks if maxchainlen config value is respected also it can serve as basic test for debugrevlog -d <file>.\n" >> a
383 383 $ hg ci -m a
384 384 $ printf "b\n" >> a
385 385 $ hg ci -m a
386 386 $ printf "c\n" >> a
387 387 $ hg ci -m a
388 388 $ printf "d\n" >> a
389 389 $ hg ci -m a
390 390 $ printf "e\n" >> a
391 391 $ hg ci -m a
392 392 $ printf "f\n" >> a
393 393 $ hg ci -m a
394 394 $ printf 'g\n' >> a
395 395 $ hg ci -m a
396 396 $ printf 'h\n' >> a
397 397 $ hg ci -m a
398 398
399 399 $ hg debugrevlog -d a
400 400 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
401 401 0 -1 -1 0 ??? 0 0 0 0 ??? ???? ? 1 0 (glob)
402 402 1 0 -1 ??? ??? 0 0 0 0 ??? ???? ? 1 1 (glob)
403 403 2 1 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
404 404 3 2 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
405 405 4 3 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 4 (glob)
406 406 5 4 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 0 (glob)
407 407 6 5 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 1 (glob)
408 408 7 6 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
409 409 8 7 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
410 410 #endif
411 411
412 412 Test debuglocks command:
413 413
414 414 $ hg debuglocks
415 415 lock: free
416 416 wlock: free
417 417
418 418 * Test setting the lock
419 419
420 420 waitlock <file> will wait for file to be created. If it isn't in a reasonable
421 421 amount of time, displays error message and returns 1
422 422 $ waitlock() {
423 423 > start=`date +%s`
424 424 > timeout=5
425 425 > while [ \( ! -f $1 \) -a \( ! -L $1 \) ]; do
426 426 > now=`date +%s`
427 427 > if [ "`expr $now - $start`" -gt $timeout ]; then
428 428 > echo "timeout: $1 was not created in $timeout seconds"
429 429 > return 1
430 430 > fi
431 431 > sleep 0.1
432 432 > done
433 433 > }
434 434 $ dolock() {
435 435 > {
436 436 > waitlock .hg/unlock
437 437 > rm -f .hg/unlock
438 438 > echo y
439 439 > } | hg debuglocks "$@" > /dev/null
440 440 > }
441 441 $ dolock -s &
442 442 $ waitlock .hg/store/lock
443 443
444 444 $ hg debuglocks
445 445 lock: user *, process * (*s) (glob)
446 446 wlock: free
447 447 [1]
448 448 $ touch .hg/unlock
449 449 $ wait
450 450 $ [ -f .hg/store/lock ] || echo "There is no lock"
451 451 There is no lock
452 452
453 453 * Test setting the wlock
454 454
455 455 $ dolock -S &
456 456 $ waitlock .hg/wlock
457 457
458 458 $ hg debuglocks
459 459 lock: free
460 460 wlock: user *, process * (*s) (glob)
461 461 [1]
462 462 $ touch .hg/unlock
463 463 $ wait
464 464 $ [ -f .hg/wlock ] || echo "There is no wlock"
465 465 There is no wlock
466 466
467 467 * Test setting both locks
468 468
469 469 $ dolock -Ss &
470 470 $ waitlock .hg/wlock && waitlock .hg/store/lock
471 471
472 472 $ hg debuglocks
473 473 lock: user *, process * (*s) (glob)
474 474 wlock: user *, process * (*s) (glob)
475 475 [2]
476 476
477 477 * Test failing to set a lock
478 478
479 479 $ hg debuglocks -s
480 480 abort: lock is already held
481 481 [255]
482 482
483 483 $ hg debuglocks -S
484 484 abort: wlock is already held
485 485 [255]
486 486
487 487 $ touch .hg/unlock
488 488 $ wait
489 489
490 490 $ hg debuglocks
491 491 lock: free
492 492 wlock: free
493 493
494 494 * Test forcing the lock
495 495
496 496 $ dolock -s &
497 497 $ waitlock .hg/store/lock
498 498
499 499 $ hg debuglocks
500 500 lock: user *, process * (*s) (glob)
501 501 wlock: free
502 502 [1]
503 503
504 504 $ hg debuglocks -L
505 505
506 506 $ hg debuglocks
507 507 lock: free
508 508 wlock: free
509 509
510 510 $ touch .hg/unlock
511 511 $ wait
512 512
513 513 * Test forcing the wlock
514 514
515 515 $ dolock -S &
516 516 $ waitlock .hg/wlock
517 517
518 518 $ hg debuglocks
519 519 lock: free
520 520 wlock: user *, process * (*s) (glob)
521 521 [1]
522 522
523 523 $ hg debuglocks -W
524 524
525 525 $ hg debuglocks
526 526 lock: free
527 527 wlock: free
528 528
529 529 $ touch .hg/unlock
530 530 $ wait
531 531
532 532 Test WdirUnsupported exception
533 533
534 534 $ hg debugdata -c ffffffffffffffffffffffffffffffffffffffff
535 535 abort: working directory revision cannot be specified
536 536 [255]
537 537
538 538 Test cache warming command
539 539
540 540 $ rm -rf .hg/cache/
541 541 $ hg debugupdatecaches --debug
542 542 updating the branch cache
543 543 $ ls -r .hg/cache/*
544 544 .hg/cache/tags2-served
545 545 .hg/cache/tags2
546 546 .hg/cache/rbc-revs-v1
547 547 .hg/cache/rbc-names-v1
548 548 .hg/cache/hgtagsfnodes1
549 549 .hg/cache/branch2-visible-hidden
550 550 .hg/cache/branch2-visible
551 551 .hg/cache/branch2-served.hidden
552 552 .hg/cache/branch2-served
553 553 .hg/cache/branch2-immutable
554 554 .hg/cache/branch2-base
555 555
556 556 Test debugcolor
557 557
558 558 #if no-windows
559 559 $ hg debugcolor --style --color always | egrep 'mode|style|log\.'
560 560 color mode: 'ansi'
561 561 available style:
562 562 \x1b[0;33mlog.changeset\x1b[0m: \x1b[0;33myellow\x1b[0m (esc)
563 563 #endif
564 564
565 565 $ hg debugcolor --style --color never
566 566 color mode: None
567 567 available style:
568 568
569 569 $ cd ..
570 570
571 571 Test internal debugstacktrace command
572 572
573 573 $ cat > debugstacktrace.py << EOF
574 574 > from __future__ import absolute_import
575 575 > from mercurial import (
576 576 > util,
577 577 > )
578 578 > from mercurial.utils import (
579 579 > procutil,
580 580 > )
581 581 > def f():
582 582 > util.debugstacktrace(f=procutil.stdout)
583 583 > g()
584 584 > def g():
585 585 > util.dst(b'hello from g\\n', skip=1)
586 586 > h()
587 587 > def h():
588 588 > util.dst(b'hi ...\\nfrom h hidden in g', 1, depth=2)
589 589 > f()
590 590 > EOF
591 591 $ "$PYTHON" debugstacktrace.py
592 592 stacktrace at:
593 593 *debugstacktrace.py:16 in * (glob)
594 594 *debugstacktrace.py:9 in f (glob)
595 595 hello from g at:
596 596 *debugstacktrace.py:16 in * (glob)
597 597 *debugstacktrace.py:10 in f (glob)
598 598 hi ...
599 599 from h hidden in g at:
600 600 *debugstacktrace.py:10 in f (glob)
601 601 *debugstacktrace.py:13 in g (glob)
602 602
603 603 Test debugcapabilities command:
604 604
605 605 $ hg debugcapabilities ./debugrevlog/
606 606 Main capabilities:
607 607 branchmap
608 608 $USUAL_BUNDLE2_CAPS$
609 609 getbundle
610 610 known
611 611 lookup
612 612 pushkey
613 613 unbundle
614 614 Bundle2 capabilities:
615 615 HG20
616 616 bookmarks
617 617 changegroup
618 618 01
619 619 02
620 620 checkheads
621 621 related
622 622 digests
623 623 md5
624 624 sha1
625 625 sha512
626 626 error
627 627 abort
628 628 unsupportedcontent
629 629 pushraced
630 630 pushkey
631 631 hgtagsfnodes
632 632 listkeys
633 633 phases
634 634 heads
635 635 pushkey
636 636 remote-changegroup
637 637 http
638 638 https
639 rev-branch-cache
640 639 stream
641 640 v2
642 641
643 642 Test debugpeer
644 643
645 644 $ hg --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" debugpeer ssh://user@dummy/debugrevlog
646 645 url: ssh://user@dummy/debugrevlog
647 646 local: no
648 647 pushable: yes
649 648
650 649 $ hg --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" --debug debugpeer ssh://user@dummy/debugrevlog
651 650 running "*" "*/tests/dummyssh" 'user@dummy' 'hg -R debugrevlog serve --stdio' (glob) (no-windows !)
652 651 running "*" "*\tests/dummyssh" "user@dummy" "hg -R debugrevlog serve --stdio" (glob) (windows !)
653 652 devel-peer-request: hello+between
654 653 devel-peer-request: pairs: 81 bytes
655 654 sending hello command
656 655 sending between command
657 remote: 463
656 remote: 444
658 657 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
659 658 remote: 1
660 659 devel-peer-request: protocaps
661 660 devel-peer-request: caps: * bytes (glob)
662 661 sending protocaps command
663 662 url: ssh://user@dummy/debugrevlog
664 663 local: no
665 664 pushable: yes
@@ -1,1306 +1,1285 b''
1 1 #require serve zstd
2 2
3 3 Client version is embedded in HTTP request and is effectively dynamic. Pin the
4 4 version so behavior is deterministic.
5 5
6 6 $ cat > fakeversion.py << EOF
7 7 > from mercurial import util
8 8 > util.version = lambda: b'4.2'
9 9 > EOF
10 10
11 11 $ cat >> $HGRCPATH << EOF
12 12 > [extensions]
13 13 > fakeversion = `pwd`/fakeversion.py
14 14 > [format]
15 15 > sparse-revlog = no
16 16 > [devel]
17 17 > legacy.exchange = phases
18 18 > [server]
19 19 > concurrent-push-mode = strict
20 20 > EOF
21 21
22 22 $ hg init server0
23 23 $ cd server0
24 24 $ touch foo
25 25 $ hg -q commit -A -m initial
26 26
27 27 Also disable compression because zstd is optional and causes output to vary
28 28 and because debugging partial responses is hard when compression is involved
29 29
30 30 $ cat > .hg/hgrc << EOF
31 31 > [extensions]
32 32 > badserver = $TESTDIR/badserverext.py
33 33 > [server]
34 34 > compressionengines = none
35 35 > EOF
36 36
37 37 Failure to accept() socket should result in connection related error message
38 38
39 39 $ hg serve --config badserver.closebeforeaccept=true -p $HGPORT -d --pid-file=hg.pid
40 40 $ cat hg.pid > $DAEMON_PIDS
41 41
42 42 $ hg clone http://localhost:$HGPORT/ clone
43 43 abort: error: (\$ECONNRESET\$|\$EADDRNOTAVAIL\$) (re)
44 44 [100]
45 45
46 46 (The server exits on its own, but there is a race between that and starting a new server.
47 47 So ensure the process is dead.)
48 48
49 49 $ killdaemons.py $DAEMON_PIDS
50 50
51 51 Failure immediately after accept() should yield connection related error message
52 52
53 53 $ hg serve --config badserver.closeafteraccept=true -p $HGPORT -d --pid-file=hg.pid
54 54 $ cat hg.pid > $DAEMON_PIDS
55 55
56 56 TODO: this usually outputs good results, but sometimes emits abort:
57 57 error: '' on FreeBSD and OS X.
58 58 What we ideally want are:
59 59
60 60 abort: error: $ECONNRESET$
61 61
62 62 The flakiness in this output was observable easily with
63 63 --runs-per-test=20 on macOS 10.12 during the freeze for 4.2.
64 64 $ hg clone http://localhost:$HGPORT/ clone
65 65 abort: error: * (glob)
66 66 [100]
67 67
68 68 $ killdaemons.py $DAEMON_PIDS
69 69
70 70 Failure to read all bytes in initial HTTP request should yield connection related error message
71 71
72 72 $ hg serve --config badserver.closeafterrecvbytes=1 -p $HGPORT -d --pid-file=hg.pid -E error.log
73 73 $ cat hg.pid > $DAEMON_PIDS
74 74
75 75 $ hg clone http://localhost:$HGPORT/ clone
76 76 abort: error: bad HTTP status line: * (glob)
77 77 [100]
78 78
79 79 $ killdaemons.py $DAEMON_PIDS
80 80
81 81 $ cat error.log
82 82 readline(1 from 65537) -> (1) G
83 83 read limit reached; closing socket
84 84
85 85 $ rm -f error.log
86 86
87 87 Same failure, but server reads full HTTP request line
88 88
89 89 $ hg serve --config badserver.closeafterrecvbytes=40 -p $HGPORT -d --pid-file=hg.pid -E error.log
90 90 $ cat hg.pid > $DAEMON_PIDS
91 91 $ hg clone http://localhost:$HGPORT/ clone
92 92 abort: error: bad HTTP status line: * (glob)
93 93 [100]
94 94
95 95 $ killdaemons.py $DAEMON_PIDS
96 96
97 97 $ cat error.log
98 98 readline(40 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
99 99 readline(7 from *) -> (7) Accept- (glob)
100 100 read limit reached; closing socket
101 101
102 102 $ rm -f error.log
103 103
104 104 Failure on subsequent HTTP request on the same socket (cmd?batch)
105 105
106 106 $ hg serve --config badserver.closeafterrecvbytes=210,223 -p $HGPORT -d --pid-file=hg.pid -E error.log
107 107 $ cat hg.pid > $DAEMON_PIDS
108 108 $ hg clone http://localhost:$HGPORT/ clone
109 109 abort: error: bad HTTP status line: * (glob)
110 110 [100]
111 111
112 112 $ killdaemons.py $DAEMON_PIDS
113 113
114 114 $ cat error.log
115 115 readline(210 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
116 116 readline(177 from *) -> (27) Accept-Encoding: identity\r\n (glob)
117 117 readline(150 from *) -> (35) accept: application/mercurial-0.1\r\n (glob)
118 118 readline(115 from *) -> (*) host: localhost:$HGPORT\r\n (glob)
119 119 readline(* from *) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
120 120 readline(* from *) -> (2) \r\n (glob)
121 sendall(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py36 !)
122 sendall(450) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
123 write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py3 no-py36 !)
124 write(450) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
121 sendall(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py36 !)
122 sendall(431) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
123 write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py3 no-py36 !)
124 write(431) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
125 125 write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !)
126 126 write(23) -> Server: badhttpserver\r\n (no-py3 !)
127 127 write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !)
128 128 write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !)
129 write(21) -> Content-Length: 450\r\n (no-py3 !)
129 write(21) -> Content-Length: 431\r\n (no-py3 !)
130 130 write(2) -> \r\n (no-py3 !)
131 write(450) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
131 write(431) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
132 132 readline(4? from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n (glob)
133 133 readline(1? from *) -> (1?) Accept-Encoding* (glob)
134 134 read limit reached; closing socket
135 135 readline(223 from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
136 136 readline(197 from *) -> (27) Accept-Encoding: identity\r\n (glob)
137 137 readline(170 from *) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
138 138 readline(141 from *) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n (glob)
139 139 readline(100 from *) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
140 140 readline(39 from *) -> (35) accept: application/mercurial-0.1\r\n (glob)
141 141 readline(4 from *) -> (4) host (glob)
142 142 read limit reached; closing socket
143 143
144 144 $ rm -f error.log
145 145
146 146 Failure to read getbundle HTTP request
147 147
148 148 $ hg serve --config badserver.closeafterrecvbytes=308,317,304 -p $HGPORT -d --pid-file=hg.pid -E error.log
149 149 $ cat hg.pid > $DAEMON_PIDS
150 150 $ hg clone http://localhost:$HGPORT/ clone
151 151 requesting all changes
152 152 abort: error: bad HTTP status line: * (glob)
153 153 [100]
154 154
155 155 $ killdaemons.py $DAEMON_PIDS
156 156
157 157 $ cat error.log
158 158 readline(1 from -1) -> (1) x (?)
159 159 readline(1 from -1) -> (1) x (?)
160 160 readline(308 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
161 161 readline(275 from *) -> (27) Accept-Encoding: identity\r\n (glob)
162 162 readline(248 from *) -> (35) accept: application/mercurial-0.1\r\n (glob)
163 163 readline(213 from *) -> (*) host: localhost:$HGPORT\r\n (glob)
164 164 readline(* from *) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
165 165 readline(* from *) -> (2) \r\n (glob)
166 sendall(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py36 !)
167 sendall(450) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
168 write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py3 no-py36 !)
169 write(450) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
166 sendall(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py36 !)
167 sendall(431) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
168 write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py3 no-py36 !)
169 write(431) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
170 170 write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !)
171 171 write(23) -> Server: badhttpserver\r\n (no-py3 !)
172 172 write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !)
173 173 write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !)
174 write(21) -> Content-Length: 450\r\n (no-py3 !)
174 write(21) -> Content-Length: 431\r\n (no-py3 !)
175 175 write(2) -> \r\n (no-py3 !)
176 write(450) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
176 write(431) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
177 177 readline(13? from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n (glob)
178 178 readline(1?? from *) -> (27) Accept-Encoding: identity\r\n (glob)
179 179 readline(8? from *) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
180 180 readline(5? from *) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n (glob)
181 181 readline(1? from *) -> (1?) x-hgproto-1:* (glob)
182 182 read limit reached; closing socket
183 183 readline(317 from 65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
184 184 readline(291 from *) -> (27) Accept-Encoding: identity\r\n (glob)
185 185 readline(264 from *) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
186 186 readline(235 from *) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n (glob)
187 187 readline(194 from *) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
188 188 readline(133 from *) -> (35) accept: application/mercurial-0.1\r\n (glob)
189 189 readline(98 from *) -> (*) host: localhost:$HGPORT\r\n (glob)
190 190 readline(* from *) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
191 191 readline(* from *) -> (2) \r\n (glob)
192 192 sendall(159) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py36 !)
193 193 sendall(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py36 !)
194 194 write(159) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py3 no-py36 !)
195 195 write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py3 no-py36 !)
196 196 write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !)
197 197 write(23) -> Server: badhttpserver\r\n (no-py3 !)
198 198 write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !)
199 199 write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !)
200 200 write(20) -> Content-Length: 42\r\n (no-py3 !)
201 201 write(2) -> \r\n (no-py3 !)
202 202 write(42) -> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (no-py3 !)
203 203 readline(* from 65537) -> (*) GET /?cmd=getbundle HTTP* (glob)
204 204 read limit reached; closing socket
205 205 readline(304 from 65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
206 206 readline(274 from *) -> (27) Accept-Encoding: identity\r\n (glob)
207 207 readline(247 from *) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
208 208 readline(218 from *) -> (218) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtag (glob)
209 209 read limit reached; closing socket
210 210
211 211 $ rm -f error.log
212 212
213 213 Now do a variation using POST to send arguments
214 214
215 215 $ hg serve --config experimental.httppostargs=true --config badserver.closeafterrecvbytes=329,344 -p $HGPORT -d --pid-file=hg.pid -E error.log
216 216 $ cat hg.pid > $DAEMON_PIDS
217 217
218 218 $ hg clone http://localhost:$HGPORT/ clone
219 219 abort: error: bad HTTP status line: * (glob)
220 220 [100]
221 221
222 222 $ killdaemons.py $DAEMON_PIDS
223 223
224 224 $ cat error.log | "$PYTHON" $TESTDIR/filtertraceback.py
225 225 readline(329 from 65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
226 226 readline(296 from *) -> (27) Accept-Encoding: identity\r\n (glob)
227 227 readline(269 from *) -> (35) accept: application/mercurial-0.1\r\n (glob)
228 228 readline(234 from *) -> (2?) host: localhost:$HGPORT\r\n (glob)
229 229 readline(* from *) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
230 230 readline(* from *) -> (2) \r\n (glob)
231 sendall(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 463\r\n\r\n (py36 !)
232 sendall(463) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
233 write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 463\r\n\r\n (py3 no-py36 !)
234 write(463) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
231 sendall(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 444\r\n\r\n (py36 !)
232 sendall(444) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
233 write(160) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 444\r\n\r\n (py3 no-py36 !)
234 write(444) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
235 235 write(36) -> HTTP/1.1 200 Script output follows\r\n (no-py3 !)
236 236 write(23) -> Server: badhttpserver\r\n (no-py3 !)
237 237 write(37) -> Date: $HTTP_DATE$\r\n (no-py3 !)
238 238 write(41) -> Content-Type: application/mercurial-0.1\r\n (no-py3 !)
239 write(21) -> Content-Length: 463\r\n (no-py3 !)
239 write(21) -> Content-Length: 444\r\n (no-py3 !)
240 240 write(2) -> \r\n (no-py3 !)
241 write(463) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
241 write(444) -> batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx httppostargs known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
242 242 readline(1?? from 65537) -> (27) POST /?cmd=batch HTTP/1.1\r\n (glob)
243 243 readline(1?? from *) -> (27) Accept-Encoding: identity\r\n (glob)
244 244 readline(1?? from *) -> (41) content-type: application/mercurial-0.1\r\n (glob)
245 245 readline(6? from *) -> (33) vary: X-HgArgs-Post,X-HgProto-1\r\n (glob)
246 246 readline(3? from *) -> (19) x-hgargs-post: 28\r\n (glob)
247 247 readline(1? from *) -> (1?) x-hgproto-1: * (glob)
248 248 read limit reached; closing socket
249 249 readline(344 from 65537) -> (27) POST /?cmd=batch HTTP/1.1\r\n
250 250 readline(317 from *) -> (27) Accept-Encoding: identity\r\n (glob)
251 251 readline(290 from *) -> (41) content-type: application/mercurial-0.1\r\n (glob)
252 252 readline(249 from *) -> (33) vary: X-HgArgs-Post,X-HgProto-1\r\n (glob)
253 253 readline(216 from *) -> (19) x-hgargs-post: 28\r\n (glob)
254 254 readline(197 from *) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
255 255 readline(136 from *) -> (35) accept: application/mercurial-0.1\r\n (glob)
256 256 readline(101 from *) -> (20) content-length: 28\r\n (glob)
257 257 readline(81 from *) -> (*) host: localhost:$HGPORT\r\n (glob)
258 258 readline(* from *) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
259 259 readline(* from *) -> (2) \r\n (glob)
260 260 read(* from 28) -> (*) cmds=* (glob)
261 261 read limit reached, closing socket
262 262 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=batch': (glob)
263 263 Traceback (most recent call last):
264 264 Exception: connection closed after receiving N bytes
265 265
266 266 write(126) -> HTTP/1.1 500 Internal Server Error\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nTransfer-Encoding: chunked\r\n\r\n (py3 no-py36 !)
267 267 write(36) -> HTTP/1.1 500 Internal Server Error\r\n (no-py3 !)
268 268
269 269 $ rm -f error.log
270 270
271 271 Now move on to partial server responses
272 272
273 273 Server sends a single character from the HTTP response line
274 274
275 275 $ hg serve --config badserver.closeaftersendbytes=1 -p $HGPORT -d --pid-file=hg.pid -E error.log
276 276 $ cat hg.pid > $DAEMON_PIDS
277 277
278 278 $ hg clone http://localhost:$HGPORT/ clone
279 279 abort: error: bad HTTP status line: H
280 280 [100]
281 281
282 282 $ killdaemons.py $DAEMON_PIDS
283 283
284 284 $ cat error.log | "$PYTHON" $TESTDIR/filtertraceback.py
285 285 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
286 286 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
287 287 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
288 288 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
289 289 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
290 290 readline(*) -> (2) \r\n (glob)
291 291 sendall(1 from 160) -> (0) H (py36 !)
292 292 write(1 from 160) -> (0) H (py3 no-py36 !)
293 293 write(1 from 36) -> (0) H (no-py3 !)
294 294 write limit reached; closing socket
295 295 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=capabilities': (glob)
296 296 Traceback (most recent call last):
297 297 Exception: connection closed after sending N bytes
298 298
299 write(286) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\nHTTP/1.1 500 Internal Server Error\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nTransfer-Encoding: chunked\r\n\r\n (py3 no-py36 !)
299 write(286) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\nHTTP/1.1 500 Internal Server Error\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nTransfer-Encoding: chunked\r\n\r\n (py3 no-py36 !)
300 300 write(36) -> HTTP/1.1 500 Internal Server Error\r\n (no-py3 !)
301 301
302 302 $ rm -f error.log
303 303
304 304 Server sends an incomplete capabilities response body
305 305
306 306 $ hg serve --config badserver.closeaftersendbytes=180 -p $HGPORT -d --pid-file=hg.pid -E error.log
307 307 $ cat hg.pid > $DAEMON_PIDS
308 308
309 309 $ hg clone http://localhost:$HGPORT/ clone
310 abort: HTTP request error (incomplete response; expected 450 bytes got 20)
310 abort: HTTP request error (incomplete response; expected 431 bytes got 20)
311 311 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
312 312 [255]
313 313
314 314 $ killdaemons.py $DAEMON_PIDS
315 315
316 316 $ cat error.log | "$PYTHON" $TESTDIR/filtertraceback.py
317 317 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
318 318 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
319 319 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
320 320 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
321 321 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
322 322 readline(*) -> (2) \r\n (glob)
323 sendall(160 from 160) -> (20) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py36 !)
324 sendall(20 from 450) -> (0) batch branchmap bund (py36 !)
325 write(160 from 160) -> (20) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py3 no-py36 !)
326 write(20 from 450) -> (0) batch branchmap bund (py3 no-py36 !)
323 sendall(160 from 160) -> (20) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py36 !)
324 sendall(20 from 431) -> (0) batch branchmap bund (py36 !)
325 write(160 from 160) -> (20) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py3 no-py36 !)
326 write(20 from 431) -> (0) batch branchmap bund (py3 no-py36 !)
327 327 write(36 from 36) -> (144) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
328 328 write(23 from 23) -> (121) Server: badhttpserver\r\n (no-py3 !)
329 329 write(37 from 37) -> (84) Date: $HTTP_DATE$\r\n (no-py3 !)
330 330 write(41 from 41) -> (43) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
331 write(21 from 21) -> (22) Content-Length: 450\r\n (no-py3 !)
331 write(21 from 21) -> (22) Content-Length: 431\r\n (no-py3 !)
332 332 write(2 from 2) -> (20) \r\n (no-py3 !)
333 write(20 from 450) -> (0) batch branchmap bund (no-py3 !)
333 write(20 from 431) -> (0) batch branchmap bund (no-py3 !)
334 334 write limit reached; closing socket
335 335 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=capabilities': (glob)
336 336 Traceback (most recent call last):
337 337 Exception: connection closed after sending N bytes
338 338
339 339
340 340 $ rm -f error.log
341 341
342 342 Server sends incomplete headers for batch request
343 343
344 $ hg serve --config badserver.closeaftersendbytes=728 -p $HGPORT -d --pid-file=hg.pid -E error.log
344 $ hg serve --config badserver.closeaftersendbytes=709 -p $HGPORT -d --pid-file=hg.pid -E error.log
345 345 $ cat hg.pid > $DAEMON_PIDS
346 346
347 347 TODO this output is horrible
348 348
349 349 $ hg clone http://localhost:$HGPORT/ clone
350 350 abort: 'http://localhost:$HGPORT/' does not appear to be an hg repository:
351 351 ---%<--- (applicat)
352 352
353 353 ---%<---
354 354
355 355 [255]
356 356
357 357 $ killdaemons.py $DAEMON_PIDS
358 358
359 359 $ cat error.log | "$PYTHON" $TESTDIR/filtertraceback.py
360 360 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
361 361 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
362 362 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
363 363 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
364 364 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
365 365 readline(*) -> (2) \r\n (glob)
366 sendall(160 from 160) -> (568) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py36 !)
367 sendall(450 from 450) -> (118) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
368 write(160 from 160) -> (568) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py3 no-py36 !)
369 write(450 from 450) -> (118) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
370 write(36 from 36) -> (692) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
371 write(23 from 23) -> (669) Server: badhttpserver\r\n (no-py3 !)
372 write(37 from 37) -> (632) Date: $HTTP_DATE$\r\n (no-py3 !)
373 write(41 from 41) -> (591) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
374 write(21 from 21) -> (570) Content-Length: 450\r\n (no-py3 !)
375 write(2 from 2) -> (568) \r\n (no-py3 !)
376 write(450 from 450) -> (118) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
366 sendall(160 from 160) -> (549) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py36 !)
367 sendall(431 from 431) -> (118) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
368 write(160 from 160) -> (568) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py3 no-py36 !)
369 write(431 from 431) -> (118) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
370 write(36 from 36) -> (673) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
371 write(23 from 23) -> (650) Server: badhttpserver\r\n (no-py3 !)
372 write(37 from 37) -> (613) Date: $HTTP_DATE$\r\n (no-py3 !)
373 write(41 from 41) -> (572) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
374 write(21 from 21) -> (551) Content-Length: 431\r\n (no-py3 !)
375 write(2 from 2) -> (549) \r\n (no-py3 !)
376 write(431 from 431) -> (118) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
377 377 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
378 378 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
379 379 readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
380 380 readline(*) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n (glob)
381 381 readline(*) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
382 382 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
383 383 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
384 384 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
385 385 readline(*) -> (2) \r\n (glob)
386 386 sendall(118 from 159) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: applicat (py36 !)
387 387 write(118 from 159) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: applicat (py3 no-py36 !)
388 388 write(36 from 36) -> (82) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
389 389 write(23 from 23) -> (59) Server: badhttpserver\r\n (no-py3 !)
390 390 write(37 from 37) -> (22) Date: $HTTP_DATE$\r\n (no-py3 !)
391 391 write(22 from 41) -> (0) Content-Type: applicat (no-py3 !)
392 392 write limit reached; closing socket
393 393 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=batch': (glob)
394 394 Traceback (most recent call last):
395 395 Exception: connection closed after sending N bytes
396 396
397 397 write(285) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\nHTTP/1.1 500 Internal Server Error\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nTransfer-Encoding: chunked\r\n\r\n (py3 no-py36 !)
398 398 write(36) -> HTTP/1.1 500 Internal Server Error\r\n (no-py3 !)
399 399
400 400 $ rm -f error.log
401 401
402 402 Server sends an incomplete HTTP response body to batch request
403 403
404 $ hg serve --config badserver.closeaftersendbytes=793 -p $HGPORT -d --pid-file=hg.pid -E error.log
404 $ hg serve --config badserver.closeaftersendbytes=774 -p $HGPORT -d --pid-file=hg.pid -E error.log
405 405 $ cat hg.pid > $DAEMON_PIDS
406 406
407 407 TODO client spews a stack due to uncaught ValueError in batch.results()
408 408 #if no-chg
409 409 $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null
410 410 [1]
411 411 #else
412 412 $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null
413 413 [255]
414 414 #endif
415 415
416 416 $ killdaemons.py $DAEMON_PIDS
417 417
418 418 $ cat error.log | "$PYTHON" $TESTDIR/filtertraceback.py
419 419 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
420 420 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
421 421 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
422 422 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
423 423 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
424 424 readline(*) -> (2) \r\n (glob)
425 sendall(160 from 160) -> (633) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py36 !)
426 sendall(450 from 450) -> (183) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
427 write(160 from 160) -> (633) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py3 no-py36 !)
428 write(450 from 450) -> (183) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
429 write(36 from 36) -> (757) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
430 write(23 from 23) -> (734) Server: badhttpserver\r\n (no-py3 !)
431 write(37 from 37) -> (697) Date: $HTTP_DATE$\r\n (no-py3 !)
432 write(41 from 41) -> (656) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
433 write(21 from 21) -> (635) Content-Length: 450\r\n (no-py3 !)
434 write(2 from 2) -> (633) \r\n (no-py3 !)
435 write(450 from 450) -> (183) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
425 sendall(160 from 160) -> (614) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py36 !)
426 sendall(431 from 431) -> (183) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
427 write(160 from 160) -> (633) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py3 no-py36 !)
428 write(431 from 431) -> (183) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
429 write(36 from 36) -> (738) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
430 write(23 from 23) -> (715) Server: badhttpserver\r\n (no-py3 !)
431 write(37 from 37) -> (678) Date: $HTTP_DATE$\r\n (no-py3 !)
432 write(41 from 41) -> (637) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
433 write(21 from 21) -> (616) Content-Length: 431\r\n (no-py3 !)
434 write(2 from 2) -> (614) \r\n (no-py3 !)
435 write(431 from 431) -> (183) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
436 436 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
437 437 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
438 438 readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
439 439 readline(*) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n (glob)
440 440 readline(*) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
441 441 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
442 442 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
443 443 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
444 444 readline(*) -> (2) \r\n (glob)
445 445 sendall(159 from 159) -> (24) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py36 !)
446 446 sendall(24 from 42) -> (0) 96ee1d7354c4ad7372047672 (py36 !)
447 447 write(159 from 159) -> (24) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py3 no-py36 !)
448 448 write(24 from 42) -> (0) 96ee1d7354c4ad7372047672 (py3 no-py36 !)
449 449 write(36 from 36) -> (147) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
450 450 write(23 from 23) -> (124) Server: badhttpserver\r\n (no-py3 !)
451 451 write(37 from 37) -> (87) Date: $HTTP_DATE$\r\n (no-py3 !)
452 452 write(41 from 41) -> (46) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
453 453 write(20 from 20) -> (26) Content-Length: 42\r\n (no-py3 !)
454 454 write(2 from 2) -> (24) \r\n (no-py3 !)
455 455 write(24 from 42) -> (0) 96ee1d7354c4ad7372047672 (no-py3 !)
456 456 write limit reached; closing socket
457 457 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=batch': (glob)
458 458 Traceback (most recent call last):
459 459 Exception: connection closed after sending N bytes
460 460
461 461
462 462 $ rm -f error.log
463 463
464 464 Server sends incomplete headers for getbundle response
465 465
466 $ hg serve --config badserver.closeaftersendbytes=940 -p $HGPORT -d --pid-file=hg.pid -E error.log
466 $ hg serve --config badserver.closeaftersendbytes=921 -p $HGPORT -d --pid-file=hg.pid -E error.log
467 467 $ cat hg.pid > $DAEMON_PIDS
468 468
469 469 TODO this output is terrible
470 470
471 471 $ hg clone http://localhost:$HGPORT/ clone
472 472 requesting all changes
473 473 abort: 'http://localhost:$HGPORT/' does not appear to be an hg repository:
474 474 ---%<--- (application/mercuri)
475 475
476 476 ---%<---
477 477
478 478 [255]
479 479
480 480 $ killdaemons.py $DAEMON_PIDS
481 481
482 482 $ cat error.log | "$PYTHON" $TESTDIR/filtertraceback.py
483 483 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
484 484 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
485 485 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
486 486 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
487 487 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
488 488 readline(*) -> (2) \r\n (glob)
489 sendall(160 from 160) -> (780) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py36 !)
490 sendall(450 from 450) -> (330) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
491 write(160 from 160) -> (780) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py3 no-py36 !)
492 write(450 from 450) -> (330) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
493 write(36 from 36) -> (904) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
494 write(23 from 23) -> (881) Server: badhttpserver\r\n (no-py3 !)
495 write(37 from 37) -> (844) Date: $HTTP_DATE$\r\n (no-py3 !)
496 write(41 from 41) -> (803) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
497 write(21 from 21) -> (782) Content-Length: 450\r\n (no-py3 !)
498 write(2 from 2) -> (780) \r\n (no-py3 !)
499 write(450 from 450) -> (330) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
489 sendall(160 from 160) -> (761) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py36 !)
490 sendall(431 from 431) -> (330) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
491 write(160 from 160) -> (780) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py3 no-py36 !)
492 write(431 from 431) -> (330) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
493 write(36 from 36) -> (885) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
494 write(23 from 23) -> (862) Server: badhttpserver\r\n (no-py3 !)
495 write(37 from 37) -> (825) Date: $HTTP_DATE$\r\n (no-py3 !)
496 write(41 from 41) -> (784) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
497 write(21 from 21) -> (763) Content-Length: 431\r\n (no-py3 !)
498 write(2 from 2) -> (761) \r\n (no-py3 !)
499 write(431 from 431) -> (330) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
500 500 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
501 501 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
502 502 readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
503 503 readline(*) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n (glob)
504 504 readline(*) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
505 505 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
506 506 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
507 507 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
508 508 readline(*) -> (2) \r\n (glob)
509 509 sendall(159 from 159) -> (171) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py36 !)
510 510 sendall(42 from 42) -> (129) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py36 !)
511 511 write(159 from 159) -> (171) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py3 no-py36 !)
512 512 write(42 from 42) -> (129) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py3 no-py36 !)
513 513 write(36 from 36) -> (294) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
514 514 write(23 from 23) -> (271) Server: badhttpserver\r\n (no-py3 !)
515 515 write(37 from 37) -> (234) Date: $HTTP_DATE$\r\n (no-py3 !)
516 516 write(41 from 41) -> (193) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
517 517 write(20 from 20) -> (173) Content-Length: 42\r\n (no-py3 !)
518 518 write(2 from 2) -> (171) \r\n (no-py3 !)
519 519 write(42 from 42) -> (129) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (no-py3 !)
520 520 readline(65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
521 521 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
522 522 readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
523 readline(*) -> (461) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n (glob)
523 readline(*) -> (440) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n (glob)
524 524 readline(*) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
525 525 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
526 526 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
527 527 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
528 528 readline(*) -> (2) \r\n (glob)
529 529 sendall(129 from 167) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercuri (py36 !)
530 530 write(129 from 167) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercuri (py3 no-py36 !)
531 531 write(36 from 36) -> (93) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
532 532 write(23 from 23) -> (70) Server: badhttpserver\r\n (no-py3 !)
533 533 write(37 from 37) -> (33) Date: $HTTP_DATE$\r\n (no-py3 !)
534 534 write(33 from 41) -> (0) Content-Type: application/mercuri (no-py3 !)
535 535 write limit reached; closing socket
536 536 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
537 537 Traceback (most recent call last):
538 538 Exception: connection closed after sending N bytes
539 539
540 540 write(293) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\nHTTP/1.1 500 Internal Server Error\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nTransfer-Encoding: chunked\r\n\r\n (py3 no-py36 !)
541 541 write(36) -> HTTP/1.1 500 Internal Server Error\r\n (no-py3 !)
542 542
543 543 $ rm -f error.log
544 544
545 545 Server stops before it sends transfer encoding
546 546
547 $ hg serve --config badserver.closeaftersendbytes=973 -p $HGPORT -d --pid-file=hg.pid -E error.log
547 $ hg serve --config badserver.closeaftersendbytes=954 -p $HGPORT -d --pid-file=hg.pid -E error.log
548 548 $ cat hg.pid > $DAEMON_PIDS
549 549
550 550 $ hg clone http://localhost:$HGPORT/ clone
551 551 requesting all changes
552 552 abort: stream ended unexpectedly (got 0 bytes, expected 1)
553 553 [255]
554 554
555 555 $ killdaemons.py $DAEMON_PIDS
556 556
557 557 #if py36
558 558 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -3
559 559 Traceback (most recent call last):
560 560 Exception: connection closed after sending N bytes
561 561
562 562
563 563 #else
564 564 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -4
565 565 Traceback (most recent call last):
566 566 Exception: connection closed after sending N bytes
567 567
568 568 write(293) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\nHTTP/1.1 500 Internal Server Error\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !)
569 569 write(36) -> HTTP/1.1 500 Internal Server Error\r\n (no-py3 !)
570 570 #endif
571 571
572 572 $ rm -f error.log
573 573
574 574 Server sends empty HTTP body for getbundle
575 575
576 $ hg serve --config badserver.closeaftersendbytes=978 -p $HGPORT -d --pid-file=hg.pid -E error.log
576 $ hg serve --config badserver.closeaftersendbytes=959 -p $HGPORT -d --pid-file=hg.pid -E error.log
577 577 $ cat hg.pid > $DAEMON_PIDS
578 578
579 579 $ hg clone http://localhost:$HGPORT/ clone
580 580 requesting all changes
581 581 abort: HTTP request error (incomplete response)
582 582 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
583 583 [255]
584 584
585 585 $ killdaemons.py $DAEMON_PIDS
586 586
587 587 $ cat error.log | "$PYTHON" $TESTDIR/filtertraceback.py
588 588 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
589 589 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
590 590 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
591 591 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
592 592 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
593 593 readline(*) -> (2) \r\n (glob)
594 sendall(160 from 160) -> (818) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py36 !)
595 sendall(450 from 450) -> (368) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
596 write(160 from 160) -> (818) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py3 no-py36 !)
597 write(450 from 450) -> (368) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
598 write(36 from 36) -> (942) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
599 write(23 from 23) -> (919) Server: badhttpserver\r\n (no-py3 !)
600 write(37 from 37) -> (882) Date: $HTTP_DATE$\r\n (no-py3 !)
601 write(41 from 41) -> (841) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
602 write(21 from 21) -> (820) Content-Length: 450\r\n (no-py3 !)
603 write(2 from 2) -> (818) \r\n (no-py3 !)
604 write(450 from 450) -> (368) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
594 sendall(160 from 160) -> (799) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py36 !)
595 sendall(431 from 431) -> (368) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
596 write(160 from 160) -> (818) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py3 no-py36 !)
597 write(431 from 431) -> (368) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
598 write(36 from 36) -> (923) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
599 write(23 from 23) -> (900) Server: badhttpserver\r\n (no-py3 !)
600 write(37 from 37) -> (863) Date: $HTTP_DATE$\r\n (no-py3 !)
601 write(41 from 41) -> (822) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
602 write(21 from 21) -> (801) Content-Length: 431\r\n (no-py3 !)
603 write(2 from 2) -> (799) \r\n (no-py3 !)
604 write(431 from 431) -> (368) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
605 605 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
606 606 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
607 607 readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
608 608 readline(*) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n (glob)
609 609 readline(*) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
610 610 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
611 611 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
612 612 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
613 613 readline(*) -> (2) \r\n (glob)
614 614 sendall(159 from 159) -> (209) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py36 !)
615 615 sendall(42 from 42) -> (167) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py36 !)
616 616 write(159 from 159) -> (209) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py3 no-py36 !)
617 617 write(42 from 42) -> (167) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py3 no-py36 !)
618 618 write(36 from 36) -> (332) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
619 619 write(23 from 23) -> (309) Server: badhttpserver\r\n (no-py3 !)
620 620 write(37 from 37) -> (272) Date: $HTTP_DATE$\r\n (no-py3 !)
621 621 write(41 from 41) -> (231) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
622 622 write(20 from 20) -> (211) Content-Length: 42\r\n (no-py3 !)
623 623 write(2 from 2) -> (209) \r\n (no-py3 !)
624 624 write(42 from 42) -> (167) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (no-py3 !)
625 625 readline(65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
626 626 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
627 627 readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
628 readline(*) -> (461) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n (glob)
628 readline(*) -> (440) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n (glob)
629 629 readline(*) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
630 630 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
631 631 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
632 632 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
633 633 readline(*) -> (2) \r\n (glob)
634 634 sendall(167 from 167) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py36 !)
635 635 write(167 from 167) -> (0) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 no-py36 !)
636 636 write(36 from 36) -> (131) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
637 637 write(23 from 23) -> (108) Server: badhttpserver\r\n (no-py3 !)
638 638 write(37 from 37) -> (71) Date: $HTTP_DATE$\r\n (no-py3 !)
639 639 write(41 from 41) -> (30) Content-Type: application/mercurial-0.2\r\n (no-py3 !)
640 640 write(28 from 28) -> (2) Transfer-Encoding: chunked\r\n (no-py3 !)
641 641 write(2 from 2) -> (0) \r\n (no-py3 !)
642 642 write limit reached; closing socket
643 643 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
644 644 Traceback (most recent call last):
645 645 Exception: connection closed after sending N bytes
646 646
647 647 write(293) -> HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\nHTTP/1.1 500 Internal Server Error\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nTransfer-Encoding: chunked\r\n\r\n (py3 no-py36 !)
648 648 write(36) -> HTTP/1.1 500 Internal Server Error\r\n (no-py3 !)
649 649
650 650 $ rm -f error.log
651 651
652 652 Server sends partial compression string
653 653
654 $ hg serve --config badserver.closeaftersendbytes=1002 -p $HGPORT -d --pid-file=hg.pid -E error.log
654 $ hg serve --config badserver.closeaftersendbytes=983 -p $HGPORT -d --pid-file=hg.pid -E error.log
655 655 $ cat hg.pid > $DAEMON_PIDS
656 656
657 657 $ hg clone http://localhost:$HGPORT/ clone
658 658 requesting all changes
659 659 abort: HTTP request error (incomplete response)
660 660 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
661 661 [255]
662 662
663 663 $ killdaemons.py $DAEMON_PIDS
664 664
665 665 $ cat error.log | "$PYTHON" $TESTDIR/filtertraceback.py
666 666 readline(65537) -> (33) GET /?cmd=capabilities HTTP/1.1\r\n
667 667 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
668 668 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
669 669 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
670 670 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
671 671 readline(*) -> (2) \r\n (glob)
672 sendall(160 from 160) -> (842) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py36 !)
673 sendall(450 from 450) -> (392) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
674 write(160 from 160) -> (842) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 450\r\n\r\n (py3 no-py36 !)
675 write(450 from 450) -> (392) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
676 write(36 from 36) -> (966) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
677 write(23 from 23) -> (943) Server: badhttpserver\r\n (no-py3 !)
678 write(37 from 37) -> (906) Date: $HTTP_DATE$\r\n (no-py3 !)
679 write(41 from 41) -> (865) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
680 write(21 from 21) -> (844) Content-Length: 450\r\n (no-py3 !)
681 write(2 from 2) -> (842) \r\n (no-py3 !)
682 write(450 from 450) -> (392) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
672 sendall(160 from 160) -> (823) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py36 !)
673 sendall(431 from 431) -> (392) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py36 !)
674 write(160 from 160) -> (842) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 431\r\n\r\n (py3 no-py36 !)
675 write(431 from 431) -> (392) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (py3 no-py36 !)
676 write(36 from 36) -> (947) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
677 write(23 from 23) -> (924) Server: badhttpserver\r\n (no-py3 !)
678 write(37 from 37) -> (887) Date: $HTTP_DATE$\r\n (no-py3 !)
679 write(41 from 41) -> (846) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
680 write(21 from 21) -> (825) Content-Length: 431\r\n (no-py3 !)
681 write(2 from 2) -> (823) \r\n (no-py3 !)
682 write(431 from 431) -> (392) batch branchmap $USUAL_BUNDLE2_CAPS_NO_PHASES$ changegroupsubset compression=none getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-py3 !)
683 683 readline(65537) -> (26) GET /?cmd=batch HTTP/1.1\r\n
684 684 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
685 685 readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
686 686 readline(*) -> (41) x-hgarg-1: cmds=heads+%3Bknown+nodes%3D\r\n (glob)
687 687 readline(*) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
688 688 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
689 689 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
690 690 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
691 691 readline(*) -> (2) \r\n (glob)
692 692 sendall(159 from 159) -> (233) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py36 !)
693 693 sendall(42 from 42) -> (191) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (py36 !)
694 694 write(159 from 159) -> (233) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.1\r\nContent-Length: 42\r\n\r\n (py3 no-py36 !)
695 695 write(36 from 36) -> (356) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
696 696 write(23 from 23) -> (333) Server: badhttpserver\r\n (no-py3 !)
697 697 write(37 from 37) -> (296) Date: $HTTP_DATE$\r\n (no-py3 !)
698 698 write(41 from 41) -> (255) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
699 699 write(20 from 20) -> (235) Content-Length: 42\r\n (no-py3 !)
700 700 write(2 from 2) -> (233) \r\n (no-py3 !)
701 701 write(42 from 42) -> (191) 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n; (no-py3 !)
702 702 readline(65537) -> (30) GET /?cmd=getbundle HTTP/1.1\r\n
703 703 readline(*) -> (27) Accept-Encoding: identity\r\n (glob)
704 704 readline(*) -> (29) vary: X-HgArg-1,X-HgProto-1\r\n (glob)
705 readline(*) -> (461) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n (glob)
705 readline(*) -> (440) x-hgarg-1: bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=96ee1d7354c4ad7372047672c36a1f561e3a6a4c&listkeys=phases%2Cbookmarks\r\n (glob)
706 706 readline(*) -> (61) x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n (glob)
707 707 readline(*) -> (35) accept: application/mercurial-0.1\r\n (glob)
708 708 readline(*) -> (2?) host: localhost:$HGPORT\r\n (glob)
709 709 readline(*) -> (49) user-agent: mercurial/proto-1.0 (Mercurial 4.2)\r\n (glob)
710 710 readline(*) -> (2) \r\n (glob)
711 711 sendall(167 from 167) -> (24) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py36 !)
712 712 sendall(6 from 6) -> (18) 1\\r\\n\x04\\r\\n (esc) (py36 !)
713 713 sendall(9 from 9) -> (9) 4\r\nnone\r\n (py36 !)
714 714 sendall(9 from 9) -> (0) 4\r\nHG20\r\n (py36 !)
715 715 write(167 from 167) -> (24) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 no-py36 !)
716 716 write(36 from 36) -> (155) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
717 717 write(23 from 23) -> (132) Server: badhttpserver\r\n (no-py3 !)
718 718 write(37 from 37) -> (95) Date: $HTTP_DATE$\r\n (no-py3 !)
719 719 write(41 from 41) -> (54) Content-Type: application/mercurial-0.2\r\n (no-py3 !)
720 720 write(28 from 28) -> (26) Transfer-Encoding: chunked\r\n (no-py3 !)
721 721 write(2 from 2) -> (24) \r\n (no-py3 !)
722 722 write(6 from 6) -> (18) 1\\r\\n\x04\\r\\n (esc) (no-py3 !)
723 723 write(9 from 9) -> (9) 4\r\nnone\r\n (no-py3 !)
724 724 write(9 from 9) -> (0) 4\r\nHG20\r\n (no-py3 !)
725 725 write limit reached; closing socket
726 726 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
727 727 Traceback (most recent call last):
728 728 Exception: connection closed after sending N bytes
729 729
730 730 write(27) -> 15\r\nInternal Server Error\r\n (no-py3 !)
731 731
732 732 $ rm -f error.log
733 733
734 734 Server sends partial bundle2 header magic
735 735
736 $ hg serve --config badserver.closeaftersendbytes=999 -p $HGPORT -d --pid-file=hg.pid -E error.log
736 $ hg serve --config badserver.closeaftersendbytes=980 -p $HGPORT -d --pid-file=hg.pid -E error.log
737 737 $ cat hg.pid > $DAEMON_PIDS
738 738
739 739 $ hg clone http://localhost:$HGPORT/ clone
740 740 requesting all changes
741 741 abort: HTTP request error (incomplete response) (py3 !)
742 742 abort: HTTP request error (incomplete response; expected 4 bytes got 3) (no-py3 !)
743 743 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
744 744 [255]
745 745
746 746 $ killdaemons.py $DAEMON_PIDS
747 747
748 748 #if py36
749 749 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -9
750 750 sendall(167 from 167) -> (21) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n
751 751 sendall(6 from 6) -> (15) 1\\r\\n\x04\\r\\n (esc)
752 752 sendall(9 from 9) -> (6) 4\r\nnone\r\n
753 753 sendall(6 from 9) -> (0) 4\r\nHG2
754 754 write limit reached; closing socket
755 755 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
756 756 Traceback (most recent call last):
757 757 Exception: connection closed after sending N bytes
758 758
759 759
760 760 #else
761 761 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -11
762 762 readline(65537) -> (2) \r\n (py3 !)
763 763 write(167 from 167) -> (21) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !)
764 764 write(28 from 28) -> (23) Transfer-Encoding: chunked\r\n (no-py3 !)
765 765 write(2 from 2) -> (21) \r\n (no-py3 !)
766 766 write(6 from 6) -> (15) 1\\r\\n\x04\\r\\n (esc)
767 767 write(9 from 9) -> (6) 4\r\nnone\r\n
768 768 write(6 from 9) -> (0) 4\r\nHG2
769 769 write limit reached; closing socket
770 770 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
771 771 Traceback (most recent call last):
772 772 Exception: connection closed after sending N bytes
773 773
774 774 write(27) -> 15\r\nInternal Server Error\r\n
775 775 #endif
776 776
777 777 $ rm -f error.log
778 778
779 779 Server sends incomplete bundle2 stream params length
780 780
781 $ hg serve --config badserver.closeaftersendbytes=1008 -p $HGPORT -d --pid-file=hg.pid -E error.log
781 $ hg serve --config badserver.closeaftersendbytes=989 -p $HGPORT -d --pid-file=hg.pid -E error.log
782 782 $ cat hg.pid > $DAEMON_PIDS
783 783
784 784 $ hg clone http://localhost:$HGPORT/ clone
785 785 requesting all changes
786 786 abort: HTTP request error (incomplete response) (py3 !)
787 787 abort: HTTP request error (incomplete response; expected 4 bytes got 3) (no-py3 !)
788 788 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
789 789 [255]
790 790
791 791 $ killdaemons.py $DAEMON_PIDS
792 792
793 793 #if py36
794 794 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -10
795 795 sendall(167 from 167) -> (30) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n
796 796 sendall(6 from 6) -> (24) 1\\r\\n\x04\\r\\n (esc)
797 797 sendall(9 from 9) -> (15) 4\r\nnone\r\n
798 798 sendall(9 from 9) -> (6) 4\r\nHG20\r\n
799 799 sendall(6 from 9) -> (0) 4\\r\\n\x00\x00\x00 (esc)
800 800 write limit reached; closing socket
801 801 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
802 802 Traceback (most recent call last):
803 803 Exception: connection closed after sending N bytes
804 804
805 805
806 806 #else
807 807 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -12
808 808 readline(65537) -> (2) \r\n (py3 !)
809 809 write(167 from 167) -> (30) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !)
810 810 write(28 from 28) -> (32) Transfer-Encoding: chunked\r\n (no-py3 !)
811 811 write(2 from 2) -> (30) \r\n (no-py3 !)
812 812 write(6 from 6) -> (24) 1\\r\\n\x04\\r\\n (esc)
813 813 write(9 from 9) -> (15) 4\r\nnone\r\n
814 814 write(9 from 9) -> (6) 4\r\nHG20\r\n
815 815 write(6 from 9) -> (0) 4\\r\\n\x00\x00\x00 (esc)
816 816 write limit reached; closing socket
817 817 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
818 818 Traceback (most recent call last):
819 819 Exception: connection closed after sending N bytes
820 820
821 821 write(27) -> 15\r\nInternal Server Error\r\n
822 822 #endif
823 823
824 824 $ rm -f error.log
825 825
826 826 Servers stops after bundle2 stream params header
827 827
828 $ hg serve --config badserver.closeaftersendbytes=1011 -p $HGPORT -d --pid-file=hg.pid -E error.log
828 $ hg serve --config badserver.closeaftersendbytes=992 -p $HGPORT -d --pid-file=hg.pid -E error.log
829 829 $ cat hg.pid > $DAEMON_PIDS
830 830
831 831 $ hg clone http://localhost:$HGPORT/ clone
832 832 requesting all changes
833 833 abort: HTTP request error (incomplete response)
834 834 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
835 835 [255]
836 836
837 837 $ killdaemons.py $DAEMON_PIDS
838 838
839 839 #if py36
840 840 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -10
841 841 sendall(167 from 167) -> (33) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n
842 842 sendall(6 from 6) -> (27) 1\\r\\n\x04\\r\\n (esc)
843 843 sendall(9 from 9) -> (18) 4\r\nnone\r\n
844 844 sendall(9 from 9) -> (9) 4\r\nHG20\r\n
845 845 sendall(9 from 9) -> (0) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
846 846 write limit reached; closing socket
847 847 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
848 848 Traceback (most recent call last):
849 849 Exception: connection closed after sending N bytes
850 850
851 851
852 852 #else
853 853 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -12
854 854 readline(65537) -> (2) \r\n (py3 !)
855 855 write(167 from 167) -> (33) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !)
856 856 write(28 from 28) -> (35) Transfer-Encoding: chunked\r\n (no-py3 !)
857 857 write(2 from 2) -> (33) \r\n (no-py3 !)
858 858 write(6 from 6) -> (27) 1\\r\\n\x04\\r\\n (esc)
859 859 write(9 from 9) -> (18) 4\r\nnone\r\n
860 860 write(9 from 9) -> (9) 4\r\nHG20\r\n
861 861 write(9 from 9) -> (0) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
862 862 write limit reached; closing socket
863 863 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
864 864 Traceback (most recent call last):
865 865 Exception: connection closed after sending N bytes
866 866
867 867 write(27) -> 15\r\nInternal Server Error\r\n
868 868 #endif
869 869
870 870 $ rm -f error.log
871 871
872 872 Server stops sending after bundle2 part header length
873 873
874 $ hg serve --config badserver.closeaftersendbytes=1020 -p $HGPORT -d --pid-file=hg.pid -E error.log
874 $ hg serve --config badserver.closeaftersendbytes=1001 -p $HGPORT -d --pid-file=hg.pid -E error.log
875 875 $ cat hg.pid > $DAEMON_PIDS
876 876
877 877 $ hg clone http://localhost:$HGPORT/ clone
878 878 requesting all changes
879 879 abort: HTTP request error (incomplete response)
880 880 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
881 881 [255]
882 882
883 883 $ killdaemons.py $DAEMON_PIDS
884 884
885 885 #if py36
886 886 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -11
887 887 sendall(167 from 167) -> (42) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n
888 888 sendall(6 from 6) -> (36) 1\\r\\n\x04\\r\\n (esc)
889 889 sendall(9 from 9) -> (27) 4\r\nnone\r\n
890 890 sendall(9 from 9) -> (18) 4\r\nHG20\r\n
891 891 sendall(9 from 9) -> (9) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
892 892 sendall(9 from 9) -> (0) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
893 893 write limit reached; closing socket
894 894 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
895 895 Traceback (most recent call last):
896 896 Exception: connection closed after sending N bytes
897 897
898 898
899 899 #else
900 900
901 901 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -13
902 902 readline(65537) -> (2) \r\n (py3 !)
903 903 write(167 from 167) -> (42) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !)
904 904 write(28 from 28) -> (44) Transfer-Encoding: chunked\r\n (no-py3 !)
905 905 write(2 from 2) -> (42) \r\n (no-py3 !)
906 906 write(6 from 6) -> (36) 1\\r\\n\x04\\r\\n (esc)
907 907 write(9 from 9) -> (27) 4\r\nnone\r\n
908 908 write(9 from 9) -> (18) 4\r\nHG20\r\n
909 909 write(9 from 9) -> (9) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
910 910 write(9 from 9) -> (0) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
911 911 write limit reached; closing socket
912 912 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
913 913 Traceback (most recent call last):
914 914 Exception: connection closed after sending N bytes
915 915
916 916 write(27) -> 15\r\nInternal Server Error\r\n
917 917 #endif
918 918
919 919 $ rm -f error.log
920 920
921 921 Server stops sending after bundle2 part header
922 922
923 $ hg serve --config badserver.closeaftersendbytes=1067 -p $HGPORT -d --pid-file=hg.pid -E error.log
923 $ hg serve --config badserver.closeaftersendbytes=1048 -p $HGPORT -d --pid-file=hg.pid -E error.log
924 924 $ cat hg.pid > $DAEMON_PIDS
925 925
926 926 $ hg clone http://localhost:$HGPORT/ clone
927 927 requesting all changes
928 928 adding changesets
929 929 transaction abort!
930 930 rollback completed
931 931 abort: HTTP request error (incomplete response)
932 932 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
933 933 [255]
934 934
935 935 $ killdaemons.py $DAEMON_PIDS
936 936
937 937 #if py36
938 938 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -12
939 939 sendall(167 from 167) -> (89) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n
940 940 sendall(6 from 6) -> (83) 1\\r\\n\x04\\r\\n (esc)
941 941 sendall(9 from 9) -> (74) 4\r\nnone\r\n
942 942 sendall(9 from 9) -> (65) 4\r\nHG20\r\n
943 943 sendall(9 from 9) -> (56) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
944 944 sendall(9 from 9) -> (47) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
945 945 sendall(47 from 47) -> (0) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
946 946 write limit reached; closing socket
947 947 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
948 948 Traceback (most recent call last):
949 949 Exception: connection closed after sending N bytes
950 950
951 951
952 952 #else
953 953 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -14
954 954 readline(65537) -> (2) \r\n (py3 !)
955 955 write(167 from 167) -> (89) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !)
956 956 write(28 from 28) -> (91) Transfer-Encoding: chunked\r\n (no-py3 !)
957 957 write(2 from 2) -> (89) \r\n (no-py3 !)
958 958 write(6 from 6) -> (83) 1\\r\\n\x04\\r\\n (esc)
959 959 write(9 from 9) -> (74) 4\r\nnone\r\n
960 960 write(9 from 9) -> (65) 4\r\nHG20\r\n
961 961 write(9 from 9) -> (56) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
962 962 write(9 from 9) -> (47) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
963 963 write(47 from 47) -> (0) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
964 964 write limit reached; closing socket
965 965 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
966 966 Traceback (most recent call last):
967 967 Exception: connection closed after sending N bytes
968 968
969 969 write(27) -> 15\r\nInternal Server Error\r\n
970 970 #endif
971 971
972 972 $ rm -f error.log
973 973
974 974 Server stops after bundle2 part payload chunk size
975 975
976 $ hg serve --config badserver.closeaftersendbytes=1088 -p $HGPORT -d --pid-file=hg.pid -E error.log
976 $ hg serve --config badserver.closeaftersendbytes=1069 -p $HGPORT -d --pid-file=hg.pid -E error.log
977 977 $ cat hg.pid > $DAEMON_PIDS
978 978
979 979 $ hg clone http://localhost:$HGPORT/ clone
980 980 requesting all changes
981 981 adding changesets
982 982 transaction abort!
983 983 rollback completed
984 984 abort: HTTP request error (incomplete response) (py3 !)
985 985 abort: HTTP request error (incomplete response; expected 466 bytes got 7) (no-py3 !)
986 986 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
987 987 [255]
988 988
989 989 $ killdaemons.py $DAEMON_PIDS
990 990
991 991 #if py36
992 992 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -14
993 993 sendall(167 from 167) -> (110) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n
994 994 sendall(6 from 6) -> (104) 1\\r\\n\x04\\r\\n (esc)
995 995 sendall(9 from 9) -> (95) 4\r\nnone\r\n
996 996 sendall(9 from 9) -> (86) 4\r\nHG20\r\n
997 997 sendall(9 from 9) -> (77) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
998 998 sendall(9 from 9) -> (68) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
999 999 sendall(47 from 47) -> (21) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1000 1000 sendall(9 from 9) -> (12) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1001 1001 sendall(12 from 473) -> (0) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1d (esc)
1002 1002 write limit reached; closing socket
1003 1003 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1004 1004 Traceback (most recent call last):
1005 1005 Exception: connection closed after sending N bytes
1006 1006
1007 1007
1008 1008 #else
1009 1009 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -15
1010 1010 write(167 from 167) -> (110) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !)
1011 1011 write(2 from 2) -> (110) \r\n (no-py3 !)
1012 1012 write(6 from 6) -> (104) 1\\r\\n\x04\\r\\n (esc)
1013 1013 write(9 from 9) -> (95) 4\r\nnone\r\n
1014 1014 write(9 from 9) -> (86) 4\r\nHG20\r\n
1015 1015 write(9 from 9) -> (77) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1016 1016 write(9 from 9) -> (68) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1017 1017 write(47 from 47) -> (21) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1018 1018 write(9 from 9) -> (12) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1019 1019 write(12 from 473) -> (0) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1d (esc)
1020 1020 write limit reached; closing socket
1021 1021 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1022 1022 Traceback (most recent call last):
1023 1023 Exception: connection closed after sending N bytes
1024 1024
1025 1025 write(27) -> 15\r\nInternal Server Error\r\n
1026 1026 #endif
1027 1027
1028 1028 $ rm -f error.log
1029 1029
1030 1030 Server stops sending in middle of bundle2 payload chunk
1031 1031
1032 $ hg serve --config badserver.closeaftersendbytes=1549 -p $HGPORT -d --pid-file=hg.pid -E error.log
1032 $ hg serve --config badserver.closeaftersendbytes=1530 -p $HGPORT -d --pid-file=hg.pid -E error.log
1033 1033 $ cat hg.pid > $DAEMON_PIDS
1034 1034
1035 1035 $ hg clone http://localhost:$HGPORT/ clone
1036 1036 requesting all changes
1037 1037 adding changesets
1038 1038 transaction abort!
1039 1039 rollback completed
1040 1040 abort: HTTP request error (incomplete response)
1041 1041 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
1042 1042 [255]
1043 1043
1044 1044 $ killdaemons.py $DAEMON_PIDS
1045 1045
1046 1046 #if py36
1047 1047 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -14
1048 1048 sendall(167 from 167) -> (571) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n
1049 1049 sendall(6 from 6) -> (565) 1\\r\\n\x04\\r\\n (esc)
1050 1050 sendall(9 from 9) -> (556) 4\r\nnone\r\n
1051 1051 sendall(9 from 9) -> (547) 4\r\nHG20\r\n
1052 1052 sendall(9 from 9) -> (538) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1053 1053 sendall(9 from 9) -> (529) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1054 1054 sendall(47 from 47) -> (482) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1055 1055 sendall(9 from 9) -> (473) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1056 1056 sendall(473 from 473) -> (0) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1057 1057 write limit reached; closing socket
1058 1058 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1059 1059 Traceback (most recent call last):
1060 1060 Exception: connection closed after sending N bytes
1061 1061
1062 1062
1063 1063 #else
1064 1064 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -16
1065 1065 readline(65537) -> (2) \r\n (py3 !)
1066 1066 write(167 from 167) -> (571) HTTP/1.1 200 Script output follows\r\nServer: badhttpserver\r\nDate: $HTTP_DATE$\r\nContent-Type: application/mercurial-0.2\r\nTransfer-Encoding: chunked\r\n\r\n (py3 !)
1067 1067 write(28 from 28) -> (573) Transfer-Encoding: chunked\r\n (no-py3 !)
1068 1068 write(2 from 2) -> (571) \r\n (no-py3 !)
1069 1069 write(6 from 6) -> (565) 1\\r\\n\x04\\r\\n (esc)
1070 1070 write(9 from 9) -> (556) 4\r\nnone\r\n
1071 1071 write(9 from 9) -> (547) 4\r\nHG20\r\n
1072 1072 write(9 from 9) -> (538) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1073 1073 write(9 from 9) -> (529) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1074 1074 write(47 from 47) -> (482) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1075 1075 write(9 from 9) -> (473) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1076 1076 write(473 from 473) -> (0) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1077 1077 write limit reached; closing socket
1078 1078 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1079 1079 Traceback (most recent call last):
1080 1080 Exception: connection closed after sending N bytes
1081 1081
1082 1082 write(27) -> 15\r\nInternal Server Error\r\n
1083 1083 #endif
1084 1084
1085 1085 $ rm -f error.log
1086 1086
1087 1087 Server stops sending after 0 length payload chunk size
1088 1088
1089 $ hg serve --config badserver.closeaftersendbytes=1580 -p $HGPORT -d --pid-file=hg.pid -E error.log
1089 $ hg serve --config badserver.closeaftersendbytes=1561 -p $HGPORT -d --pid-file=hg.pid -E error.log
1090 1090 $ cat hg.pid > $DAEMON_PIDS
1091 1091
1092 1092 $ hg clone http://localhost:$HGPORT/ clone
1093 1093 requesting all changes
1094 1094 adding changesets
1095 1095 adding manifests
1096 1096 adding file changes
1097 1097 transaction abort!
1098 1098 rollback completed
1099 1099 abort: HTTP request error (incomplete response) (py3 !)
1100 1100 abort: HTTP request error (incomplete response; expected 32 bytes got 9) (no-py3 !)
1101 1101 (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator)
1102 1102 [255]
1103 1103
1104 1104 $ killdaemons.py $DAEMON_PIDS
1105 1105
1106 1106 #if py36
1107 1107 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -16
1108 1108 sendall(6 from 6) -> (596) 1\\r\\n\x04\\r\\n (esc)
1109 1109 sendall(9 from 9) -> (587) 4\r\nnone\r\n
1110 1110 sendall(9 from 9) -> (578) 4\r\nHG20\r\n
1111 1111 sendall(9 from 9) -> (569) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1112 1112 sendall(9 from 9) -> (560) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1113 1113 sendall(47 from 47) -> (513) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1114 1114 sendall(9 from 9) -> (504) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1115 1115 sendall(473 from 473) -> (31) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1116 1116 sendall(9 from 9) -> (22) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1117 1117 sendall(9 from 9) -> (13) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1118 1118 sendall(13 from 38) -> (0) 20\\r\\n\x08LISTKEYS (esc)
1119 1119 write limit reached; closing socket
1120 1120 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1121 1121 Traceback (most recent call last):
1122 1122 Exception: connection closed after sending N bytes
1123 1123
1124 1124
1125 1125 #else
1126 1126 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -17
1127 1127 write(6 from 6) -> (596) 1\\r\\n\x04\\r\\n (esc)
1128 1128 write(9 from 9) -> (587) 4\r\nnone\r\n
1129 1129 write(9 from 9) -> (578) 4\r\nHG20\r\n
1130 1130 write(9 from 9) -> (569) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1131 1131 write(9 from 9) -> (560) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1132 1132 write(47 from 47) -> (513) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1133 1133 write(9 from 9) -> (504) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1134 1134 write(473 from 473) -> (31) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1135 1135 write(9 from 9) -> (22) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1136 1136 write(9 from 9) -> (13) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1137 1137 write(13 from 38) -> (0) 20\\r\\n\x08LISTKEYS (esc)
1138 1138 write limit reached; closing socket
1139 1139 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1140 1140 Traceback (most recent call last):
1141 1141 Exception: connection closed after sending N bytes
1142 1142
1143 1143 write(27) -> 15\r\nInternal Server Error\r\n
1144 1144 #endif
1145 1145
1146 1146 $ rm -f error.log
1147 1147
1148 1148 Server stops sending after 0 part bundle part header (indicating end of bundle2 payload)
1149 1149 This is before the 0 size chunked transfer part that signals end of HTTP response.
1150 1150
1151 # $ hg serve --config badserver.closeaftersendbytes=1755 -p $HGPORT -d --pid-file=hg.pid -E error.log
1152 $ hg serve --config badserver.closeaftersendbytes=1862 -p $HGPORT -d --pid-file=hg.pid -E error.log
1151 $ hg serve --config badserver.closeaftersendbytes=1736 -p $HGPORT -d --pid-file=hg.pid -E error.log
1153 1152 $ cat hg.pid > $DAEMON_PIDS
1154 1153
1155 1154 $ hg clone http://localhost:$HGPORT/ clone
1156 1155 requesting all changes
1157 1156 adding changesets
1158 1157 adding manifests
1159 1158 adding file changes
1160 1159 added 1 changesets with 1 changes to 1 files
1161 1160 new changesets 96ee1d7354c4
1162 1161 updating to branch default
1163 1162 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1164 1163
1165 1164 $ killdaemons.py $DAEMON_PIDS
1166 1165
1167 1166 #if py36
1168 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -25
1169 sendall(9 from 9) -> (851) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1170 sendall(9 from 9) -> (842) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1171 sendall(47 from 47) -> (795) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1172 sendall(9 from 9) -> (786) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1173 sendall(473 from 473) -> (313) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1174 sendall(9 from 9) -> (304) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1175 sendall(9 from 9) -> (295) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1176 sendall(38 from 38) -> (257) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1177 sendall(9 from 9) -> (248) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1178 sendall(64 from 64) -> (184) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1179 sendall(9 from 9) -> (175) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1180 sendall(9 from 9) -> (166) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1181 sendall(41 from 41) -> (125) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1182 sendall(9 from 9) -> (116) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1183 sendall(9 from 9) -> (107) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
1184 sendall(35 from 35) -> (72) 1d\\r\\n\x16cache:rev-branch-cache\x00\x00\x00\x03\x00\x00\\r\\n (esc)
1185 sendall(9 from 9) -> (63) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
1186 sendall(45 from 45) -> (18) 27\\r\\n\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00default\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\\r\\n (esc)
1167 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -20
1168 sendall(9 from 9) -> (744) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1169 sendall(9 from 9) -> (735) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1170 sendall(47 from 47) -> (688) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1171 sendall(9 from 9) -> (679) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1172 sendall(473 from 473) -> (206) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1173 sendall(9 from 9) -> (197) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1174 sendall(9 from 9) -> (188) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1175 sendall(38 from 38) -> (150) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1176 sendall(9 from 9) -> (141) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1177 sendall(64 from 64) -> (77) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1178 sendall(9 from 9) -> (68) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1179 sendall(9 from 9) -> (59) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1180 sendall(41 from 41) -> (18) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1187 1181 sendall(9 from 9) -> (9) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1188 1182 sendall(9 from 9) -> (0) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1189 1183 write limit reached; closing socket
1190 1184 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1191 1185 Traceback (most recent call last):
1192 1186 Exception: connection closed after sending N bytes
1193 1187
1194 1188
1195 1189 #else
1196 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -26
1197 write(9 from 9) -> (851) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1198 write(9 from 9) -> (842) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1199 write(47 from 47) -> (795) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1200 write(9 from 9) -> (786) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1201 write(473 from 473) -> (313) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1202 write(9 from 9) -> (304) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1203 write(9 from 9) -> (295) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1204 write(38 from 38) -> (257) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1205 write(9 from 9) -> (248) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1206 write(64 from 64) -> (184) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1207 write(9 from 9) -> (175) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1208 write(9 from 9) -> (166) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1209 write(41 from 41) -> (125) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1210 write(9 from 9) -> (116) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1211 write(9 from 9) -> (107) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
1212 write(35 from 35) -> (72) 1d\\r\\n\x16cache:rev-branch-cache\x00\x00\x00\x03\x00\x00\\r\\n (esc)
1213 write(9 from 9) -> (63) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
1214 write(45 from 45) -> (18) 27\\r\\n\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00default\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\\r\\n (esc)
1190 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -21
1191 write(9 from 9) -> (744) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1192 write(9 from 9) -> (735) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1193 write(47 from 47) -> (688) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1194 write(9 from 9) -> (679) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1195 write(473 from 473) -> (206) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1196 write(9 from 9) -> (197) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1197 write(9 from 9) -> (188) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1198 write(38 from 38) -> (150) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1199 write(9 from 9) -> (141) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1200 write(64 from 64) -> (77) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1201 write(9 from 9) -> (68) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1202 write(9 from 9) -> (59) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1203 write(41 from 41) -> (18) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1215 1204 write(9 from 9) -> (9) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1216 1205 write(9 from 9) -> (0) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1217 1206 write limit reached; closing socket
1218 1207 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1219 1208 Traceback (most recent call last):
1220 1209 Exception: connection closed after sending N bytes
1221 1210
1222 1211 write(27) -> 15\r\nInternal Server Error\r\n
1223 1212 #endif
1224 1213
1225 1214 $ rm -f error.log
1226 1215 $ rm -rf clone
1227 1216
1228 1217 Server sends a size 0 chunked-transfer size without terminating \r\n
1229 1218
1230 $ hg serve --config badserver.closeaftersendbytes=1865 -p $HGPORT -d --pid-file=hg.pid -E error.log
1219 $ hg serve --config badserver.closeaftersendbytes=1739 -p $HGPORT -d --pid-file=hg.pid -E error.log
1231 1220 $ cat hg.pid > $DAEMON_PIDS
1232 1221
1233 1222 $ hg clone http://localhost:$HGPORT/ clone
1234 1223 requesting all changes
1235 1224 adding changesets
1236 1225 adding manifests
1237 1226 adding file changes
1238 1227 added 1 changesets with 1 changes to 1 files
1239 1228 new changesets 96ee1d7354c4
1240 1229 updating to branch default
1241 1230 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1242 1231
1243 1232 $ killdaemons.py $DAEMON_PIDS
1244 1233
1245 1234 #if py36
1246 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -26
1247 sendall(9 from 9) -> (854) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1248 sendall(9 from 9) -> (845) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1249 sendall(47 from 47) -> (798) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1250 sendall(9 from 9) -> (789) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1251 sendall(473 from 473) -> (316) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1252 sendall(9 from 9) -> (307) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1253 sendall(9 from 9) -> (298) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1254 sendall(38 from 38) -> (260) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1255 sendall(9 from 9) -> (251) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1256 sendall(64 from 64) -> (187) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1257 sendall(9 from 9) -> (178) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1258 sendall(9 from 9) -> (169) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1259 sendall(41 from 41) -> (128) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1260 sendall(9 from 9) -> (119) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1261 sendall(9 from 9) -> (110) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
1262 sendall(35 from 35) -> (75) 1d\\r\\n\x16cache:rev-branch-cache\x00\x00\x00\x03\x00\x00\\r\\n (esc)
1263 sendall(9 from 9) -> (66) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
1264 sendall(45 from 45) -> (21) 27\\r\\n\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00default\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\\r\\n (esc)
1235 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -21
1236 sendall(9 from 9) -> (747) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1237 sendall(9 from 9) -> (738) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1238 sendall(47 from 47) -> (691) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1239 sendall(9 from 9) -> (682) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1240 sendall(473 from 473) -> (209) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1241 sendall(9 from 9) -> (200) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1242 sendall(9 from 9) -> (191) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1243 sendall(38 from 38) -> (153) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1244 sendall(9 from 9) -> (144) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1245 sendall(64 from 64) -> (80) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1246 sendall(9 from 9) -> (71) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1247 sendall(9 from 9) -> (62) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1248 sendall(41 from 41) -> (21) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1265 1249 sendall(9 from 9) -> (12) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1266 1250 sendall(9 from 9) -> (3) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1267 1251 sendall(3 from 5) -> (0) 0\r\n
1268 1252 write limit reached; closing socket
1269 1253 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1270 1254 Traceback (most recent call last):
1271 1255 Exception: connection closed after sending N bytes
1272 1256
1273 1257
1274 1258 #else
1275 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -27
1276 write(9 from 9) -> (854) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1277 write(9 from 9) -> (845) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1278 write(47 from 47) -> (798) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1279 write(9 from 9) -> (789) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1280 write(473 from 473) -> (316) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1281 write(9 from 9) -> (307) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1282 write(9 from 9) -> (298) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1283 write(38 from 38) -> (260) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1284 write(9 from 9) -> (251) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1285 write(64 from 64) -> (187) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1286 write(9 from 9) -> (178) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1287 write(9 from 9) -> (169) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1288 write(41 from 41) -> (128) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1289 write(9 from 9) -> (119) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1290 write(9 from 9) -> (110) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
1291 write(35 from 35) -> (75) 1d\\r\\n\x16cache:rev-branch-cache\x00\x00\x00\x03\x00\x00\\r\\n (esc)
1292 write(9 from 9) -> (66) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
1293 write(45 from 45) -> (21) 27\\r\\n\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x00default\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\\r\\n (esc)
1259 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -22
1260 write(9 from 9) -> (747) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1261 write(9 from 9) -> (738) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1262 write(47 from 47) -> (691) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1263 write(9 from 9) -> (682) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1264 write(473 from 473) -> (209) 1d2\\r\\n\x00\x00\x00\xb2\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>6a3df4de388f3c4f8e28f4f9a814299a3cbb5f50\\ntest\\n0 0\\nfoo\\n\\ninitial\x00\x00\x00\x00\x00\x00\x00\xa1j=\xf4\xde8\x8f<O\x8e(\xf4\xf9\xa8\x14)\x9a<\xbb_P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00b80de5d138758541c5f05265ad144ab9fa86d1db\\n\x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00h\xb8\\r\xe5\xd18u\x85A\xc5\xf0Re\xad\x14J\xb9\xfa\x86\xd1\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL\x00\x00\x00\x00\x00\x00\x00\x00\\r\\n (esc)
1265 write(9 from 9) -> (200) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1266 write(9 from 9) -> (191) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1267 write(38 from 38) -> (153) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1268 write(9 from 9) -> (144) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1269 write(64 from 64) -> (80) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1270 write(9 from 9) -> (71) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1271 write(9 from 9) -> (62) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1272 write(41 from 41) -> (21) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1294 1273 write(9 from 9) -> (12) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1295 1274 write(9 from 9) -> (3) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1296 1275 write(3 from 5) -> (0) 0\r\n
1297 1276 write limit reached; closing socket
1298 1277 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1299 1278 Traceback (most recent call last):
1300 1279 Exception: connection closed after sending N bytes
1301 1280
1302 1281 write(27) -> 15\r\nInternal Server Error\r\n
1303 1282 #endif
1304 1283
1305 1284 $ rm -f error.log
1306 1285 $ rm -rf clone
@@ -1,773 +1,773 b''
1 1 #require no-chg
2 2
3 3 $ . $TESTDIR/wireprotohelpers.sh
4 4
5 5 $ cat >> $HGRCPATH << EOF
6 6 > [web]
7 7 > push_ssl = false
8 8 > allow_push = *
9 9 > EOF
10 10
11 11 $ hg init server
12 12 $ cd server
13 13 $ touch a
14 14 $ hg -q commit -A -m initial
15 15 $ cd ..
16 16
17 17 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
18 18 $ cat hg.pid >> $DAEMON_PIDS
19 19
20 20 compression formats are advertised in compression capability
21 21
22 22 #if zstd
23 23 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zstd,zlib$' > /dev/null
24 24 #else
25 25 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zlib$' > /dev/null
26 26 #endif
27 27
28 28 $ killdaemons.py
29 29
30 30 server.compressionengines can replace engines list wholesale
31 31
32 32 $ hg serve --config server.compressionengines=none -R server -p $HGPORT -d --pid-file hg.pid
33 33 $ cat hg.pid > $DAEMON_PIDS
34 34 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none$' > /dev/null
35 35
36 36 $ killdaemons.py
37 37
38 38 Order of engines can also change
39 39
40 40 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
41 41 $ cat hg.pid > $DAEMON_PIDS
42 42 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none,zlib$' > /dev/null
43 43
44 44 $ killdaemons.py
45 45
46 46 Start a default server again
47 47
48 48 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
49 49 $ cat hg.pid > $DAEMON_PIDS
50 50
51 51 Server should send application/mercurial-0.1 to clients if no Accept is used
52 52
53 53 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
54 54 200 Script output follows
55 55 content-type: application/mercurial-0.1
56 56 date: $HTTP_DATE$
57 57 server: testing stub value
58 58 transfer-encoding: chunked
59 59
60 60 Server should send application/mercurial-0.1 when client says it wants it
61 61
62 62 $ get-with-headers.py --hgproto '0.1' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
63 63 200 Script output follows
64 64 content-type: application/mercurial-0.1
65 65 date: $HTTP_DATE$
66 66 server: testing stub value
67 67 transfer-encoding: chunked
68 68
69 69 Server should send application/mercurial-0.2 when client says it wants it
70 70
71 71 $ get-with-headers.py --hgproto '0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
72 72 200 Script output follows
73 73 content-type: application/mercurial-0.2
74 74 date: $HTTP_DATE$
75 75 server: testing stub value
76 76 transfer-encoding: chunked
77 77
78 78 $ get-with-headers.py --hgproto '0.1 0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
79 79 200 Script output follows
80 80 content-type: application/mercurial-0.2
81 81 date: $HTTP_DATE$
82 82 server: testing stub value
83 83 transfer-encoding: chunked
84 84
85 85 Requesting a compression format that server doesn't support results will fall back to 0.1
86 86
87 87 $ get-with-headers.py --hgproto '0.2 comp=aa' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
88 88 200 Script output follows
89 89 content-type: application/mercurial-0.1
90 90 date: $HTTP_DATE$
91 91 server: testing stub value
92 92 transfer-encoding: chunked
93 93
94 94 #if zstd
95 95 zstd is used if available
96 96
97 97 $ get-with-headers.py --hgproto '0.2 comp=zstd' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
98 98 $ f --size --hexdump --bytes 36 --sha1 resp
99 99 resp: size=248, sha1=f11b5c098c638068b3d5fe2f9e6241bf5228
100 100 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
101 101 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 73 74 64 |t follows...zstd|
102 102 0020: 28 b5 2f fd |(./.|
103 103
104 104 #endif
105 105
106 106 application/mercurial-0.2 is not yet used on non-streaming responses
107 107
108 108 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=heads' -
109 109 200 Script output follows
110 110 content-length: 41
111 111 content-type: application/mercurial-0.1
112 112 date: $HTTP_DATE$
113 113 server: testing stub value
114 114
115 115 e93700bd72895c5addab234c56d4024b487a362f
116 116
117 117 Now test protocol preference usage
118 118
119 119 $ killdaemons.py
120 120 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
121 121 $ cat hg.pid > $DAEMON_PIDS
122 122
123 123 No Accept will send 0.1+zlib, even though "none" is preferred b/c "none" isn't supported on 0.1
124 124
125 125 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' Content-Type
126 126 200 Script output follows
127 127 content-type: application/mercurial-0.1
128 128
129 129 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
130 130 $ f --size --hexdump --bytes 28 --sha1 resp
131 131 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
132 132 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
133 133 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
134 134
135 135 Explicit 0.1 will send zlib because "none" isn't supported on 0.1
136 136
137 137 $ get-with-headers.py --hgproto '0.1' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
138 138 $ f --size --hexdump --bytes 28 --sha1 resp
139 139 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
140 140 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
141 141 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
142 142
143 143 0.2 with no compression will get "none" because that is server's preference
144 144 (spec says ZL and UN are implicitly supported)
145 145
146 146 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
147 147 $ f --size --hexdump --bytes 32 --sha1 resp
148 148 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
149 149 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
150 150 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
151 151
152 152 Client receives server preference even if local order doesn't match
153 153
154 154 $ get-with-headers.py --hgproto '0.2 comp=zlib,none' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
155 155 $ f --size --hexdump --bytes 32 --sha1 resp
156 156 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
157 157 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
158 158 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
159 159
160 160 Client receives only supported format even if not server preferred format
161 161
162 162 $ get-with-headers.py --hgproto '0.2 comp=zlib' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
163 163 $ f --size --hexdump --bytes 33 --sha1 resp
164 164 resp: size=232, sha1=a1c727f0c9693ca15742a75c30419bc36
165 165 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
166 166 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 6c 69 62 |t follows...zlib|
167 167 0020: 78 |x|
168 168
169 169 $ killdaemons.py
170 170 $ cd ..
171 171
172 172 Test listkeys for listing namespaces
173 173
174 174 $ hg init empty
175 175 $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
176 176 $ cat hg.pid > $DAEMON_PIDS
177 177
178 178 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
179 179 > command listkeys
180 180 > namespace namespaces
181 181 > EOF
182 182 s> setsockopt(6, 1, 1) -> None (?)
183 183 s> GET /?cmd=capabilities HTTP/1.1\r\n
184 184 s> Accept-Encoding: identity\r\n
185 185 s> accept: application/mercurial-0.1\r\n
186 186 s> host: $LOCALIP:$HGPORT\r\n (glob)
187 187 s> user-agent: Mercurial debugwireproto\r\n
188 188 s> \r\n
189 189 s> makefile('rb', None)
190 190 s> HTTP/1.1 200 Script output follows\r\n
191 191 s> Server: testing stub value\r\n
192 192 s> Date: $HTTP_DATE$\r\n
193 193 s> Content-Type: application/mercurial-0.1\r\n
194 194 s> Content-Length: *\r\n (glob)
195 195 s> \r\n
196 196 s> batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
197 197 sending listkeys command
198 198 s> setsockopt(6, 1, 1) -> None (?)
199 199 s> GET /?cmd=listkeys HTTP/1.1\r\n
200 200 s> Accept-Encoding: identity\r\n
201 201 s> vary: X-HgArg-1,X-HgProto-1\r\n
202 202 s> x-hgarg-1: namespace=namespaces\r\n
203 203 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
204 204 s> accept: application/mercurial-0.1\r\n
205 205 s> host: $LOCALIP:$HGPORT\r\n (glob)
206 206 s> user-agent: Mercurial debugwireproto\r\n
207 207 s> \r\n
208 208 s> makefile('rb', None)
209 209 s> HTTP/1.1 200 Script output follows\r\n
210 210 s> Server: testing stub value\r\n
211 211 s> Date: $HTTP_DATE$\r\n
212 212 s> Content-Type: application/mercurial-0.1\r\n
213 213 s> Content-Length: 30\r\n
214 214 s> \r\n
215 215 s> bookmarks\t\n
216 216 s> namespaces\t\n
217 217 s> phases\t
218 218 response: {
219 219 b'bookmarks': b'',
220 220 b'namespaces': b'',
221 221 b'phases': b''
222 222 }
223 223 (sent 2 HTTP requests and * bytes; received * bytes in responses) (glob)
224 224
225 225 Same thing, but with "httprequest" command
226 226
227 227 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
228 228 > httprequest GET ?cmd=listkeys
229 229 > user-agent: test
230 230 > x-hgarg-1: namespace=namespaces
231 231 > EOF
232 232 using raw connection to peer
233 233 s> setsockopt(6, 1, 1) -> None (?)
234 234 s> GET /?cmd=listkeys HTTP/1.1\r\n
235 235 s> Accept-Encoding: identity\r\n
236 236 s> user-agent: test\r\n
237 237 s> x-hgarg-1: namespace=namespaces\r\n
238 238 s> host: $LOCALIP:$HGPORT\r\n (glob)
239 239 s> \r\n
240 240 s> makefile('rb', None)
241 241 s> HTTP/1.1 200 Script output follows\r\n
242 242 s> Server: testing stub value\r\n
243 243 s> Date: $HTTP_DATE$\r\n
244 244 s> Content-Type: application/mercurial-0.1\r\n
245 245 s> Content-Length: 30\r\n
246 246 s> \r\n
247 247 s> bookmarks\t\n
248 248 s> namespaces\t\n
249 249 s> phases\t
250 250
251 251 Client with HTTPv2 enabled advertises that and gets old capabilities response from old server
252 252
253 253 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
254 254 > command heads
255 255 > EOF
256 256 s> setsockopt(6, 1, 1) -> None (?)
257 257 s> GET /?cmd=capabilities HTTP/1.1\r\n
258 258 s> Accept-Encoding: identity\r\n
259 259 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
260 260 s> x-hgproto-1: cbor\r\n
261 261 s> x-hgupgrade-1: exp-http-v2-0003\r\n
262 262 s> accept: application/mercurial-0.1\r\n
263 263 s> host: $LOCALIP:$HGPORT\r\n (glob)
264 264 s> user-agent: Mercurial debugwireproto\r\n
265 265 s> \r\n
266 266 s> makefile('rb', None)
267 267 s> HTTP/1.1 200 Script output follows\r\n
268 268 s> Server: testing stub value\r\n
269 269 s> Date: $HTTP_DATE$\r\n
270 270 s> Content-Type: application/mercurial-0.1\r\n
271 271 s> Content-Length: *\r\n (glob)
272 272 s> \r\n
273 273 s> batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
274 274 sending heads command
275 275 s> setsockopt(6, 1, 1) -> None (?)
276 276 s> GET /?cmd=heads HTTP/1.1\r\n
277 277 s> Accept-Encoding: identity\r\n
278 278 s> vary: X-HgProto-1\r\n
279 279 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
280 280 s> accept: application/mercurial-0.1\r\n
281 281 s> host: $LOCALIP:$HGPORT\r\n (glob)
282 282 s> user-agent: Mercurial debugwireproto\r\n
283 283 s> \r\n
284 284 s> makefile('rb', None)
285 285 s> HTTP/1.1 200 Script output follows\r\n
286 286 s> Server: testing stub value\r\n
287 287 s> Date: $HTTP_DATE$\r\n
288 288 s> Content-Type: application/mercurial-0.1\r\n
289 289 s> Content-Length: 41\r\n
290 290 s> \r\n
291 291 s> 0000000000000000000000000000000000000000\n
292 292 response: [
293 293 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
294 294 ]
295 295 (sent 2 HTTP requests and * bytes; received * bytes in responses) (glob)
296 296
297 297 $ killdaemons.py
298 298 $ enablehttpv2 empty
299 299 $ hg --config server.compressionengines=zlib -R empty serve -p $HGPORT -d --pid-file hg.pid
300 300 $ cat hg.pid > $DAEMON_PIDS
301 301
302 302 Client with HTTPv2 enabled automatically upgrades if the server supports it
303 303
304 304 $ hg --config experimental.httppeer.advertise-v2=true --config experimental.httppeer.v2-encoder-order=identity --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
305 305 > command heads
306 306 > EOF
307 307 s> setsockopt(6, 1, 1) -> None (?)
308 308 s> GET /?cmd=capabilities HTTP/1.1\r\n
309 309 s> Accept-Encoding: identity\r\n
310 310 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
311 311 s> x-hgproto-1: cbor\r\n
312 312 s> x-hgupgrade-1: exp-http-v2-0003\r\n
313 313 s> accept: application/mercurial-0.1\r\n
314 314 s> host: $LOCALIP:$HGPORT\r\n (glob)
315 315 s> user-agent: Mercurial debugwireproto\r\n
316 316 s> \r\n
317 317 s> makefile('rb', None)
318 318 s> HTTP/1.1 200 OK\r\n
319 319 s> Server: testing stub value\r\n
320 320 s> Date: $HTTP_DATE$\r\n
321 321 s> Content-Type: application/mercurial-cbor\r\n
322 322 s> Content-Length: *\r\n (glob)
323 323 s> \r\n
324 s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0003\xa4Hcommands\xacIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa2Ffields\xa4Gdefault\xd9\x01\x02\x80Hrequired\xf4DtypeCsetKvalidvalues\xd9\x01\x02\x84IbookmarksGparentsEphaseHrevisionIrevisions\xa2Hrequired\xf5DtypeDlistKpermissions\x81DpullHfiledata\xa2Dargs\xa4Ffields\xa4Gdefault\xd9\x01\x02\x80Hrequired\xf4DtypeCsetKvalidvalues\xd9\x01\x02\x83HlinknodeGparentsHrevisionKhaveparents\xa3Gdefault\xf4Hrequired\xf4DtypeDboolEnodes\xa2Hrequired\xf5DtypeDlistDpath\xa2Hrequired\xf5DtypeEbytesKpermissions\x81DpullIfilesdata\xa3Dargs\xa4Ffields\xa4Gdefault\xd9\x01\x02\x80Hrequired\xf4DtypeCsetKvalidvalues\xd9\x01\x02\x84NfirstchangesetHlinknodeGparentsHrevisionKhaveparents\xa3Gdefault\xf4Hrequired\xf4DtypeDboolJpathfilter\xa3Gdefault\xf6Hrequired\xf4DtypeDdictIrevisions\xa2Hrequired\xf5DtypeDlistKpermissions\x81DpullTrecommendedbatchsize\x19\xc3PEheads\xa2Dargs\xa1Jpubliconly\xa3Gdefault\xf4Hrequired\xf4DtypeDboolKpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\xa3Gdefault\x80Hrequired\xf4DtypeDlistKpermissions\x81DpullHlistkeys\xa2Dargs\xa1Inamespace\xa2Hrequired\xf5DtypeEbytesKpermissions\x81DpullFlookup\xa2Dargs\xa1Ckey\xa2Hrequired\xf5DtypeEbytesKpermissions\x81DpullLmanifestdata\xa3Dargs\xa4Ffields\xa4Gdefault\xd9\x01\x02\x80Hrequired\xf4DtypeCsetKvalidvalues\xd9\x01\x02\x82GparentsHrevisionKhaveparents\xa3Gdefault\xf4Hrequired\xf4DtypeDboolEnodes\xa2Hrequired\xf5DtypeDlistDtree\xa2Hrequired\xf5DtypeEbytesKpermissions\x81DpullTrecommendedbatchsize\x1a\x00\x01\x86\xa0Gpushkey\xa2Dargs\xa4Ckey\xa2Hrequired\xf5DtypeEbytesInamespace\xa2Hrequired\xf5DtypeEbytesCnew\xa2Hrequired\xf5DtypeEbytesCold\xa2Hrequired\xf5DtypeEbytesKpermissions\x81DpushPrawstorefiledata\xa2Dargs\xa2Efiles\xa2Hrequired\xf5DtypeDlistJpathfilter\xa3Gdefault\xf6Hrequired\xf4DtypeDlistKpermissions\x81DpullQframingmediatypes\x81X&application/mercurial-exp-framing-0006Rpathfilterprefixes\xd9\x01\x02\x82Epath:Lrootfilesin:Nrawrepoformats\x83LgeneraldeltaHrevlogv1LsparserevlogNv1capabilitiesY\x01\xf7batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
324 s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0003\xa4Hcommands\xacIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa2Ffields\xa4Gdefault\xd9\x01\x02\x80Hrequired\xf4DtypeCsetKvalidvalues\xd9\x01\x02\x84IbookmarksGparentsEphaseHrevisionIrevisions\xa2Hrequired\xf5DtypeDlistKpermissions\x81DpullHfiledata\xa2Dargs\xa4Ffields\xa4Gdefault\xd9\x01\x02\x80Hrequired\xf4DtypeCsetKvalidvalues\xd9\x01\x02\x83HlinknodeGparentsHrevisionKhaveparents\xa3Gdefault\xf4Hrequired\xf4DtypeDboolEnodes\xa2Hrequired\xf5DtypeDlistDpath\xa2Hrequired\xf5DtypeEbytesKpermissions\x81DpullIfilesdata\xa3Dargs\xa4Ffields\xa4Gdefault\xd9\x01\x02\x80Hrequired\xf4DtypeCsetKvalidvalues\xd9\x01\x02\x84NfirstchangesetHlinknodeGparentsHrevisionKhaveparents\xa3Gdefault\xf4Hrequired\xf4DtypeDboolJpathfilter\xa3Gdefault\xf6Hrequired\xf4DtypeDdictIrevisions\xa2Hrequired\xf5DtypeDlistKpermissions\x81DpullTrecommendedbatchsize\x19\xc3PEheads\xa2Dargs\xa1Jpubliconly\xa3Gdefault\xf4Hrequired\xf4DtypeDboolKpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\xa3Gdefault\x80Hrequired\xf4DtypeDlistKpermissions\x81DpullHlistkeys\xa2Dargs\xa1Inamespace\xa2Hrequired\xf5DtypeEbytesKpermissions\x81DpullFlookup\xa2Dargs\xa1Ckey\xa2Hrequired\xf5DtypeEbytesKpermissions\x81DpullLmanifestdata\xa3Dargs\xa4Ffields\xa4Gdefault\xd9\x01\x02\x80Hrequired\xf4DtypeCsetKvalidvalues\xd9\x01\x02\x82GparentsHrevisionKhaveparents\xa3Gdefault\xf4Hrequired\xf4DtypeDboolEnodes\xa2Hrequired\xf5DtypeDlistDtree\xa2Hrequired\xf5DtypeEbytesKpermissions\x81DpullTrecommendedbatchsize\x1a\x00\x01\x86\xa0Gpushkey\xa2Dargs\xa4Ckey\xa2Hrequired\xf5DtypeEbytesInamespace\xa2Hrequired\xf5DtypeEbytesCnew\xa2Hrequired\xf5DtypeEbytesCold\xa2Hrequired\xf5DtypeEbytesKpermissions\x81DpushPrawstorefiledata\xa2Dargs\xa2Efiles\xa2Hrequired\xf5DtypeDlistJpathfilter\xa3Gdefault\xf6Hrequired\xf4DtypeDlistKpermissions\x81DpullQframingmediatypes\x81X&application/mercurial-exp-framing-0006Rpathfilterprefixes\xd9\x01\x02\x82Epath:Lrootfilesin:Nrawrepoformats\x83LgeneraldeltaHrevlogv1LsparserevlogNv1capabilitiesY\x01\xe4batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
325 325 sending heads command
326 326 s> setsockopt(6, 1, 1) -> None (?)
327 327 s> POST /api/exp-http-v2-0003/ro/heads HTTP/1.1\r\n
328 328 s> Accept-Encoding: identity\r\n
329 329 s> accept: application/mercurial-exp-framing-0006\r\n
330 330 s> content-type: application/mercurial-exp-framing-0006\r\n
331 331 s> content-length: 56\r\n
332 332 s> host: $LOCALIP:$HGPORT\r\n (glob)
333 333 s> user-agent: Mercurial debugwireproto\r\n
334 334 s> \r\n
335 335 s> \x1c\x00\x00\x01\x00\x01\x01\x82\xa1Pcontentencodings\x81Hidentity\x0c\x00\x00\x01\x00\x01\x00\x11\xa1DnameEheads
336 336 s> makefile('rb', None)
337 337 s> HTTP/1.1 200 OK\r\n
338 338 s> Server: testing stub value\r\n
339 339 s> Date: $HTTP_DATE$\r\n
340 340 s> Content-Type: application/mercurial-exp-framing-0006\r\n
341 341 s> Transfer-Encoding: chunked\r\n
342 342 s> \r\n
343 343 s> 11\r\n
344 344 s> \t\x00\x00\x01\x00\x02\x01\x92
345 345 s> Hidentity
346 346 s> \r\n
347 347 s> 13\r\n
348 348 s> \x0b\x00\x00\x01\x00\x02\x041
349 349 s> \xa1FstatusBok
350 350 s> \r\n
351 351 s> 1e\r\n
352 352 s> \x16\x00\x00\x01\x00\x02\x041
353 353 s> \x81T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
354 354 s> \r\n
355 355 s> 8\r\n
356 356 s> \x00\x00\x00\x01\x00\x02\x002
357 357 s> \r\n
358 358 s> 0\r\n
359 359 s> \r\n
360 360 response: [
361 361 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
362 362 ]
363 363 (sent 2 HTTP requests and * bytes; received * bytes in responses) (glob)
364 364
365 365 $ killdaemons.py
366 366
367 367 HTTP client follows HTTP redirect on handshake to new repo
368 368
369 369 $ cd $TESTTMP
370 370
371 371 $ hg init redirector
372 372 $ hg init redirected
373 373 $ cd redirected
374 374 $ touch foo
375 375 $ hg -q commit -A -m initial
376 376 $ cd ..
377 377
378 378 $ cat > paths.conf << EOF
379 379 > [paths]
380 380 > / = $TESTTMP/*
381 381 > EOF
382 382
383 383 $ cat > redirectext.py << EOF
384 384 > from mercurial import extensions, wireprotoserver
385 385 > def wrappedcallhttp(orig, repo, req, res, proto, cmd):
386 386 > path = req.advertisedurl[len(req.advertisedbaseurl):]
387 387 > if not path.startswith(b'/redirector'):
388 388 > return orig(repo, req, res, proto, cmd)
389 389 > relpath = path[len(b'/redirector'):]
390 390 > res.status = b'301 Redirect'
391 391 > newurl = b'%s/redirected%s' % (req.baseurl, relpath)
392 392 > if not repo.ui.configbool(b'testing', b'redirectqs', True) and b'?' in newurl:
393 393 > newurl = newurl[0:newurl.index(b'?')]
394 394 > res.headers[b'Location'] = newurl
395 395 > res.headers[b'Content-Type'] = b'text/plain'
396 396 > res.setbodybytes(b'redirected')
397 397 > return True
398 398 >
399 399 > extensions.wrapfunction(wireprotoserver, '_callhttp', wrappedcallhttp)
400 400 > EOF
401 401
402 402 $ hg --config extensions.redirect=$TESTTMP/redirectext.py \
403 403 > --config server.compressionengines=zlib \
404 404 > serve --web-conf paths.conf --pid-file hg.pid -p $HGPORT -d
405 405 $ cat hg.pid > $DAEMON_PIDS
406 406
407 407 Verify our HTTP 301 is served properly
408 408
409 409 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
410 410 > httprequest GET /redirector?cmd=capabilities
411 411 > user-agent: test
412 412 > EOF
413 413 using raw connection to peer
414 414 s> setsockopt(6, 1, 1) -> None (?)
415 415 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
416 416 s> Accept-Encoding: identity\r\n
417 417 s> user-agent: test\r\n
418 418 s> host: $LOCALIP:$HGPORT\r\n (glob)
419 419 s> \r\n
420 420 s> makefile('rb', None)
421 421 s> HTTP/1.1 301 Redirect\r\n
422 422 s> Server: testing stub value\r\n
423 423 s> Date: $HTTP_DATE$\r\n
424 424 s> Location: http://$LOCALIP:$HGPORT/redirected?cmd=capabilities\r\n (glob)
425 425 s> Content-Type: text/plain\r\n
426 426 s> Content-Length: 10\r\n
427 427 s> \r\n
428 428 s> redirected
429 429 s> setsockopt(6, 1, 1) -> None (?)
430 430 s> GET /redirected?cmd=capabilities HTTP/1.1\r\n
431 431 s> Accept-Encoding: identity\r\n
432 432 s> user-agent: test\r\n
433 433 s> host: $LOCALIP:$HGPORT\r\n (glob)
434 434 s> \r\n
435 435 s> makefile('rb', None)
436 436 s> HTTP/1.1 200 Script output follows\r\n
437 437 s> Server: testing stub value\r\n
438 438 s> Date: $HTTP_DATE$\r\n
439 439 s> Content-Type: application/mercurial-0.1\r\n
440 s> Content-Length: 503\r\n
440 s> Content-Length: 484\r\n
441 441 s> \r\n
442 442 s> batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
443 443
444 444 Test with the HTTP peer
445 445
446 446 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT/redirector << EOF
447 447 > command heads
448 448 > EOF
449 449 s> setsockopt(6, 1, 1) -> None (?)
450 450 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
451 451 s> Accept-Encoding: identity\r\n
452 452 s> accept: application/mercurial-0.1\r\n
453 453 s> host: $LOCALIP:$HGPORT\r\n (glob)
454 454 s> user-agent: Mercurial debugwireproto\r\n
455 455 s> \r\n
456 456 s> makefile('rb', None)
457 457 s> HTTP/1.1 301 Redirect\r\n
458 458 s> Server: testing stub value\r\n
459 459 s> Date: $HTTP_DATE$\r\n
460 460 s> Location: http://$LOCALIP:$HGPORT/redirected?cmd=capabilities\r\n (glob)
461 461 s> Content-Type: text/plain\r\n
462 462 s> Content-Length: 10\r\n
463 463 s> \r\n
464 464 s> redirected
465 465 s> setsockopt(6, 1, 1) -> None (?)
466 466 s> GET /redirected?cmd=capabilities HTTP/1.1\r\n
467 467 s> Accept-Encoding: identity\r\n
468 468 s> accept: application/mercurial-0.1\r\n
469 469 s> host: $LOCALIP:$HGPORT\r\n (glob)
470 470 s> user-agent: Mercurial debugwireproto\r\n
471 471 s> \r\n
472 472 s> makefile('rb', None)
473 473 s> HTTP/1.1 200 Script output follows\r\n
474 474 s> Server: testing stub value\r\n
475 475 s> Date: $HTTP_DATE$\r\n
476 476 s> Content-Type: application/mercurial-0.1\r\n
477 s> Content-Length: 503\r\n
477 s> Content-Length: 484\r\n
478 478 s> \r\n
479 479 real URL is http://$LOCALIP:$HGPORT/redirected (glob)
480 480 s> batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
481 481 sending heads command
482 482 s> setsockopt(6, 1, 1) -> None (?)
483 483 s> GET /redirected?cmd=heads HTTP/1.1\r\n
484 484 s> Accept-Encoding: identity\r\n
485 485 s> vary: X-HgProto-1\r\n
486 486 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
487 487 s> accept: application/mercurial-0.1\r\n
488 488 s> host: $LOCALIP:$HGPORT\r\n (glob)
489 489 s> user-agent: Mercurial debugwireproto\r\n
490 490 s> \r\n
491 491 s> makefile('rb', None)
492 492 s> HTTP/1.1 200 Script output follows\r\n
493 493 s> Server: testing stub value\r\n
494 494 s> Date: $HTTP_DATE$\r\n
495 495 s> Content-Type: application/mercurial-0.1\r\n
496 496 s> Content-Length: 41\r\n
497 497 s> \r\n
498 498 s> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n
499 499 response: [
500 500 b'\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL'
501 501 ]
502 502 (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob)
503 503
504 504 $ killdaemons.py
505 505
506 506 Now test a variation where we strip the query string from the redirect URL.
507 507 (SCM Manager apparently did this and clients would recover from it)
508 508
509 509 $ hg --config extensions.redirect=$TESTTMP/redirectext.py \
510 510 > --config server.compressionengines=zlib \
511 511 > --config testing.redirectqs=false \
512 512 > serve --web-conf paths.conf --pid-file hg.pid -p $HGPORT -d
513 513 $ cat hg.pid > $DAEMON_PIDS
514 514
515 515 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
516 516 > httprequest GET /redirector?cmd=capabilities
517 517 > user-agent: test
518 518 > EOF
519 519 using raw connection to peer
520 520 s> setsockopt(6, 1, 1) -> None (?)
521 521 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
522 522 s> Accept-Encoding: identity\r\n
523 523 s> user-agent: test\r\n
524 524 s> host: $LOCALIP:$HGPORT\r\n (glob)
525 525 s> \r\n
526 526 s> makefile('rb', None)
527 527 s> HTTP/1.1 301 Redirect\r\n
528 528 s> Server: testing stub value\r\n
529 529 s> Date: $HTTP_DATE$\r\n
530 530 s> Location: http://$LOCALIP:$HGPORT/redirected\r\n (glob)
531 531 s> Content-Type: text/plain\r\n
532 532 s> Content-Length: 10\r\n
533 533 s> \r\n
534 534 s> redirected
535 535 s> setsockopt(6, 1, 1) -> None (?)
536 536 s> GET /redirected HTTP/1.1\r\n
537 537 s> Accept-Encoding: identity\r\n
538 538 s> user-agent: test\r\n
539 539 s> host: $LOCALIP:$HGPORT\r\n (glob)
540 540 s> \r\n
541 541 s> makefile('rb', None)
542 542 s> HTTP/1.1 200 Script output follows\r\n
543 543 s> Server: testing stub value\r\n
544 544 s> Date: $HTTP_DATE$\r\n
545 545 s> ETag: W/"*"\r\n (glob)
546 546 s> Content-Type: text/html; charset=ascii\r\n
547 547 s> Transfer-Encoding: chunked\r\n
548 548 s> \r\n
549 549 s> 414\r\n
550 550 s> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n
551 551 s> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">\n
552 552 s> <head>\n
553 553 s> <link rel="icon" href="/redirected/static/hgicon.png" type="image/png" />\n
554 554 s> <meta name="robots" content="index, nofollow" />\n
555 555 s> <link rel="stylesheet" href="/redirected/static/style-paper.css" type="text/css" />\n
556 556 s> <script type="text/javascript" src="/redirected/static/mercurial.js"></script>\n
557 557 s> \n
558 558 s> <title>redirected: log</title>\n
559 559 s> <link rel="alternate" type="application/atom+xml"\n
560 560 s> href="/redirected/atom-log" title="Atom feed for redirected" />\n
561 561 s> <link rel="alternate" type="application/rss+xml"\n
562 562 s> href="/redirected/rss-log" title="RSS feed for redirected" />\n
563 563 s> </head>\n
564 564 s> <body>\n
565 565 s> \n
566 566 s> <div class="container">\n
567 567 s> <div class="menu">\n
568 568 s> <div class="logo">\n
569 569 s> <a href="https://mercurial-scm.org/">\n
570 570 s> <img src="/redirected/static/hglogo.png" alt="mercurial" /></a>\n
571 571 s> </div>\n
572 572 s> <ul>\n
573 573 s> <li class="active">log</li>\n
574 574 s> <li><a href="/redirected/graph/tip">graph</a></li>\n
575 575 s> <li><a href="/redirected/tags">tags</a></li>\n
576 576 s> <li><a href="
577 577 s> \r\n
578 578 s> 810\r\n
579 579 s> /redirected/bookmarks">bookmarks</a></li>\n
580 580 s> <li><a href="/redirected/branches">branches</a></li>\n
581 581 s> </ul>\n
582 582 s> <ul>\n
583 583 s> <li><a href="/redirected/rev/tip">changeset</a></li>\n
584 584 s> <li><a href="/redirected/file/tip">browse</a></li>\n
585 585 s> </ul>\n
586 586 s> <ul>\n
587 587 s> \n
588 588 s> </ul>\n
589 589 s> <ul>\n
590 590 s> <li><a href="/redirected/help">help</a></li>\n
591 591 s> </ul>\n
592 592 s> <div class="atom-logo">\n
593 593 s> <a href="/redirected/atom-log" title="subscribe to atom feed">\n
594 594 s> <img class="atom-logo" src="/redirected/static/feed-icon-14x14.png" alt="atom feed" />\n
595 595 s> </a>\n
596 596 s> </div>\n
597 597 s> </div>\n
598 598 s> \n
599 599 s> <div class="main">\n
600 600 s> <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/redirected">redirected</a> </h2>\n
601 601 s> <h3>log</h3>\n
602 602 s> \n
603 603 s> \n
604 604 s> <form class="search" action="/redirected/log">\n
605 605 s> \n
606 606 s> <p><input name="rev" id="search1" type="text" size="30" value="" /></p>\n
607 607 s> <div id="hint">Find changesets by keywords (author, files, the commit message), revision\n
608 608 s> number or hash, or <a href="/redirected/help/revsets">revset expression</a>.</div>\n
609 609 s> </form>\n
610 610 s> \n
611 611 s> <div class="navigate">\n
612 612 s> <a href="/redirected/shortlog/tip?revcount=30">less</a>\n
613 613 s> <a href="/redirected/shortlog/tip?revcount=120">more</a>\n
614 614 s> | rev 0: <a href="/redirected/shortlog/96ee1d7354c4">(0)</a> <a href="/redirected/shortlog/tip">tip</a> \n
615 615 s> </div>\n
616 616 s> \n
617 617 s> <table class="bigtable">\n
618 618 s> <thead>\n
619 619 s> <tr>\n
620 620 s> <th class="age">age</th>\n
621 621 s> <th class="author">author</th>\n
622 622 s> <th class="description">description</th>\n
623 623 s> </tr>\n
624 624 s> </thead>\n
625 625 s> <tbody class="stripes2">\n
626 626 s> <tr>\n
627 627 s> <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>\n
628 628 s> <td class="author">test</td>\n
629 629 s> <td class="description">\n
630 630 s> <a href="/redirected/rev/96ee1d7354c4">initial</a>\n
631 631 s> <span class="phase">draft</span> <span class="branchhead">default</span> <span class="tag">tip</span> \n
632 632 s> </td>\n
633 633 s> </tr>\n
634 634 s> \n
635 635 s> </tbody>\n
636 636 s> </table>\n
637 637 s> \n
638 638 s> <div class="navigate">\n
639 639 s> <a href="/redirected/shortlog/tip?revcount=30">less</a>\n
640 640 s> <a href="/redirected/shortlog/tip?revcount=120">more</a>\n
641 641 s> | rev 0: <a href="/redirected/shortlog/96ee1d7354c4">(0)</a> <a href="/redirected/shortlog/tip">tip</a> \n
642 642 s> </div>\n
643 643 s> \n
644 644 s> <script type="text/javascript">\n
645 645 s> ajaxScrollInit(\n
646 646 s> \'/redirected/shortlog/%next%\',\n
647 647 s> \'\', <!-- NEXTHASH\n
648 648 s> function (htmlText) {
649 649 s> \r\n
650 650 s> 14a\r\n
651 651 s> \n
652 652 s> var m = htmlText.match(/\'(\\w+)\', <!-- NEXTHASH/);\n
653 653 s> return m ? m[1] : null;\n
654 654 s> },\n
655 655 s> \'.bigtable > tbody\',\n
656 656 s> \'<tr class="%class%">\\\n
657 657 s> <td colspan="3" style="text-align: center;">%text%</td>\\\n
658 658 s> </tr>\'\n
659 659 s> );\n
660 660 s> </script>\n
661 661 s> \n
662 662 s> </div>\n
663 663 s> </div>\n
664 664 s> \n
665 665 s> \n
666 666 s> \n
667 667 s> </body>\n
668 668 s> </html>\n
669 669 s> \n
670 670 s> \r\n
671 671 s> 0\r\n
672 672 s> \r\n
673 673
674 674 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT/redirector << EOF
675 675 > command heads
676 676 > EOF
677 677 s> setsockopt(6, 1, 1) -> None (?)
678 678 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
679 679 s> Accept-Encoding: identity\r\n
680 680 s> accept: application/mercurial-0.1\r\n
681 681 s> host: $LOCALIP:$HGPORT\r\n (glob)
682 682 s> user-agent: Mercurial debugwireproto\r\n
683 683 s> \r\n
684 684 s> makefile('rb', None)
685 685 s> HTTP/1.1 301 Redirect\r\n
686 686 s> Server: testing stub value\r\n
687 687 s> Date: $HTTP_DATE$\r\n
688 688 s> Location: http://$LOCALIP:$HGPORT/redirected\r\n (glob)
689 689 s> Content-Type: text/plain\r\n
690 690 s> Content-Length: 10\r\n
691 691 s> \r\n
692 692 s> redirected
693 693 s> setsockopt(6, 1, 1) -> None (?)
694 694 s> GET /redirected HTTP/1.1\r\n
695 695 s> Accept-Encoding: identity\r\n
696 696 s> accept: application/mercurial-0.1\r\n
697 697 s> host: $LOCALIP:$HGPORT\r\n (glob)
698 698 s> user-agent: Mercurial debugwireproto\r\n
699 699 s> \r\n
700 700 s> makefile('rb', None)
701 701 s> HTTP/1.1 200 Script output follows\r\n
702 702 s> Server: testing stub value\r\n
703 703 s> Date: $HTTP_DATE$\r\n
704 704 s> ETag: W/"*"\r\n (glob)
705 705 s> Content-Type: text/html; charset=ascii\r\n
706 706 s> Transfer-Encoding: chunked\r\n
707 707 s> \r\n
708 708 real URL is http://$LOCALIP:$HGPORT/redirected (glob)
709 709 s> 414\r\n
710 710 s> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n
711 711 s> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">\n
712 712 s> <head>\n
713 713 s> <link rel="icon" href="/redirected/static/hgicon.png" type="image/png" />\n
714 714 s> <meta name="robots" content="index, nofollow" />\n
715 715 s> <link rel="stylesheet" href="/redirected/static/style-paper.css" type="text/css" />\n
716 716 s> <script type="text/javascript" src="/redirected/static/mercurial.js"></script>\n
717 717 s> \n
718 718 s> <title>redirected: log</title>\n
719 719 s> <link rel="alternate" type="application/atom+xml"\n
720 720 s> href="/redirected/atom-log" title="Atom feed for redirected" />\n
721 721 s> <link rel="alternate" type="application/rss+xml"\n
722 722 s> href="/redirected/rss-log" title="RSS feed for redirected" />\n
723 723 s> </head>\n
724 724 s> <body>\n
725 725 s> \n
726 726 s> <div class="container">\n
727 727 s> <div class="menu">\n
728 728 s> <div class="logo">\n
729 729 s> <a href="https://mercurial-scm.org/">\n
730 730 s> <img src="/redirected/static/hglogo.png" alt="mercurial" /></a>\n
731 731 s> </div>\n
732 732 s> <ul>\n
733 733 s> <li class="active">log</li>\n
734 734 s> <li><a href="/redirected/graph/tip">graph</a></li>\n
735 735 s> <li><a href="/redirected/tags">tags</a
736 736 s> setsockopt(6, 1, 1) -> None (?)
737 737 s> GET /redirected?cmd=capabilities HTTP/1.1\r\n
738 738 s> Accept-Encoding: identity\r\n
739 739 s> accept: application/mercurial-0.1\r\n
740 740 s> host: $LOCALIP:$HGPORT\r\n (glob)
741 741 s> user-agent: Mercurial debugwireproto\r\n
742 742 s> \r\n
743 743 s> makefile('rb', None)
744 744 s> HTTP/1.1 200 Script output follows\r\n
745 745 s> Server: testing stub value\r\n
746 746 s> Date: $HTTP_DATE$\r\n
747 747 s> Content-Type: application/mercurial-0.1\r\n
748 s> Content-Length: 503\r\n
748 s> Content-Length: 484\r\n
749 749 s> \r\n
750 750 real URL is http://$LOCALIP:$HGPORT/redirected (glob)
751 751 s> batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
752 752 sending heads command
753 753 s> setsockopt(6, 1, 1) -> None (?)
754 754 s> GET /redirected?cmd=heads HTTP/1.1\r\n
755 755 s> Accept-Encoding: identity\r\n
756 756 s> vary: X-HgProto-1\r\n
757 757 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
758 758 s> accept: application/mercurial-0.1\r\n
759 759 s> host: $LOCALIP:$HGPORT\r\n (glob)
760 760 s> user-agent: Mercurial debugwireproto\r\n
761 761 s> \r\n
762 762 s> makefile('rb', None)
763 763 s> HTTP/1.1 200 Script output follows\r\n
764 764 s> Server: testing stub value\r\n
765 765 s> Date: $HTTP_DATE$\r\n
766 766 s> Content-Type: application/mercurial-0.1\r\n
767 767 s> Content-Length: 41\r\n
768 768 s> \r\n
769 769 s> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n
770 770 response: [
771 771 b'\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL'
772 772 ]
773 773 (sent 4 HTTP requests and * bytes; received * bytes in responses) (glob)
@@ -1,615 +1,615 b''
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 $ hg serve -p $HGPORT1 2>&1
21 21 abort: cannot start server at 'localhost:$HGPORT1': $EADDRINUSE$
22 22 [255]
23 23
24 24 $ cd ..
25 25 $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
26 26
27 27 clone via stream
28 28
29 29 #if no-reposimplestore
30 30 $ hg clone --stream http://localhost:$HGPORT/ copy 2>&1
31 31 streaming all changes
32 32 9 files to transfer, 715 bytes of data
33 33 transferred * bytes in * seconds (*/sec) (glob)
34 34 updating to branch default
35 35 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
36 36 $ hg verify -R copy
37 37 checking changesets
38 38 checking manifests
39 39 crosschecking files in changesets and manifests
40 40 checking files
41 41 checked 1 changesets with 4 changes to 4 files
42 42 #endif
43 43
44 44 try to clone via stream, should use pull instead
45 45
46 46 $ hg clone --stream http://localhost:$HGPORT1/ copy2
47 47 warning: stream clone requested but server has them disabled
48 48 requesting all changes
49 49 adding changesets
50 50 adding manifests
51 51 adding file changes
52 52 added 1 changesets with 4 changes to 4 files
53 53 new changesets 8b6053c928fe
54 54 updating to branch default
55 55 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 56
57 57 try to clone via stream but missing requirements, so should use pull instead
58 58
59 59 $ cat > $TESTTMP/removesupportedformat.py << EOF
60 60 > from mercurial import localrepo
61 61 > def extsetup(ui):
62 62 > localrepo.localrepository.supportedformats.remove(b'generaldelta')
63 63 > EOF
64 64
65 65 $ hg clone --config extensions.rsf=$TESTTMP/removesupportedformat.py --stream http://localhost:$HGPORT/ copy3
66 66 warning: stream clone requested but client is missing requirements: generaldelta
67 67 (see https://www.mercurial-scm.org/wiki/MissingRequirement for more information)
68 68 requesting all changes
69 69 adding changesets
70 70 adding manifests
71 71 adding file changes
72 72 added 1 changesets with 4 changes to 4 files
73 73 new changesets 8b6053c928fe
74 74 updating to branch default
75 75 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 76
77 77 clone via pull
78 78
79 79 $ hg clone http://localhost:$HGPORT1/ copy-pull
80 80 requesting all changes
81 81 adding changesets
82 82 adding manifests
83 83 adding file changes
84 84 added 1 changesets with 4 changes to 4 files
85 85 new changesets 8b6053c928fe
86 86 updating to branch default
87 87 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 88 $ hg verify -R copy-pull
89 89 checking changesets
90 90 checking manifests
91 91 crosschecking files in changesets and manifests
92 92 checking files
93 93 checked 1 changesets with 4 changes to 4 files
94 94 $ cd test
95 95 $ echo bar > bar
96 96 $ hg commit -A -d '1 0' -m 2
97 97 adding bar
98 98 $ cd ..
99 99
100 100 clone over http with --update
101 101
102 102 $ hg clone http://localhost:$HGPORT1/ updated --update 0
103 103 requesting all changes
104 104 adding changesets
105 105 adding manifests
106 106 adding file changes
107 107 added 2 changesets with 5 changes to 5 files
108 108 new changesets 8b6053c928fe:5fed3813f7f5
109 109 updating to branch default
110 110 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
111 111 $ hg log -r . -R updated
112 112 changeset: 0:8b6053c928fe
113 113 user: test
114 114 date: Thu Jan 01 00:00:00 1970 +0000
115 115 summary: 1
116 116
117 117 $ rm -rf updated
118 118
119 119 incoming via HTTP
120 120
121 121 $ hg clone http://localhost:$HGPORT1/ --rev 0 partial
122 122 adding changesets
123 123 adding manifests
124 124 adding file changes
125 125 added 1 changesets with 4 changes to 4 files
126 126 new changesets 8b6053c928fe
127 127 updating to branch default
128 128 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
129 129 $ cd partial
130 130 $ touch LOCAL
131 131 $ hg ci -qAm LOCAL
132 132 $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n'
133 133 comparing with http://localhost:$HGPORT1/
134 134 searching for changes
135 135 2
136 136 $ cd ..
137 137
138 138 pull
139 139
140 140 $ cd copy-pull
141 141 $ cat >> .hg/hgrc <<EOF
142 142 > [hooks]
143 143 > changegroup = sh -c "printenv.py --line changegroup"
144 144 > EOF
145 145 $ hg pull
146 146 pulling from http://localhost:$HGPORT1/
147 147 searching for changes
148 148 adding changesets
149 149 adding manifests
150 150 adding file changes
151 151 added 1 changesets with 1 changes to 1 files
152 152 new changesets 5fed3813f7f5
153 153 changegroup hook: HG_HOOKNAME=changegroup
154 154 HG_HOOKTYPE=changegroup
155 155 HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d
156 156 HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d
157 157 HG_SOURCE=pull
158 158 HG_TXNID=TXN:$ID$
159 159 HG_TXNNAME=pull
160 160 http://localhost:$HGPORT1/
161 161 HG_URL=http://localhost:$HGPORT1/
162 162
163 163 (run 'hg update' to get a working copy)
164 164 $ cd ..
165 165
166 166 clone from invalid URL
167 167
168 168 $ hg clone http://localhost:$HGPORT/bad
169 169 abort: HTTP Error 404: Not Found
170 170 [100]
171 171
172 172 test http authentication
173 173 + use the same server to test server side streaming preference
174 174
175 175 $ cd test
176 176
177 177 $ hg serve --config extensions.x=$TESTDIR/httpserverauth.py -p $HGPORT2 -d \
178 178 > --pid-file=pid --config server.preferuncompressed=True -E ../errors2.log \
179 179 > --config web.push_ssl=False --config web.allow_push=* -A ../access.log
180 180 $ cat pid >> $DAEMON_PIDS
181 181
182 182 $ cat << EOF > get_pass.py
183 183 > import getpass
184 184 > def newgetpass(arg):
185 185 > return "pass"
186 186 > getpass.getpass = newgetpass
187 187 > EOF
188 188
189 189 $ hg id http://localhost:$HGPORT2/
190 190 abort: http authorization required for http://localhost:$HGPORT2/
191 191 [255]
192 192 $ hg id http://localhost:$HGPORT2/
193 193 abort: http authorization required for http://localhost:$HGPORT2/
194 194 [255]
195 195 $ hg id --config ui.interactive=true --debug http://localhost:$HGPORT2/
196 196 using http://localhost:$HGPORT2/
197 197 sending capabilities command
198 198 http authorization required for http://localhost:$HGPORT2/
199 199 realm: mercurial
200 200 user: abort: response expected
201 201 [255]
202 202 $ cat <<'EOF' | hg id --config ui.interactive=true --config ui.nontty=true --debug http://localhost:$HGPORT2/
203 203 >
204 204 > EOF
205 205 using http://localhost:$HGPORT2/
206 206 sending capabilities command
207 207 http authorization required for http://localhost:$HGPORT2/
208 208 realm: mercurial
209 209 user:
210 210 password: abort: response expected
211 211 [255]
212 212 $ cat <<'EOF' | hg id --config ui.interactive=true --config ui.nontty=true --debug http://localhost:$HGPORT2/
213 213 >
214 214 >
215 215 > EOF
216 216 using http://localhost:$HGPORT2/
217 217 sending capabilities command
218 218 http authorization required for http://localhost:$HGPORT2/
219 219 realm: mercurial
220 220 user:
221 221 password: abort: authorization failed
222 222 [255]
223 223 $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
224 224 http authorization required for http://localhost:$HGPORT2/
225 225 realm: mercurial
226 226 user: user
227 227 password: 5fed3813f7f5
228 228 $ hg id http://user:pass@localhost:$HGPORT2/
229 229 5fed3813f7f5
230 230 $ echo '[auth]' >> .hg/hgrc
231 231 $ echo 'l.schemes=http' >> .hg/hgrc
232 232 $ echo 'l.prefix=lo' >> .hg/hgrc
233 233 $ echo 'l.username=user' >> .hg/hgrc
234 234 $ echo 'l.password=pass' >> .hg/hgrc
235 235 $ hg id http://localhost:$HGPORT2/
236 236 5fed3813f7f5
237 237 $ hg id http://localhost:$HGPORT2/
238 238 5fed3813f7f5
239 239 $ hg id http://user@localhost:$HGPORT2/
240 240 5fed3813f7f5
241 241
242 242 $ cat > use_digests.py << EOF
243 243 > from mercurial import (
244 244 > exthelper,
245 245 > url,
246 246 > )
247 247 >
248 248 > eh = exthelper.exthelper()
249 249 > uisetup = eh.finaluisetup
250 250 >
251 251 > @eh.wrapfunction(url, 'opener')
252 252 > def urlopener(orig, *args, **kwargs):
253 253 > opener = orig(*args, **kwargs)
254 254 > opener.addheaders.append((r'X-HgTest-AuthType', r'Digest'))
255 255 > return opener
256 256 > EOF
257 257
258 258 $ hg id http://localhost:$HGPORT2/ --config extensions.x=use_digests.py
259 259 5fed3813f7f5
260 260
261 261 #if no-reposimplestore
262 262 $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1
263 263 streaming all changes
264 264 10 files to transfer, 1.01 KB of data
265 265 transferred * KB in * seconds (*/sec) (glob)
266 266 updating to branch default
267 267 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
268 268 #endif
269 269
270 270 --pull should override server's preferuncompressed
271 271 $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1
272 272 requesting all changes
273 273 adding changesets
274 274 adding manifests
275 275 adding file changes
276 276 added 2 changesets with 5 changes to 5 files
277 277 new changesets 8b6053c928fe:5fed3813f7f5
278 278 updating to branch default
279 279 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
280 280
281 281 $ hg id http://user2@localhost:$HGPORT2/
282 282 abort: http authorization required for http://localhost:$HGPORT2/
283 283 [255]
284 284 $ hg id http://user:pass2@localhost:$HGPORT2/
285 285 abort: HTTP Error 403: no
286 286 [100]
287 287
288 288 $ hg -R dest-pull tag -r tip top
289 289 $ hg -R dest-pull push http://user:pass@localhost:$HGPORT2/
290 290 pushing to http://user:***@localhost:$HGPORT2/
291 291 searching for changes
292 292 remote: adding changesets
293 293 remote: adding manifests
294 294 remote: adding file changes
295 295 remote: added 1 changesets with 1 changes to 1 files
296 296 $ hg rollback -q
297 297 $ hg -R dest-pull push http://user:pass@localhost:$HGPORT2/ --debug --config devel.debug.peer-request=yes
298 298 pushing to http://user:***@localhost:$HGPORT2/
299 299 using http://localhost:$HGPORT2/
300 300 http auth: user user, password ****
301 301 sending capabilities command
302 302 devel-peer-request: GET http://localhost:$HGPORT2/?cmd=capabilities
303 303 http auth: user user, password ****
304 304 devel-peer-request: finished in *.???? seconds (200) (glob)
305 305 query 1; heads
306 306 devel-peer-request: batched-content
307 307 devel-peer-request: - heads (0 arguments)
308 308 devel-peer-request: - known (1 arguments)
309 309 sending batch command
310 310 devel-peer-request: GET http://localhost:$HGPORT2/?cmd=batch
311 311 devel-peer-request: Vary X-HgArg-1,X-HgProto-1
312 312 devel-peer-request: X-hgproto-1 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
313 313 devel-peer-request: 68 bytes of commands arguments in headers
314 314 devel-peer-request: finished in *.???? seconds (200) (glob)
315 315 searching for changes
316 316 all remote heads known locally
317 317 preparing listkeys for "phases"
318 318 sending listkeys command
319 319 devel-peer-request: GET http://localhost:$HGPORT2/?cmd=listkeys
320 320 devel-peer-request: Vary X-HgArg-1,X-HgProto-1
321 321 devel-peer-request: X-hgproto-1 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
322 322 devel-peer-request: 16 bytes of commands arguments in headers
323 323 devel-peer-request: finished in *.???? seconds (200) (glob)
324 324 received listkey for "phases": 58 bytes
325 325 checking for updated bookmarks
326 326 preparing listkeys for "bookmarks"
327 327 sending listkeys command
328 328 devel-peer-request: GET http://localhost:$HGPORT2/?cmd=listkeys
329 329 devel-peer-request: Vary X-HgArg-1,X-HgProto-1
330 330 devel-peer-request: X-hgproto-1 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
331 331 devel-peer-request: 19 bytes of commands arguments in headers
332 332 devel-peer-request: finished in *.???? seconds (200) (glob)
333 333 received listkey for "bookmarks": 0 bytes
334 334 sending branchmap command
335 335 devel-peer-request: GET http://localhost:$HGPORT2/?cmd=branchmap
336 336 devel-peer-request: Vary X-HgProto-1
337 337 devel-peer-request: X-hgproto-1 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
338 338 devel-peer-request: finished in *.???? seconds (200) (glob)
339 339 preparing listkeys for "bookmarks"
340 340 sending listkeys command
341 341 devel-peer-request: GET http://localhost:$HGPORT2/?cmd=listkeys
342 342 devel-peer-request: Vary X-HgArg-1,X-HgProto-1
343 343 devel-peer-request: X-hgproto-1 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
344 344 devel-peer-request: 19 bytes of commands arguments in headers
345 345 devel-peer-request: finished in *.???? seconds (200) (glob)
346 346 received listkey for "bookmarks": 0 bytes
347 347 1 changesets found
348 348 list of changesets:
349 349 7f4e523d01f2cc3765ac8934da3d14db775ff872
350 350 bundle2-output-bundle: "HG20", 5 parts total
351 bundle2-output-part: "replycaps" 224 bytes payload
351 bundle2-output-part: "replycaps" 207 bytes payload
352 352 bundle2-output-part: "check:phases" 24 bytes payload
353 353 bundle2-output-part: "check:updated-heads" streamed payload
354 354 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
355 355 bundle2-output-part: "phase-heads" 24 bytes payload
356 356 sending unbundle command
357 sending 1040 bytes
357 sending 1023 bytes
358 358 devel-peer-request: POST http://localhost:$HGPORT2/?cmd=unbundle
359 devel-peer-request: Content-length 1040
359 devel-peer-request: Content-length 1023
360 360 devel-peer-request: Content-type application/mercurial-0.1
361 361 devel-peer-request: Vary X-HgArg-1,X-HgProto-1
362 362 devel-peer-request: X-hgproto-1 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
363 363 devel-peer-request: 16 bytes of commands arguments in headers
364 devel-peer-request: 1040 bytes of data
364 devel-peer-request: 1023 bytes of data
365 365 devel-peer-request: finished in *.???? seconds (200) (glob)
366 366 bundle2-input-bundle: no-transaction
367 367 bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
368 368 bundle2-input-part: "output" (advisory) (params: 0 advisory) supported
369 369 bundle2-input-part: total payload size 55
370 370 remote: adding changesets
371 371 remote: adding manifests
372 372 remote: adding file changes
373 373 bundle2-input-part: "output" (advisory) supported
374 374 bundle2-input-part: total payload size 45
375 375 remote: added 1 changesets with 1 changes to 1 files
376 376 bundle2-input-bundle: 3 parts total
377 377 preparing listkeys for "phases"
378 378 sending listkeys command
379 379 devel-peer-request: GET http://localhost:$HGPORT2/?cmd=listkeys
380 380 devel-peer-request: Vary X-HgArg-1,X-HgProto-1
381 381 devel-peer-request: X-hgproto-1 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
382 382 devel-peer-request: 16 bytes of commands arguments in headers
383 383 devel-peer-request: finished in *.???? seconds (200) (glob)
384 384 received listkey for "phases": 15 bytes
385 385 $ hg rollback -q
386 386
387 387 $ sed 's/.*] "/"/' < ../access.log
388 388 "GET /?cmd=capabilities HTTP/1.1" 401 -
389 389 "GET /?cmd=capabilities HTTP/1.1" 401 -
390 390 "GET /?cmd=capabilities HTTP/1.1" 401 -
391 391 "GET /?cmd=capabilities HTTP/1.1" 401 -
392 392 "GET /?cmd=capabilities HTTP/1.1" 401 -
393 393 "GET /?cmd=capabilities HTTP/1.1" 401 -
394 394 "GET /?cmd=capabilities HTTP/1.1" 200 -
395 395 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
396 396 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
397 397 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
398 398 "GET /?cmd=capabilities HTTP/1.1" 401 -
399 399 "GET /?cmd=capabilities HTTP/1.1" 200 -
400 400 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
401 401 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
402 402 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
403 403 "GET /?cmd=capabilities HTTP/1.1" 401 -
404 404 "GET /?cmd=capabilities HTTP/1.1" 200 -
405 405 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
406 406 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
407 407 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
408 408 "GET /?cmd=capabilities HTTP/1.1" 401 -
409 409 "GET /?cmd=capabilities HTTP/1.1" 200 -
410 410 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
411 411 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
412 412 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
413 413 "GET /?cmd=capabilities HTTP/1.1" 401 -
414 414 "GET /?cmd=capabilities HTTP/1.1" 200 -
415 415 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
416 416 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
417 417 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
418 418 "GET /?cmd=capabilities HTTP/1.1" 401 - x-hgtest-authtype:Digest
419 419 "GET /?cmd=capabilities HTTP/1.1" 200 - x-hgtest-authtype:Digest
420 420 "GET /?cmd=lookup HTTP/1.1" 401 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest
421 421 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest
422 422 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest
423 423 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest
424 424 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest
425 425 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest
426 426 "GET /?cmd=capabilities HTTP/1.1" 401 - (no-reposimplestore !)
427 427 "GET /?cmd=capabilities HTTP/1.1" 200 - (no-reposimplestore !)
428 428 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (no-reposimplestore !)
429 429 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=0&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=bookmarks&stream=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (no-reposimplestore !)
430 430 "GET /?cmd=capabilities HTTP/1.1" 401 - (no-reposimplestore !)
431 431 "GET /?cmd=capabilities HTTP/1.1" 200 - (no-reposimplestore !)
432 432 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
433 433 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
434 434 "GET /?cmd=capabilities HTTP/1.1" 401 -
435 435 "GET /?cmd=capabilities HTTP/1.1" 401 -
436 436 "GET /?cmd=capabilities HTTP/1.1" 403 -
437 437 "GET /?cmd=capabilities HTTP/1.1" 401 -
438 438 "GET /?cmd=capabilities HTTP/1.1" 200 -
439 439 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
440 440 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
441 441 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
442 442 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
443 443 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
444 444 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365* (glob)
445 445 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
446 446 "GET /?cmd=capabilities HTTP/1.1" 401 -
447 447 "GET /?cmd=capabilities HTTP/1.1" 200 -
448 448 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
449 449 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
450 450 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
451 451 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
452 452 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
453 453 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
454 454 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
455 455
456 456 $ cd ..
457 457
458 458 clone of serve with repo in root and unserved subrepo (issue2970)
459 459
460 460 $ hg --cwd test init sub
461 461 $ echo empty > test/sub/empty
462 462 $ hg --cwd test/sub add empty
463 463 $ hg --cwd test/sub commit -qm 'add empty'
464 464 $ hg --cwd test/sub tag -r 0 something
465 465 $ echo sub = sub > test/.hgsub
466 466 $ hg --cwd test add .hgsub
467 467 $ hg --cwd test commit -qm 'add subrepo'
468 468 $ hg clone http://localhost:$HGPORT noslash-clone
469 469 requesting all changes
470 470 adding changesets
471 471 adding manifests
472 472 adding file changes
473 473 added 3 changesets with 7 changes to 7 files
474 474 new changesets 8b6053c928fe:56f9bc90cce6
475 475 updating to branch default
476 476 cloning subrepo sub from http://localhost:$HGPORT/sub
477 477 abort: HTTP Error 404: Not Found
478 478 [100]
479 479 $ hg clone http://localhost:$HGPORT/ slash-clone
480 480 requesting all changes
481 481 adding changesets
482 482 adding manifests
483 483 adding file changes
484 484 added 3 changesets with 7 changes to 7 files
485 485 new changesets 8b6053c928fe:56f9bc90cce6
486 486 updating to branch default
487 487 cloning subrepo sub from http://localhost:$HGPORT/sub
488 488 abort: HTTP Error 404: Not Found
489 489 [100]
490 490
491 491 check error log
492 492
493 493 $ cat error.log
494 494
495 495 $ cat errors2.log
496 496
497 497 check abort error reporting while pulling/cloning
498 498
499 499 $ $RUNTESTDIR/killdaemons.py
500 500 $ hg serve -R test -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py
501 501 $ cat hg3.pid >> $DAEMON_PIDS
502 502 $ hg clone http://localhost:$HGPORT/ abort-clone
503 503 requesting all changes
504 504 remote: abort: this is an exercise
505 505 abort: pull failed on remote
506 506 [255]
507 507 $ cat error.log
508 508
509 509 disable pull-based clones
510 510
511 511 $ hg serve -R test -p $HGPORT1 -d --pid-file=hg4.pid -E error.log --config server.disablefullbundle=True
512 512 $ cat hg4.pid >> $DAEMON_PIDS
513 513 $ hg clone http://localhost:$HGPORT1/ disable-pull-clone
514 514 requesting all changes
515 515 remote: abort: server has pull-based clones disabled
516 516 abort: pull failed on remote
517 517 (remove --pull if specified or upgrade Mercurial)
518 518 [255]
519 519
520 520 #if no-reposimplestore
521 521 ... but keep stream clones working
522 522
523 523 $ hg clone --stream --noupdate http://localhost:$HGPORT1/ test-stream-clone
524 524 streaming all changes
525 525 * files to transfer, * of data (glob)
526 526 transferred * in * seconds (*/sec) (glob)
527 527 $ cat error.log
528 528 #endif
529 529
530 530 ... and also keep partial clones and pulls working
531 531 $ hg clone http://localhost:$HGPORT1 --rev 0 test/partial/clone
532 532 adding changesets
533 533 adding manifests
534 534 adding file changes
535 535 added 1 changesets with 4 changes to 4 files
536 536 new changesets 8b6053c928fe
537 537 updating to branch default
538 538 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 539 $ hg pull -R test/partial/clone
540 540 pulling from http://localhost:$HGPORT1/
541 541 searching for changes
542 542 adding changesets
543 543 adding manifests
544 544 adding file changes
545 545 added 2 changesets with 3 changes to 3 files
546 546 new changesets 5fed3813f7f5:56f9bc90cce6
547 547 (run 'hg update' to get a working copy)
548 548
549 549 $ hg clone -U -r 0 test/partial/clone test/another/clone
550 550 adding changesets
551 551 adding manifests
552 552 adding file changes
553 553 added 1 changesets with 4 changes to 4 files
554 554 new changesets 8b6053c928fe
555 555
556 556 corrupt cookies file should yield a warning
557 557
558 558 $ cat > $TESTTMP/cookies.txt << EOF
559 559 > bad format
560 560 > EOF
561 561
562 562 $ hg --config auth.cookiefile=$TESTTMP/cookies.txt id http://localhost:$HGPORT/
563 563 (error loading cookie file $TESTTMP/cookies.txt: '*/cookies.txt' does not look like a Netscape format cookies file; continuing without cookies) (glob)
564 564 56f9bc90cce6
565 565
566 566 $ killdaemons.py
567 567
568 568 Create dummy authentication handler that looks for cookies. It doesn't do anything
569 569 useful. It just raises an HTTP 500 with details about the Cookie request header.
570 570 We raise HTTP 500 because its message is printed in the abort message.
571 571
572 572 $ cat > cookieauth.py << EOF
573 573 > from mercurial import util
574 574 > from mercurial.hgweb import common
575 575 > def perform_authentication(hgweb, req, op):
576 576 > cookie = req.headers.get(b'Cookie')
577 577 > if not cookie:
578 578 > raise common.ErrorResponse(common.HTTP_SERVER_ERROR, b'no-cookie')
579 579 > raise common.ErrorResponse(common.HTTP_SERVER_ERROR, b'Cookie: %s' % cookie)
580 580 > def extsetup(ui):
581 581 > common.permhooks.insert(0, perform_authentication)
582 582 > EOF
583 583
584 584 $ hg serve --config extensions.cookieauth=cookieauth.py -R test -p $HGPORT -d --pid-file=pid
585 585 $ cat pid > $DAEMON_PIDS
586 586
587 587 Request without cookie sent should fail due to lack of cookie
588 588
589 589 $ hg id http://localhost:$HGPORT
590 590 abort: HTTP Error 500: no-cookie
591 591 [100]
592 592
593 593 Populate a cookies file
594 594
595 595 $ cat > cookies.txt << EOF
596 596 > # HTTP Cookie File
597 597 > # Expiration is 2030-01-01 at midnight
598 598 > .example.com TRUE / FALSE 1893456000 hgkey examplevalue
599 599 > EOF
600 600
601 601 Should not send a cookie for another domain
602 602
603 603 $ hg --config auth.cookiefile=cookies.txt id http://localhost:$HGPORT/
604 604 abort: HTTP Error 500: no-cookie
605 605 [100]
606 606
607 607 Add a cookie entry for our test server and verify it is sent
608 608
609 609 $ cat >> cookies.txt << EOF
610 610 > localhost.local FALSE / FALSE 1893456000 hgkey localhostvalue
611 611 > EOF
612 612
613 613 $ hg --config auth.cookiefile=cookies.txt id http://localhost:$HGPORT/
614 614 abort: HTTP Error 500: Cookie: hgkey=localhostvalue
615 615 [100]
@@ -1,514 +1,512 b''
1 1 #require serve no-reposimplestore no-chg
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > lfs=
6 6 > [lfs]
7 7 > track=all()
8 8 > [web]
9 9 > push_ssl = False
10 10 > allow-push = *
11 11 > EOF
12 12
13 13 Serving LFS files can experimentally be turned off. The long term solution is
14 14 to support the 'verify' action in both client and server, so that the server can
15 15 tell the client to store files elsewhere.
16 16
17 17 $ hg init server
18 18 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
19 19 > --config experimental.lfs.serve=False -R server serve -d \
20 20 > --config experimental.lfs.worker-enable=False \
21 21 > -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
22 22 $ cat hg.pid >> $DAEMON_PIDS
23 23
24 24 Uploads fail...
25 25
26 26 $ hg init client
27 27 $ echo 'this-is-an-lfs-file' > client/lfs.bin
28 28 $ hg -R client ci -Am 'initial commit'
29 29 adding lfs.bin
30 30 $ hg -R client push http://localhost:$HGPORT
31 31 pushing to http://localhost:$HGPORT/
32 32 searching for changes
33 33 abort: LFS HTTP error: HTTP Error 400: no such method: .git
34 34 (check that lfs serving is enabled on http://localhost:$HGPORT/.git/info/lfs and "upload" is supported)
35 35 [50]
36 36
37 37 ... so do a local push to make the data available. Remove the blob from the
38 38 default cache, so it attempts to download.
39 39 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
40 40 > --config "lfs.url=null://" \
41 41 > -R client push -q server
42 42 $ mv `hg config lfs.usercache` $TESTTMP/servercache
43 43
44 44 Downloads fail...
45 45
46 46 $ hg clone http://localhost:$HGPORT httpclone
47 47 (remote is using large file support (lfs); lfs will be enabled for this repository)
48 48 requesting all changes
49 49 adding changesets
50 50 adding manifests
51 51 adding file changes
52 52 added 1 changesets with 1 changes to 1 files
53 53 new changesets 525251863cad
54 54 updating to branch default
55 55 abort: LFS HTTP error: HTTP Error 400: no such method: .git
56 56 (check that lfs serving is enabled on http://localhost:$HGPORT/.git/info/lfs and "download" is supported)
57 57 [50]
58 58
59 59 $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
60 60
61 61 $ cat $TESTTMP/access.log $TESTTMP/errors.log
62 62 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
63 63 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D525251863cad618e55d483555f3d00a2ca99597e x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
64 64 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
65 65 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
66 66 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
67 67 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
68 68 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
69 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Acheckheads%253Drelated%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
69 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Acheckheads%253Drelated%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
70 70 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
71 71
72 72 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
73 73 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server serve -d \
74 74 > -p $HGPORT --pid-file=hg.pid --prefix=subdir/mount/point \
75 75 > -A $TESTTMP/access.log -E $TESTTMP/errors.log
76 76 $ cat hg.pid >> $DAEMON_PIDS
77 77
78 78 Reasonable hint for a misconfigured blob server
79 79
80 80 $ hg -R httpclone update default --config lfs.url=http://localhost:$HGPORT/missing
81 81 abort: LFS HTTP error: HTTP Error 404: Not Found
82 82 (the "lfs.url" config may be used to override http://localhost:$HGPORT/missing)
83 83 [50]
84 84
85 85 $ hg -R httpclone update default --config lfs.url=http://localhost:$HGPORT2/missing
86 86 abort: LFS error: *onnection *refused* (glob) (?)
87 87 abort: LFS error: $EADDRNOTAVAIL$ (glob) (?)
88 88 abort: LFS error: No route to host (?)
89 89 (the "lfs.url" config may be used to override http://localhost:$HGPORT2/missing)
90 90 [50]
91 91
92 92 Blob URIs are correct when --prefix is used
93 93
94 94 $ hg clone --debug http://localhost:$HGPORT/subdir/mount/point cloned2
95 95 using http://localhost:$HGPORT/subdir/mount/point
96 96 sending capabilities command
97 97 (remote is using large file support (lfs); lfs will be enabled for this repository)
98 98 query 1; heads
99 99 sending batch command
100 100 requesting all changes
101 101 sending getbundle command
102 102 bundle2-input-bundle: with-transaction
103 103 bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
104 104 adding changesets
105 105 add changeset 525251863cad
106 106 adding manifests
107 107 adding file changes
108 108 adding lfs.bin revisions
109 109 bundle2-input-part: total payload size 648
110 110 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
111 111 bundle2-input-part: "phase-heads" supported
112 112 bundle2-input-part: total payload size 24
113 bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
114 bundle2-input-part: total payload size 39
115 bundle2-input-bundle: 4 parts total
113 bundle2-input-bundle: 3 parts total
116 114 checking for updated bookmarks
117 115 updating the branch cache
118 116 added 1 changesets with 1 changes to 1 files
119 117 new changesets 525251863cad
120 118 updating to branch default
121 119 resolving manifests
122 120 branchmerge: False, force: False, partial: False
123 121 ancestor: 000000000000, local: 000000000000+, remote: 525251863cad
124 122 lfs: assuming remote store: http://localhost:$HGPORT/subdir/mount/point/.git/info/lfs
125 123 Status: 200
126 124 Content-Length: 371
127 125 Content-Type: application/vnd.git-lfs+json
128 126 Date: $HTTP_DATE$
129 127 Server: testing stub value
130 128 {
131 129 "objects": [
132 130 {
133 131 "actions": {
134 132 "download": {
135 133 "expires_at": "$ISO_8601_DATE_TIME$"
136 134 "header": {
137 135 "Accept": "application/vnd.git-lfs"
138 136 }
139 137 "href": "http://localhost:$HGPORT/subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
140 138 }
141 139 }
142 140 "oid": "f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
143 141 "size": 20
144 142 }
145 143 ]
146 144 "transfer": "basic"
147 145 }
148 146 lfs: downloading f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e (20 bytes)
149 147 Status: 200
150 148 Content-Length: 20
151 149 Content-Type: application/octet-stream
152 150 Date: $HTTP_DATE$
153 151 Server: testing stub value
154 152 lfs: adding f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e to the usercache
155 153 lfs: processed: f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
156 154 lfs: downloaded 1 files (20 bytes)
157 155 lfs.bin: remote created -> g
158 156 getting lfs.bin
159 157 lfs: found f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e in the local lfs store
160 158 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
161 159 updating the branch cache
162 160 (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob)
163 161
164 162 $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
165 163
166 164 $ cat $TESTTMP/access.log $TESTTMP/errors.log
167 165 $LOCALIP - - [$LOGDATE$] "POST /missing/objects/batch HTTP/1.1" 404 - (glob)
168 166 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=capabilities HTTP/1.1" 200 - (glob)
169 167 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
170 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Acheckheads%253Drelated%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
168 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Acheckheads%253Drelated%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
171 169 $LOCALIP - - [$LOGDATE$] "POST /subdir/mount/point/.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
172 170 $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e HTTP/1.1" 200 - (glob)
173 171
174 172 Blobs that already exist in the usercache are linked into the repo store, even
175 173 though the client doesn't send the blob.
176 174
177 175 $ hg init server2
178 176 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server2 serve -d \
179 177 > -p $HGPORT --pid-file=hg.pid \
180 178 > -A $TESTTMP/access.log -E $TESTTMP/errors.log
181 179 $ cat hg.pid >> $DAEMON_PIDS
182 180
183 181 $ hg --config "lfs.usercache=$TESTTMP/servercache" -R cloned2 --debug \
184 182 > push http://localhost:$HGPORT | grep '^[{} ]'
185 183 {
186 184 "objects": [
187 185 {
188 186 "oid": "f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e"
189 187 "size": 20
190 188 }
191 189 ]
192 190 "transfer": "basic"
193 191 }
194 192 $ find server2/.hg/store/lfs/objects | sort
195 193 server2/.hg/store/lfs/objects
196 194 server2/.hg/store/lfs/objects/f0
197 195 server2/.hg/store/lfs/objects/f0/3217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
198 196 $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
199 197 $ cat $TESTTMP/errors.log
200 198
201 199 $ cat >> $TESTTMP/lfsstoreerror.py <<EOF
202 200 > import errno
203 201 > from hgext.lfs import blobstore
204 202 >
205 203 > _numverifies = 0
206 204 > _readerr = True
207 205 >
208 206 > def reposetup(ui, repo):
209 207 > # Nothing to do with a remote repo
210 208 > if not repo.local():
211 209 > return
212 210 >
213 211 > store = repo.svfs.lfslocalblobstore
214 212 > class badstore(store.__class__):
215 213 > def download(self, oid, src, contentlength):
216 214 > '''Called in the server to handle reading from the client in a
217 215 > PUT request.'''
218 216 > origread = src.read
219 217 > def _badread(nbytes):
220 218 > # Simulate bad data/checksum failure from the client
221 219 > return b'0' * len(origread(nbytes))
222 220 > src.read = _badread
223 221 > super(badstore, self).download(oid, src, contentlength)
224 222 >
225 223 > def _read(self, vfs, oid, verify):
226 224 > '''Called in the server to read data for a GET request, and then
227 225 > calls self._verify() on it before returning.'''
228 226 > global _readerr
229 227 > # One time simulation of a read error
230 228 > if _readerr:
231 229 > _readerr = False
232 230 > raise IOError(errno.EIO, r'%s: I/O error' % oid.decode("utf-8"))
233 231 > # Simulate corrupt content on client download
234 232 > blobstore._verify(oid, b'dummy content')
235 233 >
236 234 > def verify(self, oid):
237 235 > '''Called in the server to populate the Batch API response,
238 236 > letting the client re-upload if the file is corrupt.'''
239 237 > # Fail verify in Batch API for one clone command and one push
240 238 > # command with an IOError. Then let it through to access other
241 239 > # functions. Checksum failure is tested elsewhere.
242 240 > global _numverifies
243 241 > _numverifies += 1
244 242 > if _numverifies <= 2:
245 243 > raise IOError(errno.EIO, r'%s: I/O error' % oid.decode("utf-8"))
246 244 > return super(badstore, self).verify(oid)
247 245 >
248 246 > store.__class__ = badstore
249 247 > EOF
250 248
251 249 $ rm -rf `hg config lfs.usercache`
252 250 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
253 251 $ hg --config "lfs.usercache=$TESTTMP/servercache" \
254 252 > --config extensions.lfsstoreerror=$TESTTMP/lfsstoreerror.py \
255 253 > -R server serve -d \
256 254 > -p $HGPORT1 --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
257 255 $ cat hg.pid >> $DAEMON_PIDS
258 256
259 257 Test an I/O error in localstore.verify() (Batch API) with GET
260 258
261 259 $ hg clone http://localhost:$HGPORT1 httpclone2
262 260 (remote is using large file support (lfs); lfs will be enabled for this repository)
263 261 requesting all changes
264 262 adding changesets
265 263 adding manifests
266 264 adding file changes
267 265 added 1 changesets with 1 changes to 1 files
268 266 new changesets 525251863cad
269 267 updating to branch default
270 268 abort: LFS server error for "lfs.bin": Internal server error
271 269 [50]
272 270
273 271 Test an I/O error in localstore.verify() (Batch API) with PUT
274 272
275 273 $ echo foo > client/lfs.bin
276 274 $ hg -R client ci -m 'mod lfs'
277 275 $ hg -R client push http://localhost:$HGPORT1
278 276 pushing to http://localhost:$HGPORT1/
279 277 searching for changes
280 278 abort: LFS server error for "unknown": Internal server error
281 279 [50]
282 280 TODO: figure out how to associate the file name in the error above
283 281
284 282 Test a bad checksum sent by the client in the transfer API
285 283
286 284 $ hg -R client push http://localhost:$HGPORT1
287 285 pushing to http://localhost:$HGPORT1/
288 286 searching for changes
289 287 abort: LFS HTTP error: HTTP Error 422: corrupt blob (oid=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, action=upload)
290 288 [50]
291 289
292 290 $ echo 'test lfs file' > server/lfs3.bin
293 291 $ hg --config experimental.lfs.disableusercache=True \
294 292 > -R server ci -Aqm 'another lfs file'
295 293 $ hg -R client pull -q http://localhost:$HGPORT1
296 294
297 295 Test an I/O error during the processing of the GET request
298 296
299 297 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
300 298 > -R client update -r tip
301 299 abort: LFS HTTP error: HTTP Error 500: Internal Server Error (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)
302 300 [50]
303 301
304 302 Test a checksum failure during the processing of the GET request
305 303
306 304 $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
307 305 > -R client update -r tip
308 306 abort: LFS HTTP error: HTTP Error 422: corrupt blob (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)
309 307 [50]
310 308
311 309 $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
312 310
313 311 $ cat $TESTTMP/access.log
314 312 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
315 313 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
316 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Acheckheads%253Drelated%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
314 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Acheckheads%253Drelated%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
317 315 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
318 316 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
319 317 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
320 318 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
321 319 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
322 320 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
323 321 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
324 322 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
325 323 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
326 324 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
327 325 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
328 326 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
329 327 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
330 328 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
331 329 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
332 330 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c HTTP/1.1" 422 - (glob)
333 331 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
334 332 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
335 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Acheckheads%253Drelated%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=525251863cad618e55d483555f3d00a2ca99597e&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
333 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Acheckheads%253Drelated%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Astream%253Dv2&cg=1&common=525251863cad618e55d483555f3d00a2ca99597e&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
336 334 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
337 335 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 500 - (glob)
338 336 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
339 337 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 422 - (glob)
340 338
341 339 $ grep -v ' File "' $TESTTMP/errors.log
342 340 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.git/info/lfs/objects/batch': (glob)
343 341 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
344 342 $LOCALIP - - [$ERRDATE$] HG error: verifies = store.verify(oid) (glob)
345 343 $LOCALIP - - [$ERRDATE$] HG error: raise IOError(errno.EIO, r'%s: I/O error' % oid.decode("utf-8")) (glob)
346 344 $LOCALIP - - [$ERRDATE$] HG error: *Error: [Errno *] f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e: I/O error (glob)
347 345 $LOCALIP - - [$ERRDATE$] HG error: (glob)
348 346 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.git/info/lfs/objects/batch': (glob)
349 347 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
350 348 $LOCALIP - - [$ERRDATE$] HG error: verifies = store.verify(oid) (glob)
351 349 $LOCALIP - - [$ERRDATE$] HG error: raise IOError(errno.EIO, r'%s: I/O error' % oid.decode("utf-8")) (glob)
352 350 $LOCALIP - - [$ERRDATE$] HG error: *Error: [Errno *] b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c: I/O error (glob)
353 351 $LOCALIP - - [$ERRDATE$] HG error: (glob)
354 352 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c': (glob)
355 353 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
356 354 $LOCALIP - - [$ERRDATE$] HG error: localstore.download(oid, req.bodyfh, req.headers[b'Content-Length'])
357 355 $LOCALIP - - [$ERRDATE$] HG error: super(badstore, self).download(oid, src, contentlength)
358 356 $LOCALIP - - [$ERRDATE$] HG error: raise LfsCorruptionError( (glob) (py38 !)
359 357 $LOCALIP - - [$ERRDATE$] HG error: _(b'corrupt remote lfs object: %s') % oid (glob) (no-py38 !)
360 358 $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c (no-py3 !)
361 359 $LOCALIP - - [$ERRDATE$] HG error: hgext.lfs.blobstore.LfsCorruptionError: corrupt remote lfs object: b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c (py3 !)
362 360 $LOCALIP - - [$ERRDATE$] HG error: (glob)
363 361 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
364 362 Traceback (most recent call last):
365 363 self.do_write()
366 364 self.do_hgweb()
367 365 for chunk in self.server.application(env, self._start_response):
368 366 for r in self._runwsgi(req, res, repo):
369 367 handled = wireprotoserver.handlewsgirequest( (py38 !)
370 368 return _processbasictransfer( (py38 !)
371 369 rctx, req, res, self.check_perm (no-py38 !)
372 370 return func(*(args + a), **kw) (no-py3 !)
373 371 rctx.repo, req, res, lambda perm: checkperm(rctx, req, perm) (no-py38 !)
374 372 res.setbodybytes(localstore.read(oid))
375 373 blob = self._read(self.vfs, oid, verify)
376 374 raise IOError(errno.EIO, r'%s: I/O error' % oid.decode("utf-8"))
377 375 *Error: [Errno *] 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d: I/O error (glob)
378 376
379 377 $LOCALIP - - [$ERRDATE$] HG error: Exception happened while processing request '/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d': (glob)
380 378 $LOCALIP - - [$ERRDATE$] HG error: Traceback (most recent call last): (glob)
381 379 $LOCALIP - - [$ERRDATE$] HG error: res.setbodybytes(localstore.read(oid)) (glob)
382 380 $LOCALIP - - [$ERRDATE$] HG error: blob = self._read(self.vfs, oid, verify) (glob)
383 381 $LOCALIP - - [$ERRDATE$] HG error: blobstore._verify(oid, b'dummy content') (glob)
384 382 $LOCALIP - - [$ERRDATE$] HG error: raise LfsCorruptionError( (glob) (py38 !)
385 383 $LOCALIP - - [$ERRDATE$] HG error: hint=_(b'run hg verify'), (glob) (no-py38 !)
386 384 $LOCALIP - - [$ERRDATE$] HG error: LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (no-py3 !)
387 385 $LOCALIP - - [$ERRDATE$] HG error: hgext.lfs.blobstore.LfsCorruptionError: detected corrupt lfs object: 276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d (py3 !)
388 386 $LOCALIP - - [$ERRDATE$] HG error: (glob)
389 387
390 388 Basic Authorization headers are returned by the Batch API, and sent back with
391 389 the GET/PUT request.
392 390
393 391 $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
394 392
395 393 $ cat >> $HGRCPATH << EOF
396 394 > [experimental]
397 395 > lfs.disableusercache = True
398 396 > [auth]
399 397 > l.schemes=http
400 398 > l.prefix=lo
401 399 > l.username=user
402 400 > l.password=pass
403 401 > EOF
404 402
405 403 $ hg --config extensions.x=$TESTDIR/httpserverauth.py \
406 404 > -R server serve -d -p $HGPORT1 --pid-file=hg.pid \
407 405 > -A $TESTTMP/access.log -E $TESTTMP/errors.log
408 406 $ mv hg.pid $DAEMON_PIDS
409 407
410 408 $ hg clone --debug http://localhost:$HGPORT1 auth_clone | egrep '^[{}]| '
411 409 {
412 410 "objects": [
413 411 {
414 412 "actions": {
415 413 "download": {
416 414 "expires_at": "$ISO_8601_DATE_TIME$"
417 415 "header": {
418 416 "Accept": "application/vnd.git-lfs"
419 417 "Authorization": "Basic dXNlcjpwYXNz"
420 418 }
421 419 "href": "http://localhost:$HGPORT1/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d"
422 420 }
423 421 }
424 422 "oid": "276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d"
425 423 "size": 14
426 424 }
427 425 ]
428 426 "transfer": "basic"
429 427 }
430 428
431 429 $ echo 'another blob' > auth_clone/lfs.blob
432 430 $ hg -R auth_clone ci -Aqm 'add blob'
433 431
434 432 $ cat > use_digests.py << EOF
435 433 > from mercurial import (
436 434 > exthelper,
437 435 > url,
438 436 > )
439 437 >
440 438 > eh = exthelper.exthelper()
441 439 > uisetup = eh.finaluisetup
442 440 >
443 441 > @eh.wrapfunction(url, 'opener')
444 442 > def urlopener(orig, *args, **kwargs):
445 443 > opener = orig(*args, **kwargs)
446 444 > opener.addheaders.append((r'X-HgTest-AuthType', r'Digest'))
447 445 > return opener
448 446 > EOF
449 447
450 448 Test that Digest Auth fails gracefully before testing the successful Basic Auth
451 449
452 450 $ hg -R auth_clone push --config extensions.x=use_digests.py
453 451 pushing to http://localhost:$HGPORT1/
454 452 searching for changes
455 453 abort: LFS HTTP error: HTTP Error 401: the server must support Basic Authentication
456 454 (api=http://localhost:$HGPORT1/.git/info/lfs/objects/batch, action=upload)
457 455 [50]
458 456
459 457 $ hg -R auth_clone --debug push | egrep '^[{}]| '
460 458 {
461 459 "objects": [
462 460 {
463 461 "actions": {
464 462 "upload": {
465 463 "expires_at": "$ISO_8601_DATE_TIME$"
466 464 "header": {
467 465 "Accept": "application/vnd.git-lfs"
468 466 "Authorization": "Basic dXNlcjpwYXNz"
469 467 }
470 468 "href": "http://localhost:$HGPORT1/.hg/lfs/objects/df14287d8d75f076a6459e7a3703ca583ca9fb3f4918caed10c77ac8622d49b3"
471 469 }
472 470 }
473 471 "oid": "df14287d8d75f076a6459e7a3703ca583ca9fb3f4918caed10c77ac8622d49b3"
474 472 "size": 13
475 473 }
476 474 ]
477 475 "transfer": "basic"
478 476 }
479 477
480 478 $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
481 479
482 480 $ cat $TESTTMP/access.log $TESTTMP/errors.log
483 481 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 401 - (glob)
484 482 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
485 483 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
486 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Acheckheads%253Drelated%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
484 $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Acheckheads%253Drelated%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
487 485 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 401 - (glob)
488 486 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
489 487 $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d HTTP/1.1" 200 - (glob)
490 488 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 401 - x-hgtest-authtype:Digest (glob)
491 489 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - x-hgtest-authtype:Digest (glob)
492 490 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 401 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D525251863cad618e55d483555f3d00a2ca99597e+4d9397055dc0c205f3132f331f36353ab1a525a3 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest (glob)
493 491 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D525251863cad618e55d483555f3d00a2ca99597e+4d9397055dc0c205f3132f331f36353ab1a525a3 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest (glob)
494 492 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest (glob)
495 493 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest (glob)
496 494 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest (glob)
497 495 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest (glob)
498 496 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest (glob)
499 497 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest (glob)
500 498 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest (glob)
501 499 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull x-hgtest-authtype:Digest (glob)
502 500 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 401 - x-hgtest-authtype:Digest (glob)
503 501 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 401 - (glob)
504 502 $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
505 503 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D525251863cad618e55d483555f3d00a2ca99597e+4d9397055dc0c205f3132f331f36353ab1a525a3 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
506 504 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
507 505 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
508 506 $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
509 507 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
510 508 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 401 - (glob)
511 509 $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
512 510 $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/df14287d8d75f076a6459e7a3703ca583ca9fb3f4918caed10c77ac8622d49b3 HTTP/1.1" 201 - (glob)
513 511 $LOCALIP - - [$LOGDATE$] "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
514 512 $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now