##// END OF EJS Templates
errors: set detailed exit code to 100 for some remote errors...
Martin von Zweigbergk -
r46443:ebee234d default
parent child Browse files
Show More
@@ -1,2301 +1,2304 b''
1 1 # scmutil.py - Mercurial core utility functions
2 2 #
3 3 # Copyright Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11 import glob
12 12 import os
13 13 import posixpath
14 14 import re
15 15 import subprocess
16 16 import weakref
17 17
18 18 from .i18n import _
19 19 from .node import (
20 20 bin,
21 21 hex,
22 22 nullid,
23 23 nullrev,
24 24 short,
25 25 wdirid,
26 26 wdirrev,
27 27 )
28 28 from .pycompat import getattr
29 29 from .thirdparty import attr
30 30 from . import (
31 31 copies as copiesmod,
32 32 encoding,
33 33 error,
34 34 match as matchmod,
35 35 obsolete,
36 36 obsutil,
37 37 pathutil,
38 38 phases,
39 39 policy,
40 40 pycompat,
41 41 requirements as requirementsmod,
42 42 revsetlang,
43 43 similar,
44 44 smartset,
45 45 url,
46 46 util,
47 47 vfs,
48 48 )
49 49
50 50 from .utils import (
51 51 hashutil,
52 52 procutil,
53 53 stringutil,
54 54 )
55 55
56 56 if pycompat.iswindows:
57 57 from . import scmwindows as scmplatform
58 58 else:
59 59 from . import scmposix as scmplatform
60 60
61 61 parsers = policy.importmod('parsers')
62 62 rustrevlog = policy.importrust('revlog')
63 63
64 64 termsize = scmplatform.termsize
65 65
66 66
67 67 @attr.s(slots=True, repr=False)
68 68 class status(object):
69 69 '''Struct with a list of files per status.
70 70
71 71 The 'deleted', 'unknown' and 'ignored' properties are only
72 72 relevant to the working copy.
73 73 '''
74 74
75 75 modified = attr.ib(default=attr.Factory(list))
76 76 added = attr.ib(default=attr.Factory(list))
77 77 removed = attr.ib(default=attr.Factory(list))
78 78 deleted = attr.ib(default=attr.Factory(list))
79 79 unknown = attr.ib(default=attr.Factory(list))
80 80 ignored = attr.ib(default=attr.Factory(list))
81 81 clean = attr.ib(default=attr.Factory(list))
82 82
83 83 def __iter__(self):
84 84 yield self.modified
85 85 yield self.added
86 86 yield self.removed
87 87 yield self.deleted
88 88 yield self.unknown
89 89 yield self.ignored
90 90 yield self.clean
91 91
92 92 def __repr__(self):
93 93 return (
94 94 r'<status modified=%s, added=%s, removed=%s, deleted=%s, '
95 95 r'unknown=%s, ignored=%s, clean=%s>'
96 96 ) % tuple(pycompat.sysstr(stringutil.pprint(v)) for v in self)
97 97
98 98
99 99 def itersubrepos(ctx1, ctx2):
100 100 """find subrepos in ctx1 or ctx2"""
101 101 # Create a (subpath, ctx) mapping where we prefer subpaths from
102 102 # ctx1. The subpaths from ctx2 are important when the .hgsub file
103 103 # has been modified (in ctx2) but not yet committed (in ctx1).
104 104 subpaths = dict.fromkeys(ctx2.substate, ctx2)
105 105 subpaths.update(dict.fromkeys(ctx1.substate, ctx1))
106 106
107 107 missing = set()
108 108
109 109 for subpath in ctx2.substate:
110 110 if subpath not in ctx1.substate:
111 111 del subpaths[subpath]
112 112 missing.add(subpath)
113 113
114 114 for subpath, ctx in sorted(pycompat.iteritems(subpaths)):
115 115 yield subpath, ctx.sub(subpath)
116 116
117 117 # Yield an empty subrepo based on ctx1 for anything only in ctx2. That way,
118 118 # status and diff will have an accurate result when it does
119 119 # 'sub.{status|diff}(rev2)'. Otherwise, the ctx2 subrepo is compared
120 120 # against itself.
121 121 for subpath in missing:
122 122 yield subpath, ctx2.nullsub(subpath, ctx1)
123 123
124 124
125 125 def nochangesfound(ui, repo, excluded=None):
126 126 '''Report no changes for push/pull, excluded is None or a list of
127 127 nodes excluded from the push/pull.
128 128 '''
129 129 secretlist = []
130 130 if excluded:
131 131 for n in excluded:
132 132 ctx = repo[n]
133 133 if ctx.phase() >= phases.secret and not ctx.extinct():
134 134 secretlist.append(n)
135 135
136 136 if secretlist:
137 137 ui.status(
138 138 _(b"no changes found (ignored %d secret changesets)\n")
139 139 % len(secretlist)
140 140 )
141 141 else:
142 142 ui.status(_(b"no changes found\n"))
143 143
144 144
145 145 def callcatch(ui, func):
146 146 """call func() with global exception handling
147 147
148 148 return func() if no exception happens. otherwise do some error handling
149 149 and return an exit code accordingly. does not handle all exceptions.
150 150 """
151 151 coarse_exit_code = -1
152 152 detailed_exit_code = -1
153 153 try:
154 154 try:
155 155 return func()
156 156 except: # re-raises
157 157 ui.traceback()
158 158 raise
159 159 # Global exception handling, alphabetically
160 160 # Mercurial-specific first, followed by built-in and library exceptions
161 161 except error.LockHeld as inst:
162 162 detailed_exit_code = 20
163 163 if inst.errno == errno.ETIMEDOUT:
164 164 reason = _(b'timed out waiting for lock held by %r') % (
165 165 pycompat.bytestr(inst.locker)
166 166 )
167 167 else:
168 168 reason = _(b'lock held by %r') % inst.locker
169 169 ui.error(
170 170 _(b"abort: %s: %s\n")
171 171 % (inst.desc or stringutil.forcebytestr(inst.filename), reason)
172 172 )
173 173 if not inst.locker:
174 174 ui.error(_(b"(lock might be very busy)\n"))
175 175 except error.LockUnavailable as inst:
176 176 detailed_exit_code = 20
177 177 ui.error(
178 178 _(b"abort: could not lock %s: %s\n")
179 179 % (
180 180 inst.desc or stringutil.forcebytestr(inst.filename),
181 181 encoding.strtolocal(inst.strerror),
182 182 )
183 183 )
184 184 except error.OutOfBandError as inst:
185 detailed_exit_code = 100
185 186 if inst.args:
186 187 msg = _(b"abort: remote error:\n")
187 188 else:
188 189 msg = _(b"abort: remote error\n")
189 190 ui.error(msg)
190 191 if inst.args:
191 192 ui.error(b''.join(inst.args))
192 193 if inst.hint:
193 194 ui.error(b'(%s)\n' % inst.hint)
194 195 except error.RepoError as inst:
195 196 ui.error(_(b"abort: %s!\n") % inst)
196 197 if inst.hint:
197 198 ui.error(_(b"(%s)\n") % inst.hint)
198 199 except error.ResponseError as inst:
199 200 ui.error(_(b"abort: %s") % inst.args[0])
200 201 msg = inst.args[1]
201 202 if isinstance(msg, type(u'')):
202 203 msg = pycompat.sysbytes(msg)
203 204 if not isinstance(msg, bytes):
204 205 ui.error(b" %r\n" % (msg,))
205 206 elif not msg:
206 207 ui.error(_(b" empty string\n"))
207 208 else:
208 209 ui.error(b"\n%r\n" % pycompat.bytestr(stringutil.ellipsis(msg)))
209 210 except error.CensoredNodeError as inst:
210 211 ui.error(_(b"abort: file censored %s!\n") % inst)
211 212 except error.StorageError as inst:
212 213 ui.error(_(b"abort: %s!\n") % inst)
213 214 if inst.hint:
214 215 ui.error(_(b"(%s)\n") % inst.hint)
215 216 except error.InterventionRequired as inst:
216 217 ui.error(b"%s\n" % inst)
217 218 if inst.hint:
218 219 ui.error(_(b"(%s)\n") % inst.hint)
219 220 detailed_exit_code = 240
220 221 coarse_exit_code = 1
221 222 except error.WdirUnsupported:
222 223 ui.error(_(b"abort: working directory revision cannot be specified\n"))
223 224 except error.Abort as inst:
224 225 if isinstance(inst, error.InputError):
225 226 detailed_exit_code = 10
226 227 ui.error(_(b"abort: %s\n") % inst.message)
227 228 if inst.hint:
228 229 ui.error(_(b"(%s)\n") % inst.hint)
229 230 except error.WorkerError as inst:
230 231 # Don't print a message -- the worker already should have
231 232 return inst.status_code
232 233 except ImportError as inst:
233 234 ui.error(_(b"abort: %s!\n") % stringutil.forcebytestr(inst))
234 235 m = stringutil.forcebytestr(inst).split()[-1]
235 236 if m in b"mpatch bdiff".split():
236 237 ui.error(_(b"(did you forget to compile extensions?)\n"))
237 238 elif m in b"zlib".split():
238 239 ui.error(_(b"(is your Python install correct?)\n"))
239 240 except util.urlerr.httperror as inst:
241 detailed_exit_code = 100
240 242 ui.error(_(b"abort: %s\n") % stringutil.forcebytestr(inst))
241 243 except util.urlerr.urlerror as inst:
244 detailed_exit_code = 100
242 245 try: # usually it is in the form (errno, strerror)
243 246 reason = inst.reason.args[1]
244 247 except (AttributeError, IndexError):
245 248 # it might be anything, for example a string
246 249 reason = inst.reason
247 250 if isinstance(reason, pycompat.unicode):
248 251 # SSLError of Python 2.7.9 contains a unicode
249 252 reason = encoding.unitolocal(reason)
250 253 ui.error(_(b"abort: error: %s\n") % stringutil.forcebytestr(reason))
251 254 except (IOError, OSError) as inst:
252 255 if (
253 256 util.safehasattr(inst, b"args")
254 257 and inst.args
255 258 and inst.args[0] == errno.EPIPE
256 259 ):
257 260 pass
258 261 elif getattr(inst, "strerror", None): # common IOError or OSError
259 262 if getattr(inst, "filename", None) is not None:
260 263 ui.error(
261 264 _(b"abort: %s: '%s'\n")
262 265 % (
263 266 encoding.strtolocal(inst.strerror),
264 267 stringutil.forcebytestr(inst.filename),
265 268 )
266 269 )
267 270 else:
268 271 ui.error(_(b"abort: %s\n") % encoding.strtolocal(inst.strerror))
269 272 else: # suspicious IOError
270 273 raise
271 274 except MemoryError:
272 275 ui.error(_(b"abort: out of memory\n"))
273 276 except SystemExit as inst:
274 277 # Commands shouldn't sys.exit directly, but give a return code.
275 278 # Just in case catch this and and pass exit code to caller.
276 279 detailed_exit_code = 254
277 280 coarse_exit_code = inst.code
278 281
279 282 if ui.configbool(b'ui', b'detailed-exit-code'):
280 283 return detailed_exit_code
281 284 else:
282 285 return coarse_exit_code
283 286
284 287
285 288 def checknewlabel(repo, lbl, kind):
286 289 # Do not use the "kind" parameter in ui output.
287 290 # It makes strings difficult to translate.
288 291 if lbl in [b'tip', b'.', b'null']:
289 292 raise error.Abort(_(b"the name '%s' is reserved") % lbl)
290 293 for c in (b':', b'\0', b'\n', b'\r'):
291 294 if c in lbl:
292 295 raise error.Abort(
293 296 _(b"%r cannot be used in a name") % pycompat.bytestr(c)
294 297 )
295 298 try:
296 299 int(lbl)
297 300 raise error.Abort(_(b"cannot use an integer as a name"))
298 301 except ValueError:
299 302 pass
300 303 if lbl.strip() != lbl:
301 304 raise error.Abort(_(b"leading or trailing whitespace in name %r") % lbl)
302 305
303 306
304 307 def checkfilename(f):
305 308 '''Check that the filename f is an acceptable filename for a tracked file'''
306 309 if b'\r' in f or b'\n' in f:
307 310 raise error.Abort(
308 311 _(b"'\\n' and '\\r' disallowed in filenames: %r")
309 312 % pycompat.bytestr(f)
310 313 )
311 314
312 315
313 316 def checkportable(ui, f):
314 317 '''Check if filename f is portable and warn or abort depending on config'''
315 318 checkfilename(f)
316 319 abort, warn = checkportabilityalert(ui)
317 320 if abort or warn:
318 321 msg = util.checkwinfilename(f)
319 322 if msg:
320 323 msg = b"%s: %s" % (msg, procutil.shellquote(f))
321 324 if abort:
322 325 raise error.Abort(msg)
323 326 ui.warn(_(b"warning: %s\n") % msg)
324 327
325 328
326 329 def checkportabilityalert(ui):
327 330 '''check if the user's config requests nothing, a warning, or abort for
328 331 non-portable filenames'''
329 332 val = ui.config(b'ui', b'portablefilenames')
330 333 lval = val.lower()
331 334 bval = stringutil.parsebool(val)
332 335 abort = pycompat.iswindows or lval == b'abort'
333 336 warn = bval or lval == b'warn'
334 337 if bval is None and not (warn or abort or lval == b'ignore'):
335 338 raise error.ConfigError(
336 339 _(b"ui.portablefilenames value is invalid ('%s')") % val
337 340 )
338 341 return abort, warn
339 342
340 343
341 344 class casecollisionauditor(object):
342 345 def __init__(self, ui, abort, dirstate):
343 346 self._ui = ui
344 347 self._abort = abort
345 348 allfiles = b'\0'.join(dirstate)
346 349 self._loweredfiles = set(encoding.lower(allfiles).split(b'\0'))
347 350 self._dirstate = dirstate
348 351 # The purpose of _newfiles is so that we don't complain about
349 352 # case collisions if someone were to call this object with the
350 353 # same filename twice.
351 354 self._newfiles = set()
352 355
353 356 def __call__(self, f):
354 357 if f in self._newfiles:
355 358 return
356 359 fl = encoding.lower(f)
357 360 if fl in self._loweredfiles and f not in self._dirstate:
358 361 msg = _(b'possible case-folding collision for %s') % f
359 362 if self._abort:
360 363 raise error.Abort(msg)
361 364 self._ui.warn(_(b"warning: %s\n") % msg)
362 365 self._loweredfiles.add(fl)
363 366 self._newfiles.add(f)
364 367
365 368
366 369 def filteredhash(repo, maxrev):
367 370 """build hash of filtered revisions in the current repoview.
368 371
369 372 Multiple caches perform up-to-date validation by checking that the
370 373 tiprev and tipnode stored in the cache file match the current repository.
371 374 However, this is not sufficient for validating repoviews because the set
372 375 of revisions in the view may change without the repository tiprev and
373 376 tipnode changing.
374 377
375 378 This function hashes all the revs filtered from the view and returns
376 379 that SHA-1 digest.
377 380 """
378 381 cl = repo.changelog
379 382 if not cl.filteredrevs:
380 383 return None
381 384 key = cl._filteredrevs_hashcache.get(maxrev)
382 385 if not key:
383 386 revs = sorted(r for r in cl.filteredrevs if r <= maxrev)
384 387 if revs:
385 388 s = hashutil.sha1()
386 389 for rev in revs:
387 390 s.update(b'%d;' % rev)
388 391 key = s.digest()
389 392 cl._filteredrevs_hashcache[maxrev] = key
390 393 return key
391 394
392 395
393 396 def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
394 397 '''yield every hg repository under path, always recursively.
395 398 The recurse flag will only control recursion into repo working dirs'''
396 399
397 400 def errhandler(err):
398 401 if err.filename == path:
399 402 raise err
400 403
401 404 samestat = getattr(os.path, 'samestat', None)
402 405 if followsym and samestat is not None:
403 406
404 407 def adddir(dirlst, dirname):
405 408 dirstat = os.stat(dirname)
406 409 match = any(samestat(dirstat, lstdirstat) for lstdirstat in dirlst)
407 410 if not match:
408 411 dirlst.append(dirstat)
409 412 return not match
410 413
411 414 else:
412 415 followsym = False
413 416
414 417 if (seen_dirs is None) and followsym:
415 418 seen_dirs = []
416 419 adddir(seen_dirs, path)
417 420 for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler):
418 421 dirs.sort()
419 422 if b'.hg' in dirs:
420 423 yield root # found a repository
421 424 qroot = os.path.join(root, b'.hg', b'patches')
422 425 if os.path.isdir(os.path.join(qroot, b'.hg')):
423 426 yield qroot # we have a patch queue repo here
424 427 if recurse:
425 428 # avoid recursing inside the .hg directory
426 429 dirs.remove(b'.hg')
427 430 else:
428 431 dirs[:] = [] # don't descend further
429 432 elif followsym:
430 433 newdirs = []
431 434 for d in dirs:
432 435 fname = os.path.join(root, d)
433 436 if adddir(seen_dirs, fname):
434 437 if os.path.islink(fname):
435 438 for hgname in walkrepos(fname, True, seen_dirs):
436 439 yield hgname
437 440 else:
438 441 newdirs.append(d)
439 442 dirs[:] = newdirs
440 443
441 444
442 445 def binnode(ctx):
443 446 """Return binary node id for a given basectx"""
444 447 node = ctx.node()
445 448 if node is None:
446 449 return wdirid
447 450 return node
448 451
449 452
450 453 def intrev(ctx):
451 454 """Return integer for a given basectx that can be used in comparison or
452 455 arithmetic operation"""
453 456 rev = ctx.rev()
454 457 if rev is None:
455 458 return wdirrev
456 459 return rev
457 460
458 461
459 462 def formatchangeid(ctx):
460 463 """Format changectx as '{rev}:{node|formatnode}', which is the default
461 464 template provided by logcmdutil.changesettemplater"""
462 465 repo = ctx.repo()
463 466 return formatrevnode(repo.ui, intrev(ctx), binnode(ctx))
464 467
465 468
466 469 def formatrevnode(ui, rev, node):
467 470 """Format given revision and node depending on the current verbosity"""
468 471 if ui.debugflag:
469 472 hexfunc = hex
470 473 else:
471 474 hexfunc = short
472 475 return b'%d:%s' % (rev, hexfunc(node))
473 476
474 477
475 478 def resolvehexnodeidprefix(repo, prefix):
476 479 if prefix.startswith(b'x'):
477 480 prefix = prefix[1:]
478 481 try:
479 482 # Uses unfiltered repo because it's faster when prefix is ambiguous/
480 483 # This matches the shortesthexnodeidprefix() function below.
481 484 node = repo.unfiltered().changelog._partialmatch(prefix)
482 485 except error.AmbiguousPrefixLookupError:
483 486 revset = repo.ui.config(
484 487 b'experimental', b'revisions.disambiguatewithin'
485 488 )
486 489 if revset:
487 490 # Clear config to avoid infinite recursion
488 491 configoverrides = {
489 492 (b'experimental', b'revisions.disambiguatewithin'): None
490 493 }
491 494 with repo.ui.configoverride(configoverrides):
492 495 revs = repo.anyrevs([revset], user=True)
493 496 matches = []
494 497 for rev in revs:
495 498 node = repo.changelog.node(rev)
496 499 if hex(node).startswith(prefix):
497 500 matches.append(node)
498 501 if len(matches) == 1:
499 502 return matches[0]
500 503 raise
501 504 if node is None:
502 505 return
503 506 repo.changelog.rev(node) # make sure node isn't filtered
504 507 return node
505 508
506 509
507 510 def mayberevnum(repo, prefix):
508 511 """Checks if the given prefix may be mistaken for a revision number"""
509 512 try:
510 513 i = int(prefix)
511 514 # if we are a pure int, then starting with zero will not be
512 515 # confused as a rev; or, obviously, if the int is larger
513 516 # than the value of the tip rev. We still need to disambiguate if
514 517 # prefix == '0', since that *is* a valid revnum.
515 518 if (prefix != b'0' and prefix[0:1] == b'0') or i >= len(repo):
516 519 return False
517 520 return True
518 521 except ValueError:
519 522 return False
520 523
521 524
522 525 def shortesthexnodeidprefix(repo, node, minlength=1, cache=None):
523 526 """Find the shortest unambiguous prefix that matches hexnode.
524 527
525 528 If "cache" is not None, it must be a dictionary that can be used for
526 529 caching between calls to this method.
527 530 """
528 531 # _partialmatch() of filtered changelog could take O(len(repo)) time,
529 532 # which would be unacceptably slow. so we look for hash collision in
530 533 # unfiltered space, which means some hashes may be slightly longer.
531 534
532 535 minlength = max(minlength, 1)
533 536
534 537 def disambiguate(prefix):
535 538 """Disambiguate against revnums."""
536 539 if repo.ui.configbool(b'experimental', b'revisions.prefixhexnode'):
537 540 if mayberevnum(repo, prefix):
538 541 return b'x' + prefix
539 542 else:
540 543 return prefix
541 544
542 545 hexnode = hex(node)
543 546 for length in range(len(prefix), len(hexnode) + 1):
544 547 prefix = hexnode[:length]
545 548 if not mayberevnum(repo, prefix):
546 549 return prefix
547 550
548 551 cl = repo.unfiltered().changelog
549 552 revset = repo.ui.config(b'experimental', b'revisions.disambiguatewithin')
550 553 if revset:
551 554 revs = None
552 555 if cache is not None:
553 556 revs = cache.get(b'disambiguationrevset')
554 557 if revs is None:
555 558 revs = repo.anyrevs([revset], user=True)
556 559 if cache is not None:
557 560 cache[b'disambiguationrevset'] = revs
558 561 if cl.rev(node) in revs:
559 562 hexnode = hex(node)
560 563 nodetree = None
561 564 if cache is not None:
562 565 nodetree = cache.get(b'disambiguationnodetree')
563 566 if not nodetree:
564 567 if util.safehasattr(parsers, 'nodetree'):
565 568 # The CExt is the only implementation to provide a nodetree
566 569 # class so far.
567 570 index = cl.index
568 571 if util.safehasattr(index, 'get_cindex'):
569 572 # the rust wrapped need to give access to its internal index
570 573 index = index.get_cindex()
571 574 nodetree = parsers.nodetree(index, len(revs))
572 575 for r in revs:
573 576 nodetree.insert(r)
574 577 if cache is not None:
575 578 cache[b'disambiguationnodetree'] = nodetree
576 579 if nodetree is not None:
577 580 length = max(nodetree.shortest(node), minlength)
578 581 prefix = hexnode[:length]
579 582 return disambiguate(prefix)
580 583 for length in range(minlength, len(hexnode) + 1):
581 584 matches = []
582 585 prefix = hexnode[:length]
583 586 for rev in revs:
584 587 otherhexnode = repo[rev].hex()
585 588 if prefix == otherhexnode[:length]:
586 589 matches.append(otherhexnode)
587 590 if len(matches) == 1:
588 591 return disambiguate(prefix)
589 592
590 593 try:
591 594 return disambiguate(cl.shortest(node, minlength))
592 595 except error.LookupError:
593 596 raise error.RepoLookupError()
594 597
595 598
596 599 def isrevsymbol(repo, symbol):
597 600 """Checks if a symbol exists in the repo.
598 601
599 602 See revsymbol() for details. Raises error.AmbiguousPrefixLookupError if the
600 603 symbol is an ambiguous nodeid prefix.
601 604 """
602 605 try:
603 606 revsymbol(repo, symbol)
604 607 return True
605 608 except error.RepoLookupError:
606 609 return False
607 610
608 611
609 612 def revsymbol(repo, symbol):
610 613 """Returns a context given a single revision symbol (as string).
611 614
612 615 This is similar to revsingle(), but accepts only a single revision symbol,
613 616 i.e. things like ".", "tip", "1234", "deadbeef", "my-bookmark" work, but
614 617 not "max(public())".
615 618 """
616 619 if not isinstance(symbol, bytes):
617 620 msg = (
618 621 b"symbol (%s of type %s) was not a string, did you mean "
619 622 b"repo[symbol]?" % (symbol, type(symbol))
620 623 )
621 624 raise error.ProgrammingError(msg)
622 625 try:
623 626 if symbol in (b'.', b'tip', b'null'):
624 627 return repo[symbol]
625 628
626 629 try:
627 630 r = int(symbol)
628 631 if b'%d' % r != symbol:
629 632 raise ValueError
630 633 l = len(repo.changelog)
631 634 if r < 0:
632 635 r += l
633 636 if r < 0 or r >= l and r != wdirrev:
634 637 raise ValueError
635 638 return repo[r]
636 639 except error.FilteredIndexError:
637 640 raise
638 641 except (ValueError, OverflowError, IndexError):
639 642 pass
640 643
641 644 if len(symbol) == 40:
642 645 try:
643 646 node = bin(symbol)
644 647 rev = repo.changelog.rev(node)
645 648 return repo[rev]
646 649 except error.FilteredLookupError:
647 650 raise
648 651 except (TypeError, LookupError):
649 652 pass
650 653
651 654 # look up bookmarks through the name interface
652 655 try:
653 656 node = repo.names.singlenode(repo, symbol)
654 657 rev = repo.changelog.rev(node)
655 658 return repo[rev]
656 659 except KeyError:
657 660 pass
658 661
659 662 node = resolvehexnodeidprefix(repo, symbol)
660 663 if node is not None:
661 664 rev = repo.changelog.rev(node)
662 665 return repo[rev]
663 666
664 667 raise error.RepoLookupError(_(b"unknown revision '%s'") % symbol)
665 668
666 669 except error.WdirUnsupported:
667 670 return repo[None]
668 671 except (
669 672 error.FilteredIndexError,
670 673 error.FilteredLookupError,
671 674 error.FilteredRepoLookupError,
672 675 ):
673 676 raise _filterederror(repo, symbol)
674 677
675 678
676 679 def _filterederror(repo, changeid):
677 680 """build an exception to be raised about a filtered changeid
678 681
679 682 This is extracted in a function to help extensions (eg: evolve) to
680 683 experiment with various message variants."""
681 684 if repo.filtername.startswith(b'visible'):
682 685
683 686 # Check if the changeset is obsolete
684 687 unfilteredrepo = repo.unfiltered()
685 688 ctx = revsymbol(unfilteredrepo, changeid)
686 689
687 690 # If the changeset is obsolete, enrich the message with the reason
688 691 # that made this changeset not visible
689 692 if ctx.obsolete():
690 693 msg = obsutil._getfilteredreason(repo, changeid, ctx)
691 694 else:
692 695 msg = _(b"hidden revision '%s'") % changeid
693 696
694 697 hint = _(b'use --hidden to access hidden revisions')
695 698
696 699 return error.FilteredRepoLookupError(msg, hint=hint)
697 700 msg = _(b"filtered revision '%s' (not in '%s' subset)")
698 701 msg %= (changeid, repo.filtername)
699 702 return error.FilteredRepoLookupError(msg)
700 703
701 704
702 705 def revsingle(repo, revspec, default=b'.', localalias=None):
703 706 if not revspec and revspec != 0:
704 707 return repo[default]
705 708
706 709 l = revrange(repo, [revspec], localalias=localalias)
707 710 if not l:
708 711 raise error.Abort(_(b'empty revision set'))
709 712 return repo[l.last()]
710 713
711 714
712 715 def _pairspec(revspec):
713 716 tree = revsetlang.parse(revspec)
714 717 return tree and tree[0] in (
715 718 b'range',
716 719 b'rangepre',
717 720 b'rangepost',
718 721 b'rangeall',
719 722 )
720 723
721 724
722 725 def revpair(repo, revs):
723 726 if not revs:
724 727 return repo[b'.'], repo[None]
725 728
726 729 l = revrange(repo, revs)
727 730
728 731 if not l:
729 732 raise error.Abort(_(b'empty revision range'))
730 733
731 734 first = l.first()
732 735 second = l.last()
733 736
734 737 if (
735 738 first == second
736 739 and len(revs) >= 2
737 740 and not all(revrange(repo, [r]) for r in revs)
738 741 ):
739 742 raise error.Abort(_(b'empty revision on one side of range'))
740 743
741 744 # if top-level is range expression, the result must always be a pair
742 745 if first == second and len(revs) == 1 and not _pairspec(revs[0]):
743 746 return repo[first], repo[None]
744 747
745 748 return repo[first], repo[second]
746 749
747 750
748 751 def revrange(repo, specs, localalias=None):
749 752 """Execute 1 to many revsets and return the union.
750 753
751 754 This is the preferred mechanism for executing revsets using user-specified
752 755 config options, such as revset aliases.
753 756
754 757 The revsets specified by ``specs`` will be executed via a chained ``OR``
755 758 expression. If ``specs`` is empty, an empty result is returned.
756 759
757 760 ``specs`` can contain integers, in which case they are assumed to be
758 761 revision numbers.
759 762
760 763 It is assumed the revsets are already formatted. If you have arguments
761 764 that need to be expanded in the revset, call ``revsetlang.formatspec()``
762 765 and pass the result as an element of ``specs``.
763 766
764 767 Specifying a single revset is allowed.
765 768
766 769 Returns a ``smartset.abstractsmartset`` which is a list-like interface over
767 770 integer revisions.
768 771 """
769 772 allspecs = []
770 773 for spec in specs:
771 774 if isinstance(spec, int):
772 775 spec = revsetlang.formatspec(b'%d', spec)
773 776 allspecs.append(spec)
774 777 return repo.anyrevs(allspecs, user=True, localalias=localalias)
775 778
776 779
777 780 def increasingwindows(windowsize=8, sizelimit=512):
778 781 while True:
779 782 yield windowsize
780 783 if windowsize < sizelimit:
781 784 windowsize *= 2
782 785
783 786
784 787 def walkchangerevs(repo, revs, makefilematcher, prepare):
785 788 '''Iterate over files and the revs in a "windowed" way.
786 789
787 790 Callers most commonly need to iterate backwards over the history
788 791 in which they are interested. Doing so has awful (quadratic-looking)
789 792 performance, so we use iterators in a "windowed" way.
790 793
791 794 We walk a window of revisions in the desired order. Within the
792 795 window, we first walk forwards to gather data, then in the desired
793 796 order (usually backwards) to display it.
794 797
795 798 This function returns an iterator yielding contexts. Before
796 799 yielding each context, the iterator will first call the prepare
797 800 function on each context in the window in forward order.'''
798 801
799 802 if not revs:
800 803 return []
801 804 change = repo.__getitem__
802 805
803 806 def iterate():
804 807 it = iter(revs)
805 808 stopiteration = False
806 809 for windowsize in increasingwindows():
807 810 nrevs = []
808 811 for i in pycompat.xrange(windowsize):
809 812 rev = next(it, None)
810 813 if rev is None:
811 814 stopiteration = True
812 815 break
813 816 nrevs.append(rev)
814 817 for rev in sorted(nrevs):
815 818 ctx = change(rev)
816 819 prepare(ctx, makefilematcher(ctx))
817 820 for rev in nrevs:
818 821 yield change(rev)
819 822
820 823 if stopiteration:
821 824 break
822 825
823 826 return iterate()
824 827
825 828
826 829 def meaningfulparents(repo, ctx):
827 830 """Return list of meaningful (or all if debug) parentrevs for rev.
828 831
829 832 For merges (two non-nullrev revisions) both parents are meaningful.
830 833 Otherwise the first parent revision is considered meaningful if it
831 834 is not the preceding revision.
832 835 """
833 836 parents = ctx.parents()
834 837 if len(parents) > 1:
835 838 return parents
836 839 if repo.ui.debugflag:
837 840 return [parents[0], repo[nullrev]]
838 841 if parents[0].rev() >= intrev(ctx) - 1:
839 842 return []
840 843 return parents
841 844
842 845
843 846 def getuipathfn(repo, legacyrelativevalue=False, forcerelativevalue=None):
844 847 """Return a function that produced paths for presenting to the user.
845 848
846 849 The returned function takes a repo-relative path and produces a path
847 850 that can be presented in the UI.
848 851
849 852 Depending on the value of ui.relative-paths, either a repo-relative or
850 853 cwd-relative path will be produced.
851 854
852 855 legacyrelativevalue is the value to use if ui.relative-paths=legacy
853 856
854 857 If forcerelativevalue is not None, then that value will be used regardless
855 858 of what ui.relative-paths is set to.
856 859 """
857 860 if forcerelativevalue is not None:
858 861 relative = forcerelativevalue
859 862 else:
860 863 config = repo.ui.config(b'ui', b'relative-paths')
861 864 if config == b'legacy':
862 865 relative = legacyrelativevalue
863 866 else:
864 867 relative = stringutil.parsebool(config)
865 868 if relative is None:
866 869 raise error.ConfigError(
867 870 _(b"ui.relative-paths is not a boolean ('%s')") % config
868 871 )
869 872
870 873 if relative:
871 874 cwd = repo.getcwd()
872 875 if cwd != b'':
873 876 # this branch would work even if cwd == b'' (ie cwd = repo
874 877 # root), but its generality makes the returned function slower
875 878 pathto = repo.pathto
876 879 return lambda f: pathto(f, cwd)
877 880 if repo.ui.configbool(b'ui', b'slash'):
878 881 return lambda f: f
879 882 else:
880 883 return util.localpath
881 884
882 885
883 886 def subdiruipathfn(subpath, uipathfn):
884 887 '''Create a new uipathfn that treats the file as relative to subpath.'''
885 888 return lambda f: uipathfn(posixpath.join(subpath, f))
886 889
887 890
888 891 def anypats(pats, opts):
889 892 '''Checks if any patterns, including --include and --exclude were given.
890 893
891 894 Some commands (e.g. addremove) use this condition for deciding whether to
892 895 print absolute or relative paths.
893 896 '''
894 897 return bool(pats or opts.get(b'include') or opts.get(b'exclude'))
895 898
896 899
897 900 def expandpats(pats):
898 901 '''Expand bare globs when running on windows.
899 902 On posix we assume it already has already been done by sh.'''
900 903 if not util.expandglobs:
901 904 return list(pats)
902 905 ret = []
903 906 for kindpat in pats:
904 907 kind, pat = matchmod._patsplit(kindpat, None)
905 908 if kind is None:
906 909 try:
907 910 globbed = glob.glob(pat)
908 911 except re.error:
909 912 globbed = [pat]
910 913 if globbed:
911 914 ret.extend(globbed)
912 915 continue
913 916 ret.append(kindpat)
914 917 return ret
915 918
916 919
917 920 def matchandpats(
918 921 ctx, pats=(), opts=None, globbed=False, default=b'relpath', badfn=None
919 922 ):
920 923 '''Return a matcher and the patterns that were used.
921 924 The matcher will warn about bad matches, unless an alternate badfn callback
922 925 is provided.'''
923 926 if opts is None:
924 927 opts = {}
925 928 if not globbed and default == b'relpath':
926 929 pats = expandpats(pats or [])
927 930
928 931 uipathfn = getuipathfn(ctx.repo(), legacyrelativevalue=True)
929 932
930 933 def bad(f, msg):
931 934 ctx.repo().ui.warn(b"%s: %s\n" % (uipathfn(f), msg))
932 935
933 936 if badfn is None:
934 937 badfn = bad
935 938
936 939 m = ctx.match(
937 940 pats,
938 941 opts.get(b'include'),
939 942 opts.get(b'exclude'),
940 943 default,
941 944 listsubrepos=opts.get(b'subrepos'),
942 945 badfn=badfn,
943 946 )
944 947
945 948 if m.always():
946 949 pats = []
947 950 return m, pats
948 951
949 952
950 953 def match(
951 954 ctx, pats=(), opts=None, globbed=False, default=b'relpath', badfn=None
952 955 ):
953 956 '''Return a matcher that will warn about bad matches.'''
954 957 return matchandpats(ctx, pats, opts, globbed, default, badfn=badfn)[0]
955 958
956 959
957 960 def matchall(repo):
958 961 '''Return a matcher that will efficiently match everything.'''
959 962 return matchmod.always()
960 963
961 964
962 965 def matchfiles(repo, files, badfn=None):
963 966 '''Return a matcher that will efficiently match exactly these files.'''
964 967 return matchmod.exact(files, badfn=badfn)
965 968
966 969
967 970 def parsefollowlinespattern(repo, rev, pat, msg):
968 971 """Return a file name from `pat` pattern suitable for usage in followlines
969 972 logic.
970 973 """
971 974 if not matchmod.patkind(pat):
972 975 return pathutil.canonpath(repo.root, repo.getcwd(), pat)
973 976 else:
974 977 ctx = repo[rev]
975 978 m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=ctx)
976 979 files = [f for f in ctx if m(f)]
977 980 if len(files) != 1:
978 981 raise error.ParseError(msg)
979 982 return files[0]
980 983
981 984
982 985 def getorigvfs(ui, repo):
983 986 """return a vfs suitable to save 'orig' file
984 987
985 988 return None if no special directory is configured"""
986 989 origbackuppath = ui.config(b'ui', b'origbackuppath')
987 990 if not origbackuppath:
988 991 return None
989 992 return vfs.vfs(repo.wvfs.join(origbackuppath))
990 993
991 994
992 995 def backuppath(ui, repo, filepath):
993 996 '''customize where working copy backup files (.orig files) are created
994 997
995 998 Fetch user defined path from config file: [ui] origbackuppath = <path>
996 999 Fall back to default (filepath with .orig suffix) if not specified
997 1000
998 1001 filepath is repo-relative
999 1002
1000 1003 Returns an absolute path
1001 1004 '''
1002 1005 origvfs = getorigvfs(ui, repo)
1003 1006 if origvfs is None:
1004 1007 return repo.wjoin(filepath + b".orig")
1005 1008
1006 1009 origbackupdir = origvfs.dirname(filepath)
1007 1010 if not origvfs.isdir(origbackupdir) or origvfs.islink(origbackupdir):
1008 1011 ui.note(_(b'creating directory: %s\n') % origvfs.join(origbackupdir))
1009 1012
1010 1013 # Remove any files that conflict with the backup file's path
1011 1014 for f in reversed(list(pathutil.finddirs(filepath))):
1012 1015 if origvfs.isfileorlink(f):
1013 1016 ui.note(_(b'removing conflicting file: %s\n') % origvfs.join(f))
1014 1017 origvfs.unlink(f)
1015 1018 break
1016 1019
1017 1020 origvfs.makedirs(origbackupdir)
1018 1021
1019 1022 if origvfs.isdir(filepath) and not origvfs.islink(filepath):
1020 1023 ui.note(
1021 1024 _(b'removing conflicting directory: %s\n') % origvfs.join(filepath)
1022 1025 )
1023 1026 origvfs.rmtree(filepath, forcibly=True)
1024 1027
1025 1028 return origvfs.join(filepath)
1026 1029
1027 1030
1028 1031 class _containsnode(object):
1029 1032 """proxy __contains__(node) to container.__contains__ which accepts revs"""
1030 1033
1031 1034 def __init__(self, repo, revcontainer):
1032 1035 self._torev = repo.changelog.rev
1033 1036 self._revcontains = revcontainer.__contains__
1034 1037
1035 1038 def __contains__(self, node):
1036 1039 return self._revcontains(self._torev(node))
1037 1040
1038 1041
1039 1042 def cleanupnodes(
1040 1043 repo,
1041 1044 replacements,
1042 1045 operation,
1043 1046 moves=None,
1044 1047 metadata=None,
1045 1048 fixphase=False,
1046 1049 targetphase=None,
1047 1050 backup=True,
1048 1051 ):
1049 1052 """do common cleanups when old nodes are replaced by new nodes
1050 1053
1051 1054 That includes writing obsmarkers or stripping nodes, and moving bookmarks.
1052 1055 (we might also want to move working directory parent in the future)
1053 1056
1054 1057 By default, bookmark moves are calculated automatically from 'replacements',
1055 1058 but 'moves' can be used to override that. Also, 'moves' may include
1056 1059 additional bookmark moves that should not have associated obsmarkers.
1057 1060
1058 1061 replacements is {oldnode: [newnode]} or a iterable of nodes if they do not
1059 1062 have replacements. operation is a string, like "rebase".
1060 1063
1061 1064 metadata is dictionary containing metadata to be stored in obsmarker if
1062 1065 obsolescence is enabled.
1063 1066 """
1064 1067 assert fixphase or targetphase is None
1065 1068 if not replacements and not moves:
1066 1069 return
1067 1070
1068 1071 # translate mapping's other forms
1069 1072 if not util.safehasattr(replacements, b'items'):
1070 1073 replacements = {(n,): () for n in replacements}
1071 1074 else:
1072 1075 # upgrading non tuple "source" to tuple ones for BC
1073 1076 repls = {}
1074 1077 for key, value in replacements.items():
1075 1078 if not isinstance(key, tuple):
1076 1079 key = (key,)
1077 1080 repls[key] = value
1078 1081 replacements = repls
1079 1082
1080 1083 # Unfiltered repo is needed since nodes in replacements might be hidden.
1081 1084 unfi = repo.unfiltered()
1082 1085
1083 1086 # Calculate bookmark movements
1084 1087 if moves is None:
1085 1088 moves = {}
1086 1089 for oldnodes, newnodes in replacements.items():
1087 1090 for oldnode in oldnodes:
1088 1091 if oldnode in moves:
1089 1092 continue
1090 1093 if len(newnodes) > 1:
1091 1094 # usually a split, take the one with biggest rev number
1092 1095 newnode = next(unfi.set(b'max(%ln)', newnodes)).node()
1093 1096 elif len(newnodes) == 0:
1094 1097 # move bookmark backwards
1095 1098 allreplaced = []
1096 1099 for rep in replacements:
1097 1100 allreplaced.extend(rep)
1098 1101 roots = list(
1099 1102 unfi.set(b'max((::%n) - %ln)', oldnode, allreplaced)
1100 1103 )
1101 1104 if roots:
1102 1105 newnode = roots[0].node()
1103 1106 else:
1104 1107 newnode = nullid
1105 1108 else:
1106 1109 newnode = newnodes[0]
1107 1110 moves[oldnode] = newnode
1108 1111
1109 1112 allnewnodes = [n for ns in replacements.values() for n in ns]
1110 1113 toretract = {}
1111 1114 toadvance = {}
1112 1115 if fixphase:
1113 1116 precursors = {}
1114 1117 for oldnodes, newnodes in replacements.items():
1115 1118 for oldnode in oldnodes:
1116 1119 for newnode in newnodes:
1117 1120 precursors.setdefault(newnode, []).append(oldnode)
1118 1121
1119 1122 allnewnodes.sort(key=lambda n: unfi[n].rev())
1120 1123 newphases = {}
1121 1124
1122 1125 def phase(ctx):
1123 1126 return newphases.get(ctx.node(), ctx.phase())
1124 1127
1125 1128 for newnode in allnewnodes:
1126 1129 ctx = unfi[newnode]
1127 1130 parentphase = max(phase(p) for p in ctx.parents())
1128 1131 if targetphase is None:
1129 1132 oldphase = max(
1130 1133 unfi[oldnode].phase() for oldnode in precursors[newnode]
1131 1134 )
1132 1135 newphase = max(oldphase, parentphase)
1133 1136 else:
1134 1137 newphase = max(targetphase, parentphase)
1135 1138 newphases[newnode] = newphase
1136 1139 if newphase > ctx.phase():
1137 1140 toretract.setdefault(newphase, []).append(newnode)
1138 1141 elif newphase < ctx.phase():
1139 1142 toadvance.setdefault(newphase, []).append(newnode)
1140 1143
1141 1144 with repo.transaction(b'cleanup') as tr:
1142 1145 # Move bookmarks
1143 1146 bmarks = repo._bookmarks
1144 1147 bmarkchanges = []
1145 1148 for oldnode, newnode in moves.items():
1146 1149 oldbmarks = repo.nodebookmarks(oldnode)
1147 1150 if not oldbmarks:
1148 1151 continue
1149 1152 from . import bookmarks # avoid import cycle
1150 1153
1151 1154 repo.ui.debug(
1152 1155 b'moving bookmarks %r from %s to %s\n'
1153 1156 % (
1154 1157 pycompat.rapply(pycompat.maybebytestr, oldbmarks),
1155 1158 hex(oldnode),
1156 1159 hex(newnode),
1157 1160 )
1158 1161 )
1159 1162 # Delete divergent bookmarks being parents of related newnodes
1160 1163 deleterevs = repo.revs(
1161 1164 b'parents(roots(%ln & (::%n))) - parents(%n)',
1162 1165 allnewnodes,
1163 1166 newnode,
1164 1167 oldnode,
1165 1168 )
1166 1169 deletenodes = _containsnode(repo, deleterevs)
1167 1170 for name in oldbmarks:
1168 1171 bmarkchanges.append((name, newnode))
1169 1172 for b in bookmarks.divergent2delete(repo, deletenodes, name):
1170 1173 bmarkchanges.append((b, None))
1171 1174
1172 1175 if bmarkchanges:
1173 1176 bmarks.applychanges(repo, tr, bmarkchanges)
1174 1177
1175 1178 for phase, nodes in toretract.items():
1176 1179 phases.retractboundary(repo, tr, phase, nodes)
1177 1180 for phase, nodes in toadvance.items():
1178 1181 phases.advanceboundary(repo, tr, phase, nodes)
1179 1182
1180 1183 mayusearchived = repo.ui.config(b'experimental', b'cleanup-as-archived')
1181 1184 # Obsolete or strip nodes
1182 1185 if obsolete.isenabled(repo, obsolete.createmarkersopt):
1183 1186 # If a node is already obsoleted, and we want to obsolete it
1184 1187 # without a successor, skip that obssolete request since it's
1185 1188 # unnecessary. That's the "if s or not isobs(n)" check below.
1186 1189 # Also sort the node in topology order, that might be useful for
1187 1190 # some obsstore logic.
1188 1191 # NOTE: the sorting might belong to createmarkers.
1189 1192 torev = unfi.changelog.rev
1190 1193 sortfunc = lambda ns: torev(ns[0][0])
1191 1194 rels = []
1192 1195 for ns, s in sorted(replacements.items(), key=sortfunc):
1193 1196 rel = (tuple(unfi[n] for n in ns), tuple(unfi[m] for m in s))
1194 1197 rels.append(rel)
1195 1198 if rels:
1196 1199 obsolete.createmarkers(
1197 1200 repo, rels, operation=operation, metadata=metadata
1198 1201 )
1199 1202 elif phases.supportinternal(repo) and mayusearchived:
1200 1203 # this assume we do not have "unstable" nodes above the cleaned ones
1201 1204 allreplaced = set()
1202 1205 for ns in replacements.keys():
1203 1206 allreplaced.update(ns)
1204 1207 if backup:
1205 1208 from . import repair # avoid import cycle
1206 1209
1207 1210 node = min(allreplaced, key=repo.changelog.rev)
1208 1211 repair.backupbundle(
1209 1212 repo, allreplaced, allreplaced, node, operation
1210 1213 )
1211 1214 phases.retractboundary(repo, tr, phases.archived, allreplaced)
1212 1215 else:
1213 1216 from . import repair # avoid import cycle
1214 1217
1215 1218 tostrip = list(n for ns in replacements for n in ns)
1216 1219 if tostrip:
1217 1220 repair.delayedstrip(
1218 1221 repo.ui, repo, tostrip, operation, backup=backup
1219 1222 )
1220 1223
1221 1224
1222 1225 def addremove(repo, matcher, prefix, uipathfn, opts=None):
1223 1226 if opts is None:
1224 1227 opts = {}
1225 1228 m = matcher
1226 1229 dry_run = opts.get(b'dry_run')
1227 1230 try:
1228 1231 similarity = float(opts.get(b'similarity') or 0)
1229 1232 except ValueError:
1230 1233 raise error.Abort(_(b'similarity must be a number'))
1231 1234 if similarity < 0 or similarity > 100:
1232 1235 raise error.Abort(_(b'similarity must be between 0 and 100'))
1233 1236 similarity /= 100.0
1234 1237
1235 1238 ret = 0
1236 1239
1237 1240 wctx = repo[None]
1238 1241 for subpath in sorted(wctx.substate):
1239 1242 submatch = matchmod.subdirmatcher(subpath, m)
1240 1243 if opts.get(b'subrepos') or m.exact(subpath) or any(submatch.files()):
1241 1244 sub = wctx.sub(subpath)
1242 1245 subprefix = repo.wvfs.reljoin(prefix, subpath)
1243 1246 subuipathfn = subdiruipathfn(subpath, uipathfn)
1244 1247 try:
1245 1248 if sub.addremove(submatch, subprefix, subuipathfn, opts):
1246 1249 ret = 1
1247 1250 except error.LookupError:
1248 1251 repo.ui.status(
1249 1252 _(b"skipping missing subrepository: %s\n")
1250 1253 % uipathfn(subpath)
1251 1254 )
1252 1255
1253 1256 rejected = []
1254 1257
1255 1258 def badfn(f, msg):
1256 1259 if f in m.files():
1257 1260 m.bad(f, msg)
1258 1261 rejected.append(f)
1259 1262
1260 1263 badmatch = matchmod.badmatch(m, badfn)
1261 1264 added, unknown, deleted, removed, forgotten = _interestingfiles(
1262 1265 repo, badmatch
1263 1266 )
1264 1267
1265 1268 unknownset = set(unknown + forgotten)
1266 1269 toprint = unknownset.copy()
1267 1270 toprint.update(deleted)
1268 1271 for abs in sorted(toprint):
1269 1272 if repo.ui.verbose or not m.exact(abs):
1270 1273 if abs in unknownset:
1271 1274 status = _(b'adding %s\n') % uipathfn(abs)
1272 1275 label = b'ui.addremove.added'
1273 1276 else:
1274 1277 status = _(b'removing %s\n') % uipathfn(abs)
1275 1278 label = b'ui.addremove.removed'
1276 1279 repo.ui.status(status, label=label)
1277 1280
1278 1281 renames = _findrenames(
1279 1282 repo, m, added + unknown, removed + deleted, similarity, uipathfn
1280 1283 )
1281 1284
1282 1285 if not dry_run:
1283 1286 _markchanges(repo, unknown + forgotten, deleted, renames)
1284 1287
1285 1288 for f in rejected:
1286 1289 if f in m.files():
1287 1290 return 1
1288 1291 return ret
1289 1292
1290 1293
1291 1294 def marktouched(repo, files, similarity=0.0):
1292 1295 '''Assert that files have somehow been operated upon. files are relative to
1293 1296 the repo root.'''
1294 1297 m = matchfiles(repo, files, badfn=lambda x, y: rejected.append(x))
1295 1298 rejected = []
1296 1299
1297 1300 added, unknown, deleted, removed, forgotten = _interestingfiles(repo, m)
1298 1301
1299 1302 if repo.ui.verbose:
1300 1303 unknownset = set(unknown + forgotten)
1301 1304 toprint = unknownset.copy()
1302 1305 toprint.update(deleted)
1303 1306 for abs in sorted(toprint):
1304 1307 if abs in unknownset:
1305 1308 status = _(b'adding %s\n') % abs
1306 1309 else:
1307 1310 status = _(b'removing %s\n') % abs
1308 1311 repo.ui.status(status)
1309 1312
1310 1313 # TODO: We should probably have the caller pass in uipathfn and apply it to
1311 1314 # the messages above too. legacyrelativevalue=True is consistent with how
1312 1315 # it used to work.
1313 1316 uipathfn = getuipathfn(repo, legacyrelativevalue=True)
1314 1317 renames = _findrenames(
1315 1318 repo, m, added + unknown, removed + deleted, similarity, uipathfn
1316 1319 )
1317 1320
1318 1321 _markchanges(repo, unknown + forgotten, deleted, renames)
1319 1322
1320 1323 for f in rejected:
1321 1324 if f in m.files():
1322 1325 return 1
1323 1326 return 0
1324 1327
1325 1328
1326 1329 def _interestingfiles(repo, matcher):
1327 1330 '''Walk dirstate with matcher, looking for files that addremove would care
1328 1331 about.
1329 1332
1330 1333 This is different from dirstate.status because it doesn't care about
1331 1334 whether files are modified or clean.'''
1332 1335 added, unknown, deleted, removed, forgotten = [], [], [], [], []
1333 1336 audit_path = pathutil.pathauditor(repo.root, cached=True)
1334 1337
1335 1338 ctx = repo[None]
1336 1339 dirstate = repo.dirstate
1337 1340 matcher = repo.narrowmatch(matcher, includeexact=True)
1338 1341 walkresults = dirstate.walk(
1339 1342 matcher,
1340 1343 subrepos=sorted(ctx.substate),
1341 1344 unknown=True,
1342 1345 ignored=False,
1343 1346 full=False,
1344 1347 )
1345 1348 for abs, st in pycompat.iteritems(walkresults):
1346 1349 dstate = dirstate[abs]
1347 1350 if dstate == b'?' and audit_path.check(abs):
1348 1351 unknown.append(abs)
1349 1352 elif dstate != b'r' and not st:
1350 1353 deleted.append(abs)
1351 1354 elif dstate == b'r' and st:
1352 1355 forgotten.append(abs)
1353 1356 # for finding renames
1354 1357 elif dstate == b'r' and not st:
1355 1358 removed.append(abs)
1356 1359 elif dstate == b'a':
1357 1360 added.append(abs)
1358 1361
1359 1362 return added, unknown, deleted, removed, forgotten
1360 1363
1361 1364
1362 1365 def _findrenames(repo, matcher, added, removed, similarity, uipathfn):
1363 1366 '''Find renames from removed files to added ones.'''
1364 1367 renames = {}
1365 1368 if similarity > 0:
1366 1369 for old, new, score in similar.findrenames(
1367 1370 repo, added, removed, similarity
1368 1371 ):
1369 1372 if (
1370 1373 repo.ui.verbose
1371 1374 or not matcher.exact(old)
1372 1375 or not matcher.exact(new)
1373 1376 ):
1374 1377 repo.ui.status(
1375 1378 _(
1376 1379 b'recording removal of %s as rename to %s '
1377 1380 b'(%d%% similar)\n'
1378 1381 )
1379 1382 % (uipathfn(old), uipathfn(new), score * 100)
1380 1383 )
1381 1384 renames[new] = old
1382 1385 return renames
1383 1386
1384 1387
1385 1388 def _markchanges(repo, unknown, deleted, renames):
1386 1389 '''Marks the files in unknown as added, the files in deleted as removed,
1387 1390 and the files in renames as copied.'''
1388 1391 wctx = repo[None]
1389 1392 with repo.wlock():
1390 1393 wctx.forget(deleted)
1391 1394 wctx.add(unknown)
1392 1395 for new, old in pycompat.iteritems(renames):
1393 1396 wctx.copy(old, new)
1394 1397
1395 1398
1396 1399 def getrenamedfn(repo, endrev=None):
1397 1400 if copiesmod.usechangesetcentricalgo(repo):
1398 1401
1399 1402 def getrenamed(fn, rev):
1400 1403 ctx = repo[rev]
1401 1404 p1copies = ctx.p1copies()
1402 1405 if fn in p1copies:
1403 1406 return p1copies[fn]
1404 1407 p2copies = ctx.p2copies()
1405 1408 if fn in p2copies:
1406 1409 return p2copies[fn]
1407 1410 return None
1408 1411
1409 1412 return getrenamed
1410 1413
1411 1414 rcache = {}
1412 1415 if endrev is None:
1413 1416 endrev = len(repo)
1414 1417
1415 1418 def getrenamed(fn, rev):
1416 1419 '''looks up all renames for a file (up to endrev) the first
1417 1420 time the file is given. It indexes on the changerev and only
1418 1421 parses the manifest if linkrev != changerev.
1419 1422 Returns rename info for fn at changerev rev.'''
1420 1423 if fn not in rcache:
1421 1424 rcache[fn] = {}
1422 1425 fl = repo.file(fn)
1423 1426 for i in fl:
1424 1427 lr = fl.linkrev(i)
1425 1428 renamed = fl.renamed(fl.node(i))
1426 1429 rcache[fn][lr] = renamed and renamed[0]
1427 1430 if lr >= endrev:
1428 1431 break
1429 1432 if rev in rcache[fn]:
1430 1433 return rcache[fn][rev]
1431 1434
1432 1435 # If linkrev != rev (i.e. rev not found in rcache) fallback to
1433 1436 # filectx logic.
1434 1437 try:
1435 1438 return repo[rev][fn].copysource()
1436 1439 except error.LookupError:
1437 1440 return None
1438 1441
1439 1442 return getrenamed
1440 1443
1441 1444
1442 1445 def getcopiesfn(repo, endrev=None):
1443 1446 if copiesmod.usechangesetcentricalgo(repo):
1444 1447
1445 1448 def copiesfn(ctx):
1446 1449 if ctx.p2copies():
1447 1450 allcopies = ctx.p1copies().copy()
1448 1451 # There should be no overlap
1449 1452 allcopies.update(ctx.p2copies())
1450 1453 return sorted(allcopies.items())
1451 1454 else:
1452 1455 return sorted(ctx.p1copies().items())
1453 1456
1454 1457 else:
1455 1458 getrenamed = getrenamedfn(repo, endrev)
1456 1459
1457 1460 def copiesfn(ctx):
1458 1461 copies = []
1459 1462 for fn in ctx.files():
1460 1463 rename = getrenamed(fn, ctx.rev())
1461 1464 if rename:
1462 1465 copies.append((fn, rename))
1463 1466 return copies
1464 1467
1465 1468 return copiesfn
1466 1469
1467 1470
1468 1471 def dirstatecopy(ui, repo, wctx, src, dst, dryrun=False, cwd=None):
1469 1472 """Update the dirstate to reflect the intent of copying src to dst. For
1470 1473 different reasons it might not end with dst being marked as copied from src.
1471 1474 """
1472 1475 origsrc = repo.dirstate.copied(src) or src
1473 1476 if dst == origsrc: # copying back a copy?
1474 1477 if repo.dirstate[dst] not in b'mn' and not dryrun:
1475 1478 repo.dirstate.normallookup(dst)
1476 1479 else:
1477 1480 if repo.dirstate[origsrc] == b'a' and origsrc == src:
1478 1481 if not ui.quiet:
1479 1482 ui.warn(
1480 1483 _(
1481 1484 b"%s has not been committed yet, so no copy "
1482 1485 b"data will be stored for %s.\n"
1483 1486 )
1484 1487 % (repo.pathto(origsrc, cwd), repo.pathto(dst, cwd))
1485 1488 )
1486 1489 if repo.dirstate[dst] in b'?r' and not dryrun:
1487 1490 wctx.add([dst])
1488 1491 elif not dryrun:
1489 1492 wctx.copy(origsrc, dst)
1490 1493
1491 1494
1492 1495 def movedirstate(repo, newctx, match=None):
1493 1496 """Move the dirstate to newctx and adjust it as necessary.
1494 1497
1495 1498 A matcher can be provided as an optimization. It is probably a bug to pass
1496 1499 a matcher that doesn't match all the differences between the parent of the
1497 1500 working copy and newctx.
1498 1501 """
1499 1502 oldctx = repo[b'.']
1500 1503 ds = repo.dirstate
1501 1504 copies = dict(ds.copies())
1502 1505 ds.setparents(newctx.node(), nullid)
1503 1506 s = newctx.status(oldctx, match=match)
1504 1507 for f in s.modified:
1505 1508 if ds[f] == b'r':
1506 1509 # modified + removed -> removed
1507 1510 continue
1508 1511 ds.normallookup(f)
1509 1512
1510 1513 for f in s.added:
1511 1514 if ds[f] == b'r':
1512 1515 # added + removed -> unknown
1513 1516 ds.drop(f)
1514 1517 elif ds[f] != b'a':
1515 1518 ds.add(f)
1516 1519
1517 1520 for f in s.removed:
1518 1521 if ds[f] == b'a':
1519 1522 # removed + added -> normal
1520 1523 ds.normallookup(f)
1521 1524 elif ds[f] != b'r':
1522 1525 ds.remove(f)
1523 1526
1524 1527 # Merge old parent and old working dir copies
1525 1528 oldcopies = copiesmod.pathcopies(newctx, oldctx, match)
1526 1529 oldcopies.update(copies)
1527 1530 copies = {
1528 1531 dst: oldcopies.get(src, src)
1529 1532 for dst, src in pycompat.iteritems(oldcopies)
1530 1533 }
1531 1534 # Adjust the dirstate copies
1532 1535 for dst, src in pycompat.iteritems(copies):
1533 1536 if src not in newctx or dst in newctx or ds[dst] != b'a':
1534 1537 src = None
1535 1538 ds.copy(src, dst)
1536 1539 repo._quick_access_changeid_invalidate()
1537 1540
1538 1541
1539 1542 def filterrequirements(requirements):
1540 1543 """ filters the requirements into two sets:
1541 1544
1542 1545 wcreq: requirements which should be written in .hg/requires
1543 1546 storereq: which should be written in .hg/store/requires
1544 1547
1545 1548 Returns (wcreq, storereq)
1546 1549 """
1547 1550 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
1548 1551 wc, store = set(), set()
1549 1552 for r in requirements:
1550 1553 if r in requirementsmod.WORKING_DIR_REQUIREMENTS:
1551 1554 wc.add(r)
1552 1555 else:
1553 1556 store.add(r)
1554 1557 return wc, store
1555 1558 return requirements, None
1556 1559
1557 1560
1558 1561 def istreemanifest(repo):
1559 1562 """ returns whether the repository is using treemanifest or not """
1560 1563 return requirementsmod.TREEMANIFEST_REQUIREMENT in repo.requirements
1561 1564
1562 1565
1563 1566 def writereporequirements(repo, requirements=None):
1564 1567 """ writes requirements for the repo to .hg/requires """
1565 1568 if requirements:
1566 1569 repo.requirements = requirements
1567 1570 wcreq, storereq = filterrequirements(repo.requirements)
1568 1571 if wcreq is not None:
1569 1572 writerequires(repo.vfs, wcreq)
1570 1573 if storereq is not None:
1571 1574 writerequires(repo.svfs, storereq)
1572 1575
1573 1576
1574 1577 def writerequires(opener, requirements):
1575 1578 with opener(b'requires', b'w', atomictemp=True) as fp:
1576 1579 for r in sorted(requirements):
1577 1580 fp.write(b"%s\n" % r)
1578 1581
1579 1582
1580 1583 class filecachesubentry(object):
1581 1584 def __init__(self, path, stat):
1582 1585 self.path = path
1583 1586 self.cachestat = None
1584 1587 self._cacheable = None
1585 1588
1586 1589 if stat:
1587 1590 self.cachestat = filecachesubentry.stat(self.path)
1588 1591
1589 1592 if self.cachestat:
1590 1593 self._cacheable = self.cachestat.cacheable()
1591 1594 else:
1592 1595 # None means we don't know yet
1593 1596 self._cacheable = None
1594 1597
1595 1598 def refresh(self):
1596 1599 if self.cacheable():
1597 1600 self.cachestat = filecachesubentry.stat(self.path)
1598 1601
1599 1602 def cacheable(self):
1600 1603 if self._cacheable is not None:
1601 1604 return self._cacheable
1602 1605
1603 1606 # we don't know yet, assume it is for now
1604 1607 return True
1605 1608
1606 1609 def changed(self):
1607 1610 # no point in going further if we can't cache it
1608 1611 if not self.cacheable():
1609 1612 return True
1610 1613
1611 1614 newstat = filecachesubentry.stat(self.path)
1612 1615
1613 1616 # we may not know if it's cacheable yet, check again now
1614 1617 if newstat and self._cacheable is None:
1615 1618 self._cacheable = newstat.cacheable()
1616 1619
1617 1620 # check again
1618 1621 if not self._cacheable:
1619 1622 return True
1620 1623
1621 1624 if self.cachestat != newstat:
1622 1625 self.cachestat = newstat
1623 1626 return True
1624 1627 else:
1625 1628 return False
1626 1629
1627 1630 @staticmethod
1628 1631 def stat(path):
1629 1632 try:
1630 1633 return util.cachestat(path)
1631 1634 except OSError as e:
1632 1635 if e.errno != errno.ENOENT:
1633 1636 raise
1634 1637
1635 1638
1636 1639 class filecacheentry(object):
1637 1640 def __init__(self, paths, stat=True):
1638 1641 self._entries = []
1639 1642 for path in paths:
1640 1643 self._entries.append(filecachesubentry(path, stat))
1641 1644
1642 1645 def changed(self):
1643 1646 '''true if any entry has changed'''
1644 1647 for entry in self._entries:
1645 1648 if entry.changed():
1646 1649 return True
1647 1650 return False
1648 1651
1649 1652 def refresh(self):
1650 1653 for entry in self._entries:
1651 1654 entry.refresh()
1652 1655
1653 1656
1654 1657 class filecache(object):
1655 1658 """A property like decorator that tracks files under .hg/ for updates.
1656 1659
1657 1660 On first access, the files defined as arguments are stat()ed and the
1658 1661 results cached. The decorated function is called. The results are stashed
1659 1662 away in a ``_filecache`` dict on the object whose method is decorated.
1660 1663
1661 1664 On subsequent access, the cached result is used as it is set to the
1662 1665 instance dictionary.
1663 1666
1664 1667 On external property set/delete operations, the caller must update the
1665 1668 corresponding _filecache entry appropriately. Use __class__.<attr>.set()
1666 1669 instead of directly setting <attr>.
1667 1670
1668 1671 When using the property API, the cached data is always used if available.
1669 1672 No stat() is performed to check if the file has changed.
1670 1673
1671 1674 Others can muck about with the state of the ``_filecache`` dict. e.g. they
1672 1675 can populate an entry before the property's getter is called. In this case,
1673 1676 entries in ``_filecache`` will be used during property operations,
1674 1677 if available. If the underlying file changes, it is up to external callers
1675 1678 to reflect this by e.g. calling ``delattr(obj, attr)`` to remove the cached
1676 1679 method result as well as possibly calling ``del obj._filecache[attr]`` to
1677 1680 remove the ``filecacheentry``.
1678 1681 """
1679 1682
1680 1683 def __init__(self, *paths):
1681 1684 self.paths = paths
1682 1685
1683 1686 def join(self, obj, fname):
1684 1687 """Used to compute the runtime path of a cached file.
1685 1688
1686 1689 Users should subclass filecache and provide their own version of this
1687 1690 function to call the appropriate join function on 'obj' (an instance
1688 1691 of the class that its member function was decorated).
1689 1692 """
1690 1693 raise NotImplementedError
1691 1694
1692 1695 def __call__(self, func):
1693 1696 self.func = func
1694 1697 self.sname = func.__name__
1695 1698 self.name = pycompat.sysbytes(self.sname)
1696 1699 return self
1697 1700
1698 1701 def __get__(self, obj, type=None):
1699 1702 # if accessed on the class, return the descriptor itself.
1700 1703 if obj is None:
1701 1704 return self
1702 1705
1703 1706 assert self.sname not in obj.__dict__
1704 1707
1705 1708 entry = obj._filecache.get(self.name)
1706 1709
1707 1710 if entry:
1708 1711 if entry.changed():
1709 1712 entry.obj = self.func(obj)
1710 1713 else:
1711 1714 paths = [self.join(obj, path) for path in self.paths]
1712 1715
1713 1716 # We stat -before- creating the object so our cache doesn't lie if
1714 1717 # a writer modified between the time we read and stat
1715 1718 entry = filecacheentry(paths, True)
1716 1719 entry.obj = self.func(obj)
1717 1720
1718 1721 obj._filecache[self.name] = entry
1719 1722
1720 1723 obj.__dict__[self.sname] = entry.obj
1721 1724 return entry.obj
1722 1725
1723 1726 # don't implement __set__(), which would make __dict__ lookup as slow as
1724 1727 # function call.
1725 1728
1726 1729 def set(self, obj, value):
1727 1730 if self.name not in obj._filecache:
1728 1731 # we add an entry for the missing value because X in __dict__
1729 1732 # implies X in _filecache
1730 1733 paths = [self.join(obj, path) for path in self.paths]
1731 1734 ce = filecacheentry(paths, False)
1732 1735 obj._filecache[self.name] = ce
1733 1736 else:
1734 1737 ce = obj._filecache[self.name]
1735 1738
1736 1739 ce.obj = value # update cached copy
1737 1740 obj.__dict__[self.sname] = value # update copy returned by obj.x
1738 1741
1739 1742
1740 1743 def extdatasource(repo, source):
1741 1744 """Gather a map of rev -> value dict from the specified source
1742 1745
1743 1746 A source spec is treated as a URL, with a special case shell: type
1744 1747 for parsing the output from a shell command.
1745 1748
1746 1749 The data is parsed as a series of newline-separated records where
1747 1750 each record is a revision specifier optionally followed by a space
1748 1751 and a freeform string value. If the revision is known locally, it
1749 1752 is converted to a rev, otherwise the record is skipped.
1750 1753
1751 1754 Note that both key and value are treated as UTF-8 and converted to
1752 1755 the local encoding. This allows uniformity between local and
1753 1756 remote data sources.
1754 1757 """
1755 1758
1756 1759 spec = repo.ui.config(b"extdata", source)
1757 1760 if not spec:
1758 1761 raise error.Abort(_(b"unknown extdata source '%s'") % source)
1759 1762
1760 1763 data = {}
1761 1764 src = proc = None
1762 1765 try:
1763 1766 if spec.startswith(b"shell:"):
1764 1767 # external commands should be run relative to the repo root
1765 1768 cmd = spec[6:]
1766 1769 proc = subprocess.Popen(
1767 1770 procutil.tonativestr(cmd),
1768 1771 shell=True,
1769 1772 bufsize=-1,
1770 1773 close_fds=procutil.closefds,
1771 1774 stdout=subprocess.PIPE,
1772 1775 cwd=procutil.tonativestr(repo.root),
1773 1776 )
1774 1777 src = proc.stdout
1775 1778 else:
1776 1779 # treat as a URL or file
1777 1780 src = url.open(repo.ui, spec)
1778 1781 for l in src:
1779 1782 if b" " in l:
1780 1783 k, v = l.strip().split(b" ", 1)
1781 1784 else:
1782 1785 k, v = l.strip(), b""
1783 1786
1784 1787 k = encoding.tolocal(k)
1785 1788 try:
1786 1789 data[revsingle(repo, k).rev()] = encoding.tolocal(v)
1787 1790 except (error.LookupError, error.RepoLookupError):
1788 1791 pass # we ignore data for nodes that don't exist locally
1789 1792 finally:
1790 1793 if proc:
1791 1794 try:
1792 1795 proc.communicate()
1793 1796 except ValueError:
1794 1797 # This happens if we started iterating src and then
1795 1798 # get a parse error on a line. It should be safe to ignore.
1796 1799 pass
1797 1800 if src:
1798 1801 src.close()
1799 1802 if proc and proc.returncode != 0:
1800 1803 raise error.Abort(
1801 1804 _(b"extdata command '%s' failed: %s")
1802 1805 % (cmd, procutil.explainexit(proc.returncode))
1803 1806 )
1804 1807
1805 1808 return data
1806 1809
1807 1810
1808 1811 class progress(object):
1809 1812 def __init__(self, ui, updatebar, topic, unit=b"", total=None):
1810 1813 self.ui = ui
1811 1814 self.pos = 0
1812 1815 self.topic = topic
1813 1816 self.unit = unit
1814 1817 self.total = total
1815 1818 self.debug = ui.configbool(b'progress', b'debug')
1816 1819 self._updatebar = updatebar
1817 1820
1818 1821 def __enter__(self):
1819 1822 return self
1820 1823
1821 1824 def __exit__(self, exc_type, exc_value, exc_tb):
1822 1825 self.complete()
1823 1826
1824 1827 def update(self, pos, item=b"", total=None):
1825 1828 assert pos is not None
1826 1829 if total:
1827 1830 self.total = total
1828 1831 self.pos = pos
1829 1832 self._updatebar(self.topic, self.pos, item, self.unit, self.total)
1830 1833 if self.debug:
1831 1834 self._printdebug(item)
1832 1835
1833 1836 def increment(self, step=1, item=b"", total=None):
1834 1837 self.update(self.pos + step, item, total)
1835 1838
1836 1839 def complete(self):
1837 1840 self.pos = None
1838 1841 self.unit = b""
1839 1842 self.total = None
1840 1843 self._updatebar(self.topic, self.pos, b"", self.unit, self.total)
1841 1844
1842 1845 def _printdebug(self, item):
1843 1846 unit = b''
1844 1847 if self.unit:
1845 1848 unit = b' ' + self.unit
1846 1849 if item:
1847 1850 item = b' ' + item
1848 1851
1849 1852 if self.total:
1850 1853 pct = 100.0 * self.pos / self.total
1851 1854 self.ui.debug(
1852 1855 b'%s:%s %d/%d%s (%4.2f%%)\n'
1853 1856 % (self.topic, item, self.pos, self.total, unit, pct)
1854 1857 )
1855 1858 else:
1856 1859 self.ui.debug(b'%s:%s %d%s\n' % (self.topic, item, self.pos, unit))
1857 1860
1858 1861
1859 1862 def gdinitconfig(ui):
1860 1863 """helper function to know if a repo should be created as general delta
1861 1864 """
1862 1865 # experimental config: format.generaldelta
1863 1866 return ui.configbool(b'format', b'generaldelta') or ui.configbool(
1864 1867 b'format', b'usegeneraldelta'
1865 1868 )
1866 1869
1867 1870
1868 1871 def gddeltaconfig(ui):
1869 1872 """helper function to know if incoming delta should be optimised
1870 1873 """
1871 1874 # experimental config: format.generaldelta
1872 1875 return ui.configbool(b'format', b'generaldelta')
1873 1876
1874 1877
1875 1878 class simplekeyvaluefile(object):
1876 1879 """A simple file with key=value lines
1877 1880
1878 1881 Keys must be alphanumerics and start with a letter, values must not
1879 1882 contain '\n' characters"""
1880 1883
1881 1884 firstlinekey = b'__firstline'
1882 1885
1883 1886 def __init__(self, vfs, path, keys=None):
1884 1887 self.vfs = vfs
1885 1888 self.path = path
1886 1889
1887 1890 def read(self, firstlinenonkeyval=False):
1888 1891 """Read the contents of a simple key-value file
1889 1892
1890 1893 'firstlinenonkeyval' indicates whether the first line of file should
1891 1894 be treated as a key-value pair or reuturned fully under the
1892 1895 __firstline key."""
1893 1896 lines = self.vfs.readlines(self.path)
1894 1897 d = {}
1895 1898 if firstlinenonkeyval:
1896 1899 if not lines:
1897 1900 e = _(b"empty simplekeyvalue file")
1898 1901 raise error.CorruptedState(e)
1899 1902 # we don't want to include '\n' in the __firstline
1900 1903 d[self.firstlinekey] = lines[0][:-1]
1901 1904 del lines[0]
1902 1905
1903 1906 try:
1904 1907 # the 'if line.strip()' part prevents us from failing on empty
1905 1908 # lines which only contain '\n' therefore are not skipped
1906 1909 # by 'if line'
1907 1910 updatedict = dict(
1908 1911 line[:-1].split(b'=', 1) for line in lines if line.strip()
1909 1912 )
1910 1913 if self.firstlinekey in updatedict:
1911 1914 e = _(b"%r can't be used as a key")
1912 1915 raise error.CorruptedState(e % self.firstlinekey)
1913 1916 d.update(updatedict)
1914 1917 except ValueError as e:
1915 1918 raise error.CorruptedState(stringutil.forcebytestr(e))
1916 1919 return d
1917 1920
1918 1921 def write(self, data, firstline=None):
1919 1922 """Write key=>value mapping to a file
1920 1923 data is a dict. Keys must be alphanumerical and start with a letter.
1921 1924 Values must not contain newline characters.
1922 1925
1923 1926 If 'firstline' is not None, it is written to file before
1924 1927 everything else, as it is, not in a key=value form"""
1925 1928 lines = []
1926 1929 if firstline is not None:
1927 1930 lines.append(b'%s\n' % firstline)
1928 1931
1929 1932 for k, v in data.items():
1930 1933 if k == self.firstlinekey:
1931 1934 e = b"key name '%s' is reserved" % self.firstlinekey
1932 1935 raise error.ProgrammingError(e)
1933 1936 if not k[0:1].isalpha():
1934 1937 e = b"keys must start with a letter in a key-value file"
1935 1938 raise error.ProgrammingError(e)
1936 1939 if not k.isalnum():
1937 1940 e = b"invalid key name in a simple key-value file"
1938 1941 raise error.ProgrammingError(e)
1939 1942 if b'\n' in v:
1940 1943 e = b"invalid value in a simple key-value file"
1941 1944 raise error.ProgrammingError(e)
1942 1945 lines.append(b"%s=%s\n" % (k, v))
1943 1946 with self.vfs(self.path, mode=b'wb', atomictemp=True) as fp:
1944 1947 fp.write(b''.join(lines))
1945 1948
1946 1949
1947 1950 _reportobsoletedsource = [
1948 1951 b'debugobsolete',
1949 1952 b'pull',
1950 1953 b'push',
1951 1954 b'serve',
1952 1955 b'unbundle',
1953 1956 ]
1954 1957
1955 1958 _reportnewcssource = [
1956 1959 b'pull',
1957 1960 b'unbundle',
1958 1961 ]
1959 1962
1960 1963
1961 1964 def prefetchfiles(repo, revmatches):
1962 1965 """Invokes the registered file prefetch functions, allowing extensions to
1963 1966 ensure the corresponding files are available locally, before the command
1964 1967 uses them.
1965 1968
1966 1969 Args:
1967 1970 revmatches: a list of (revision, match) tuples to indicate the files to
1968 1971 fetch at each revision. If any of the match elements is None, it matches
1969 1972 all files.
1970 1973 """
1971 1974
1972 1975 def _matcher(m):
1973 1976 if m:
1974 1977 assert isinstance(m, matchmod.basematcher)
1975 1978 # The command itself will complain about files that don't exist, so
1976 1979 # don't duplicate the message.
1977 1980 return matchmod.badmatch(m, lambda fn, msg: None)
1978 1981 else:
1979 1982 return matchall(repo)
1980 1983
1981 1984 revbadmatches = [(rev, _matcher(match)) for (rev, match) in revmatches]
1982 1985
1983 1986 fileprefetchhooks(repo, revbadmatches)
1984 1987
1985 1988
1986 1989 # a list of (repo, revs, match) prefetch functions
1987 1990 fileprefetchhooks = util.hooks()
1988 1991
1989 1992 # A marker that tells the evolve extension to suppress its own reporting
1990 1993 _reportstroubledchangesets = True
1991 1994
1992 1995
1993 1996 def registersummarycallback(repo, otr, txnname=b'', as_validator=False):
1994 1997 """register a callback to issue a summary after the transaction is closed
1995 1998
1996 1999 If as_validator is true, then the callbacks are registered as transaction
1997 2000 validators instead
1998 2001 """
1999 2002
2000 2003 def txmatch(sources):
2001 2004 return any(txnname.startswith(source) for source in sources)
2002 2005
2003 2006 categories = []
2004 2007
2005 2008 def reportsummary(func):
2006 2009 """decorator for report callbacks."""
2007 2010 # The repoview life cycle is shorter than the one of the actual
2008 2011 # underlying repository. So the filtered object can die before the
2009 2012 # weakref is used leading to troubles. We keep a reference to the
2010 2013 # unfiltered object and restore the filtering when retrieving the
2011 2014 # repository through the weakref.
2012 2015 filtername = repo.filtername
2013 2016 reporef = weakref.ref(repo.unfiltered())
2014 2017
2015 2018 def wrapped(tr):
2016 2019 repo = reporef()
2017 2020 if filtername:
2018 2021 assert repo is not None # help pytype
2019 2022 repo = repo.filtered(filtername)
2020 2023 func(repo, tr)
2021 2024
2022 2025 newcat = b'%02i-txnreport' % len(categories)
2023 2026 if as_validator:
2024 2027 otr.addvalidator(newcat, wrapped)
2025 2028 else:
2026 2029 otr.addpostclose(newcat, wrapped)
2027 2030 categories.append(newcat)
2028 2031 return wrapped
2029 2032
2030 2033 @reportsummary
2031 2034 def reportchangegroup(repo, tr):
2032 2035 cgchangesets = tr.changes.get(b'changegroup-count-changesets', 0)
2033 2036 cgrevisions = tr.changes.get(b'changegroup-count-revisions', 0)
2034 2037 cgfiles = tr.changes.get(b'changegroup-count-files', 0)
2035 2038 cgheads = tr.changes.get(b'changegroup-count-heads', 0)
2036 2039 if cgchangesets or cgrevisions or cgfiles:
2037 2040 htext = b""
2038 2041 if cgheads:
2039 2042 htext = _(b" (%+d heads)") % cgheads
2040 2043 msg = _(b"added %d changesets with %d changes to %d files%s\n")
2041 2044 if as_validator:
2042 2045 msg = _(b"adding %d changesets with %d changes to %d files%s\n")
2043 2046 assert repo is not None # help pytype
2044 2047 repo.ui.status(msg % (cgchangesets, cgrevisions, cgfiles, htext))
2045 2048
2046 2049 if txmatch(_reportobsoletedsource):
2047 2050
2048 2051 @reportsummary
2049 2052 def reportobsoleted(repo, tr):
2050 2053 obsoleted = obsutil.getobsoleted(repo, tr)
2051 2054 newmarkers = len(tr.changes.get(b'obsmarkers', ()))
2052 2055 if newmarkers:
2053 2056 repo.ui.status(_(b'%i new obsolescence markers\n') % newmarkers)
2054 2057 if obsoleted:
2055 2058 msg = _(b'obsoleted %i changesets\n')
2056 2059 if as_validator:
2057 2060 msg = _(b'obsoleting %i changesets\n')
2058 2061 repo.ui.status(msg % len(obsoleted))
2059 2062
2060 2063 if obsolete.isenabled(
2061 2064 repo, obsolete.createmarkersopt
2062 2065 ) and repo.ui.configbool(
2063 2066 b'experimental', b'evolution.report-instabilities'
2064 2067 ):
2065 2068 instabilitytypes = [
2066 2069 (b'orphan', b'orphan'),
2067 2070 (b'phase-divergent', b'phasedivergent'),
2068 2071 (b'content-divergent', b'contentdivergent'),
2069 2072 ]
2070 2073
2071 2074 def getinstabilitycounts(repo):
2072 2075 filtered = repo.changelog.filteredrevs
2073 2076 counts = {}
2074 2077 for instability, revset in instabilitytypes:
2075 2078 counts[instability] = len(
2076 2079 set(obsolete.getrevs(repo, revset)) - filtered
2077 2080 )
2078 2081 return counts
2079 2082
2080 2083 oldinstabilitycounts = getinstabilitycounts(repo)
2081 2084
2082 2085 @reportsummary
2083 2086 def reportnewinstabilities(repo, tr):
2084 2087 newinstabilitycounts = getinstabilitycounts(repo)
2085 2088 for instability, revset in instabilitytypes:
2086 2089 delta = (
2087 2090 newinstabilitycounts[instability]
2088 2091 - oldinstabilitycounts[instability]
2089 2092 )
2090 2093 msg = getinstabilitymessage(delta, instability)
2091 2094 if msg:
2092 2095 repo.ui.warn(msg)
2093 2096
2094 2097 if txmatch(_reportnewcssource):
2095 2098
2096 2099 @reportsummary
2097 2100 def reportnewcs(repo, tr):
2098 2101 """Report the range of new revisions pulled/unbundled."""
2099 2102 origrepolen = tr.changes.get(b'origrepolen', len(repo))
2100 2103 unfi = repo.unfiltered()
2101 2104 if origrepolen >= len(unfi):
2102 2105 return
2103 2106
2104 2107 # Compute the bounds of new visible revisions' range.
2105 2108 revs = smartset.spanset(repo, start=origrepolen)
2106 2109 if revs:
2107 2110 minrev, maxrev = repo[revs.min()], repo[revs.max()]
2108 2111
2109 2112 if minrev == maxrev:
2110 2113 revrange = minrev
2111 2114 else:
2112 2115 revrange = b'%s:%s' % (minrev, maxrev)
2113 2116 draft = len(repo.revs(b'%ld and draft()', revs))
2114 2117 secret = len(repo.revs(b'%ld and secret()', revs))
2115 2118 if not (draft or secret):
2116 2119 msg = _(b'new changesets %s\n') % revrange
2117 2120 elif draft and secret:
2118 2121 msg = _(b'new changesets %s (%d drafts, %d secrets)\n')
2119 2122 msg %= (revrange, draft, secret)
2120 2123 elif draft:
2121 2124 msg = _(b'new changesets %s (%d drafts)\n')
2122 2125 msg %= (revrange, draft)
2123 2126 elif secret:
2124 2127 msg = _(b'new changesets %s (%d secrets)\n')
2125 2128 msg %= (revrange, secret)
2126 2129 else:
2127 2130 errormsg = b'entered unreachable condition'
2128 2131 raise error.ProgrammingError(errormsg)
2129 2132 repo.ui.status(msg)
2130 2133
2131 2134 # search new changesets directly pulled as obsolete
2132 2135 duplicates = tr.changes.get(b'revduplicates', ())
2133 2136 obsadded = unfi.revs(
2134 2137 b'(%d: + %ld) and obsolete()', origrepolen, duplicates
2135 2138 )
2136 2139 cl = repo.changelog
2137 2140 extinctadded = [r for r in obsadded if r not in cl]
2138 2141 if extinctadded:
2139 2142 # They are not just obsolete, but obsolete and invisible
2140 2143 # we call them "extinct" internally but the terms have not been
2141 2144 # exposed to users.
2142 2145 msg = b'(%d other changesets obsolete on arrival)\n'
2143 2146 repo.ui.status(msg % len(extinctadded))
2144 2147
2145 2148 @reportsummary
2146 2149 def reportphasechanges(repo, tr):
2147 2150 """Report statistics of phase changes for changesets pre-existing
2148 2151 pull/unbundle.
2149 2152 """
2150 2153 origrepolen = tr.changes.get(b'origrepolen', len(repo))
2151 2154 published = []
2152 2155 for revs, (old, new) in tr.changes.get(b'phases', []):
2153 2156 if new != phases.public:
2154 2157 continue
2155 2158 published.extend(rev for rev in revs if rev < origrepolen)
2156 2159 if not published:
2157 2160 return
2158 2161 msg = _(b'%d local changesets published\n')
2159 2162 if as_validator:
2160 2163 msg = _(b'%d local changesets will be published\n')
2161 2164 repo.ui.status(msg % len(published))
2162 2165
2163 2166
2164 2167 def getinstabilitymessage(delta, instability):
2165 2168 """function to return the message to show warning about new instabilities
2166 2169
2167 2170 exists as a separate function so that extension can wrap to show more
2168 2171 information like how to fix instabilities"""
2169 2172 if delta > 0:
2170 2173 return _(b'%i new %s changesets\n') % (delta, instability)
2171 2174
2172 2175
2173 2176 def nodesummaries(repo, nodes, maxnumnodes=4):
2174 2177 if len(nodes) <= maxnumnodes or repo.ui.verbose:
2175 2178 return b' '.join(short(h) for h in nodes)
2176 2179 first = b' '.join(short(h) for h in nodes[:maxnumnodes])
2177 2180 return _(b"%s and %d others") % (first, len(nodes) - maxnumnodes)
2178 2181
2179 2182
2180 2183 def enforcesinglehead(repo, tr, desc, accountclosed=False):
2181 2184 """check that no named branch has multiple heads"""
2182 2185 if desc in (b'strip', b'repair'):
2183 2186 # skip the logic during strip
2184 2187 return
2185 2188 visible = repo.filtered(b'visible')
2186 2189 # possible improvement: we could restrict the check to affected branch
2187 2190 bm = visible.branchmap()
2188 2191 for name in bm:
2189 2192 heads = bm.branchheads(name, closed=accountclosed)
2190 2193 if len(heads) > 1:
2191 2194 msg = _(b'rejecting multiple heads on branch "%s"')
2192 2195 msg %= name
2193 2196 hint = _(b'%d heads: %s')
2194 2197 hint %= (len(heads), nodesummaries(repo, heads))
2195 2198 raise error.Abort(msg, hint=hint)
2196 2199
2197 2200
2198 2201 def wrapconvertsink(sink):
2199 2202 """Allow extensions to wrap the sink returned by convcmd.convertsink()
2200 2203 before it is used, whether or not the convert extension was formally loaded.
2201 2204 """
2202 2205 return sink
2203 2206
2204 2207
2205 2208 def unhidehashlikerevs(repo, specs, hiddentype):
2206 2209 """parse the user specs and unhide changesets whose hash or revision number
2207 2210 is passed.
2208 2211
2209 2212 hiddentype can be: 1) 'warn': warn while unhiding changesets
2210 2213 2) 'nowarn': don't warn while unhiding changesets
2211 2214
2212 2215 returns a repo object with the required changesets unhidden
2213 2216 """
2214 2217 if not repo.filtername or not repo.ui.configbool(
2215 2218 b'experimental', b'directaccess'
2216 2219 ):
2217 2220 return repo
2218 2221
2219 2222 if repo.filtername not in (b'visible', b'visible-hidden'):
2220 2223 return repo
2221 2224
2222 2225 symbols = set()
2223 2226 for spec in specs:
2224 2227 try:
2225 2228 tree = revsetlang.parse(spec)
2226 2229 except error.ParseError: # will be reported by scmutil.revrange()
2227 2230 continue
2228 2231
2229 2232 symbols.update(revsetlang.gethashlikesymbols(tree))
2230 2233
2231 2234 if not symbols:
2232 2235 return repo
2233 2236
2234 2237 revs = _getrevsfromsymbols(repo, symbols)
2235 2238
2236 2239 if not revs:
2237 2240 return repo
2238 2241
2239 2242 if hiddentype == b'warn':
2240 2243 unfi = repo.unfiltered()
2241 2244 revstr = b", ".join([pycompat.bytestr(unfi[l]) for l in revs])
2242 2245 repo.ui.warn(
2243 2246 _(
2244 2247 b"warning: accessing hidden changesets for write "
2245 2248 b"operation: %s\n"
2246 2249 )
2247 2250 % revstr
2248 2251 )
2249 2252
2250 2253 # we have to use new filtername to separate branch/tags cache until we can
2251 2254 # disbale these cache when revisions are dynamically pinned.
2252 2255 return repo.filtered(b'visible-hidden', revs)
2253 2256
2254 2257
2255 2258 def _getrevsfromsymbols(repo, symbols):
2256 2259 """parse the list of symbols and returns a set of revision numbers of hidden
2257 2260 changesets present in symbols"""
2258 2261 revs = set()
2259 2262 unfi = repo.unfiltered()
2260 2263 unficl = unfi.changelog
2261 2264 cl = repo.changelog
2262 2265 tiprev = len(unficl)
2263 2266 allowrevnums = repo.ui.configbool(b'experimental', b'directaccess.revnums')
2264 2267 for s in symbols:
2265 2268 try:
2266 2269 n = int(s)
2267 2270 if n <= tiprev:
2268 2271 if not allowrevnums:
2269 2272 continue
2270 2273 else:
2271 2274 if n not in cl:
2272 2275 revs.add(n)
2273 2276 continue
2274 2277 except ValueError:
2275 2278 pass
2276 2279
2277 2280 try:
2278 2281 s = resolvehexnodeidprefix(unfi, s)
2279 2282 except (error.LookupError, error.WdirUnsupported):
2280 2283 s = None
2281 2284
2282 2285 if s is not None:
2283 2286 rev = unficl.rev(s)
2284 2287 if rev not in cl:
2285 2288 revs.add(rev)
2286 2289
2287 2290 return revs
2288 2291
2289 2292
2290 2293 def bookmarkrevs(repo, mark):
2291 2294 """
2292 2295 Select revisions reachable by a given bookmark
2293 2296 """
2294 2297 return repo.revs(
2295 2298 b"ancestors(bookmark(%s)) - "
2296 2299 b"ancestors(head() and not bookmark(%s)) - "
2297 2300 b"ancestors(bookmark() and not bookmark(%s))",
2298 2301 mark,
2299 2302 mark,
2300 2303 mark,
2301 2304 )
@@ -1,15 +1,15 b''
1 1 #require serve
2 2
3 3 $ hg clone http://localhost:$HGPORT/ copy
4 4 abort: * (glob)
5 [255]
5 [100]
6 6
7 7 $ test -d copy
8 8 [1]
9 9
10 10 $ "$PYTHON" "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
11 11 $ cat dumb.pid >> $DAEMON_PIDS
12 12 $ hg clone http://localhost:$HGPORT/foo copy2
13 13 abort: HTTP Error 404: * (glob)
14 [255]
14 [100]
15 15 $ killdaemons.py
@@ -1,1152 +1,1152 b''
1 1 #testcases sshv1 sshv2
2 2
3 3 #if sshv2
4 4 $ cat >> $HGRCPATH << EOF
5 5 > [experimental]
6 6 > sshpeer.advertise-v2 = true
7 7 > sshserver.support-v2 = true
8 8 > EOF
9 9 #endif
10 10
11 11 Test exchange of common information using bundle2
12 12
13 13
14 14 $ getmainid() {
15 15 > hg -R main log --template '{node}\n' --rev "$1"
16 16 > }
17 17
18 18 enable obsolescence
19 19
20 20 $ cp $HGRCPATH $TESTTMP/hgrc.orig
21 21 $ cat > $TESTTMP/bundle2-pushkey-hook.sh << EOF
22 22 > echo pushkey: lock state after \"\$HG_NAMESPACE\"
23 23 > hg debuglock
24 24 > EOF
25 25
26 26 $ cat >> $HGRCPATH << EOF
27 27 > [experimental]
28 28 > evolution.createmarkers=True
29 29 > evolution.exchange=True
30 30 > bundle2-output-capture=True
31 31 > [ui]
32 32 > ssh="$PYTHON" "$TESTDIR/dummyssh"
33 33 > [command-templates]
34 34 > log={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
35 35 > [web]
36 36 > push_ssl = false
37 37 > allow_push = *
38 38 > [phases]
39 39 > publish=False
40 40 > [hooks]
41 41 > pretxnclose.tip = hg log -r tip -T "pre-close-tip:{node|short} {phase} {bookmarks}\n"
42 42 > txnclose.tip = hg log -r tip -T "postclose-tip:{node|short} {phase} {bookmarks}\n"
43 43 > txnclose.env = sh -c "HG_LOCAL= printenv.py txnclose"
44 44 > pushkey= sh "$TESTTMP/bundle2-pushkey-hook.sh"
45 45 > EOF
46 46
47 47 The extension requires a repo (currently unused)
48 48
49 49 $ hg init main
50 50 $ cd main
51 51 $ touch a
52 52 $ hg add a
53 53 $ hg commit -m 'a'
54 54 pre-close-tip:3903775176ed draft
55 55 postclose-tip:3903775176ed draft
56 56 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
57 57
58 58 $ hg unbundle $TESTDIR/bundles/rebase.hg
59 59 adding changesets
60 60 adding manifests
61 61 adding file changes
62 62 pre-close-tip:02de42196ebe draft
63 63 added 8 changesets with 7 changes to 7 files (+3 heads)
64 64 new changesets cd010b8cd998:02de42196ebe (8 drafts)
65 65 postclose-tip:02de42196ebe draft
66 66 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=unbundle HG_TXNID=TXN:$ID$ HG_TXNNAME=unbundle
67 67 bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg (glob)
68 68 (run 'hg heads' to see heads, 'hg merge' to merge)
69 69
70 70 $ cd ..
71 71
72 72 Real world exchange
73 73 =====================
74 74
75 75 Add more obsolescence information
76 76
77 77 $ hg -R main debugobsolete -d '0 0' 1111111111111111111111111111111111111111 `getmainid 9520eea781bc`
78 78 pre-close-tip:02de42196ebe draft
79 79 1 new obsolescence markers
80 80 postclose-tip:02de42196ebe draft
81 81 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
82 82 $ hg -R main debugobsolete -d '0 0' 2222222222222222222222222222222222222222 `getmainid 24b6387c8c8c`
83 83 pre-close-tip:02de42196ebe draft
84 84 1 new obsolescence markers
85 85 postclose-tip:02de42196ebe draft
86 86 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
87 87
88 88 clone --pull
89 89
90 90 $ hg -R main phase --public cd010b8cd998
91 91 pre-close-tip:02de42196ebe draft
92 92 postclose-tip:02de42196ebe draft
93 93 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
94 94 $ hg clone main other --pull --rev 9520eea781bc
95 95 adding changesets
96 96 adding manifests
97 97 adding file changes
98 98 pre-close-tip:9520eea781bc draft
99 99 added 2 changesets with 2 changes to 2 files
100 100 1 new obsolescence markers
101 101 new changesets cd010b8cd998:9520eea781bc (1 drafts)
102 102 postclose-tip:9520eea781bc draft
103 103 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=9520eea781bcca16c1e15acc0ba14335a0e8e5ba HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
104 104 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
105 105 updating to branch default
106 106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 107 $ hg -R other log -G
108 108 @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
109 109 |
110 110 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
111 111
112 112 $ hg -R other debugobsolete
113 113 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
114 114
115 115 pull
116 116
117 117 $ hg -R main phase --public 9520eea781bc
118 118 pre-close-tip:02de42196ebe draft
119 119 postclose-tip:02de42196ebe draft
120 120 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
121 121 $ hg -R other pull -r 24b6387c8c8c
122 122 pulling from $TESTTMP/main
123 123 searching for changes
124 124 adding changesets
125 125 adding manifests
126 126 adding file changes
127 127 pre-close-tip:24b6387c8c8c draft
128 128 added 1 changesets with 1 changes to 1 files (+1 heads)
129 129 1 new obsolescence markers
130 130 new changesets 24b6387c8c8c (1 drafts)
131 131 postclose-tip:24b6387c8c8c draft
132 132 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_NODE_LAST=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
133 133 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
134 134 (run 'hg heads' to see heads, 'hg merge' to merge)
135 135 $ hg -R other log -G
136 136 o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
137 137 |
138 138 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
139 139 |/
140 140 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
141 141
142 142 $ hg -R other debugobsolete
143 143 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
144 144 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
145 145
146 146 pull empty (with phase movement)
147 147
148 148 $ hg -R main phase --public 24b6387c8c8c
149 149 pre-close-tip:02de42196ebe draft
150 150 postclose-tip:02de42196ebe draft
151 151 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
152 152 $ hg -R other pull -r 24b6387c8c8c
153 153 pulling from $TESTTMP/main
154 154 no changes found
155 155 pre-close-tip:24b6387c8c8c public
156 156 1 local changesets published
157 157 postclose-tip:24b6387c8c8c public
158 158 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
159 159 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
160 160 $ hg -R other log -G
161 161 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
162 162 |
163 163 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
164 164 |/
165 165 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
166 166
167 167 $ hg -R other debugobsolete
168 168 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
169 169 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
170 170
171 171 pull empty
172 172
173 173 $ hg -R other pull -r 24b6387c8c8c
174 174 pulling from $TESTTMP/main
175 175 no changes found
176 176 pre-close-tip:24b6387c8c8c public
177 177 postclose-tip:24b6387c8c8c public
178 178 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
179 179 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
180 180 $ hg -R other log -G
181 181 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
182 182 |
183 183 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
184 184 |/
185 185 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
186 186
187 187 $ hg -R other debugobsolete
188 188 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
189 189 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
190 190
191 191 add extra data to test their exchange during push
192 192
193 193 $ hg -R main bookmark --rev eea13746799a book_eea1
194 194 pre-close-tip:02de42196ebe draft
195 195 postclose-tip:02de42196ebe draft
196 196 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
197 197 $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a`
198 198 pre-close-tip:02de42196ebe draft
199 199 1 new obsolescence markers
200 200 postclose-tip:02de42196ebe draft
201 201 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
202 202 $ hg -R main bookmark --rev 02de42196ebe book_02de
203 203 pre-close-tip:02de42196ebe draft book_02de
204 204 postclose-tip:02de42196ebe draft book_02de
205 205 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
206 206 $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe`
207 207 pre-close-tip:02de42196ebe draft book_02de
208 208 1 new obsolescence markers
209 209 postclose-tip:02de42196ebe draft book_02de
210 210 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
211 211 $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc
212 212 pre-close-tip:02de42196ebe draft book_02de
213 213 postclose-tip:02de42196ebe draft book_02de
214 214 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
215 215 $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16`
216 216 pre-close-tip:02de42196ebe draft book_02de
217 217 1 new obsolescence markers
218 218 postclose-tip:02de42196ebe draft book_02de
219 219 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
220 220 $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd
221 221 pre-close-tip:02de42196ebe draft book_02de
222 222 postclose-tip:02de42196ebe draft book_02de
223 223 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
224 224 $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8`
225 225 pre-close-tip:02de42196ebe draft book_02de
226 226 1 new obsolescence markers
227 227 postclose-tip:02de42196ebe draft book_02de
228 228 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
229 229 $ hg -R main bookmark --rev 32af7686d403 book_32af
230 230 pre-close-tip:02de42196ebe draft book_02de
231 231 postclose-tip:02de42196ebe draft book_02de
232 232 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
233 233 $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403`
234 234 pre-close-tip:02de42196ebe draft book_02de
235 235 1 new obsolescence markers
236 236 postclose-tip:02de42196ebe draft book_02de
237 237 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
238 238
239 239 $ hg -R other bookmark --rev cd010b8cd998 book_eea1
240 240 pre-close-tip:24b6387c8c8c public
241 241 postclose-tip:24b6387c8c8c public
242 242 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
243 243 $ hg -R other bookmark --rev cd010b8cd998 book_02de
244 244 pre-close-tip:24b6387c8c8c public
245 245 postclose-tip:24b6387c8c8c public
246 246 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
247 247 $ hg -R other bookmark --rev cd010b8cd998 book_42cc
248 248 pre-close-tip:24b6387c8c8c public
249 249 postclose-tip:24b6387c8c8c public
250 250 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
251 251 $ hg -R other bookmark --rev cd010b8cd998 book_5fdd
252 252 pre-close-tip:24b6387c8c8c public
253 253 postclose-tip:24b6387c8c8c public
254 254 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
255 255 $ hg -R other bookmark --rev cd010b8cd998 book_32af
256 256 pre-close-tip:24b6387c8c8c public
257 257 postclose-tip:24b6387c8c8c public
258 258 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
259 259
260 260 $ hg -R main phase --public eea13746799a
261 261 pre-close-tip:02de42196ebe draft book_02de
262 262 postclose-tip:02de42196ebe draft book_02de
263 263 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
264 264
265 265 push
266 266 $ hg -R main push other --rev eea13746799a --bookmark book_eea1
267 267 pushing to other
268 268 searching for changes
269 269 remote: adding changesets
270 270 remote: adding manifests
271 271 remote: adding file changes
272 272 remote: pre-close-tip:eea13746799a public book_eea1
273 273 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
274 274 remote: 1 new obsolescence markers
275 275 remote: pushkey: lock state after "bookmarks"
276 276 remote: lock: free
277 277 remote: wlock: free
278 278 remote: postclose-tip:eea13746799a public book_eea1
279 279 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_NODE_LAST=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/other
280 280 updating bookmark book_eea1
281 281 pre-close-tip:02de42196ebe draft book_02de
282 282 postclose-tip:02de42196ebe draft book_02de
283 283 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
284 284 file:/*/$TESTTMP/other HG_URL=file:$TESTTMP/other (glob)
285 285 $ hg -R other log -G
286 286 o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
287 287 |\
288 288 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
289 289 | |
290 290 @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
291 291 |/
292 292 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A
293 293
294 294 $ hg -R other debugobsolete
295 295 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
296 296 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
297 297 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
298 298
299 299 pull over ssh
300 300
301 301 $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de
302 302 pulling from ssh://user@dummy/main
303 303 searching for changes
304 304 adding changesets
305 305 adding manifests
306 306 adding file changes
307 307 updating bookmark book_02de
308 308 pre-close-tip:02de42196ebe draft book_02de
309 309 added 1 changesets with 1 changes to 1 files (+1 heads)
310 310 1 new obsolescence markers
311 311 new changesets 02de42196ebe (1 drafts)
312 312 postclose-tip:02de42196ebe draft book_02de
313 313 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
314 314 ssh://user@dummy/main HG_URL=ssh://user@dummy/main
315 315 (run 'hg heads' to see heads, 'hg merge' to merge)
316 316 $ hg -R other debugobsolete
317 317 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
318 318 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
319 319 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
320 320 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
321 321
322 322 pull over http
323 323
324 324 $ hg serve -R main -p $HGPORT -d --pid-file=main.pid -E main-error.log
325 325 $ cat main.pid >> $DAEMON_PIDS
326 326
327 327 $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc
328 328 pulling from http://localhost:$HGPORT/
329 329 searching for changes
330 330 adding changesets
331 331 adding manifests
332 332 adding file changes
333 333 updating bookmark book_42cc
334 334 pre-close-tip:42ccdea3bb16 draft book_42cc
335 335 added 1 changesets with 1 changes to 1 files (+1 heads)
336 336 1 new obsolescence markers
337 337 new changesets 42ccdea3bb16 (1 drafts)
338 338 postclose-tip:42ccdea3bb16 draft book_42cc
339 339 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_NODE_LAST=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
340 340 http://localhost:$HGPORT/ HG_URL=http://localhost:$HGPORT/
341 341 (run 'hg heads .' to see heads, 'hg merge' to merge)
342 342 $ cat main-error.log
343 343 $ hg -R other debugobsolete
344 344 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
345 345 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
346 346 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
347 347 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
348 348 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
349 349
350 350 push over ssh
351 351
352 352 $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd
353 353 pushing to ssh://user@dummy/other
354 354 searching for changes
355 355 remote: adding changesets
356 356 remote: adding manifests
357 357 remote: adding file changes
358 358 remote: pre-close-tip:5fddd98957c8 draft book_5fdd
359 359 remote: added 1 changesets with 1 changes to 1 files
360 360 remote: 1 new obsolescence markers
361 361 remote: pushkey: lock state after "bookmarks"
362 362 remote: lock: free
363 363 remote: wlock: free
364 364 remote: postclose-tip:5fddd98957c8 draft book_5fdd
365 365 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_NODE_LAST=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:ssh:$LOCALIP
366 366 updating bookmark book_5fdd
367 367 pre-close-tip:02de42196ebe draft book_02de
368 368 postclose-tip:02de42196ebe draft book_02de
369 369 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
370 370 ssh://user@dummy/other HG_URL=ssh://user@dummy/other
371 371 $ hg -R other log -G
372 372 o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
373 373 |
374 374 o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
375 375 |
376 376 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
377 377 | |
378 378 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
379 379 | |/|
380 380 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
381 381 |/ /
382 382 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
383 383 |/
384 384 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A
385 385
386 386 $ hg -R other debugobsolete
387 387 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
388 388 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
389 389 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
390 390 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
391 391 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
392 392 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
393 393
394 394 push over http
395 395
396 396 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
397 397 $ cat other.pid >> $DAEMON_PIDS
398 398
399 399 $ hg -R main phase --public 32af7686d403
400 400 pre-close-tip:02de42196ebe draft book_02de
401 401 postclose-tip:02de42196ebe draft book_02de
402 402 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
403 403 $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af
404 404 pushing to http://localhost:$HGPORT2/
405 405 searching for changes
406 406 remote: adding changesets
407 407 remote: adding manifests
408 408 remote: adding file changes
409 409 remote: pre-close-tip:32af7686d403 public book_32af
410 410 remote: added 1 changesets with 1 changes to 1 files
411 411 remote: 1 new obsolescence markers
412 412 remote: pushkey: lock state after "bookmarks"
413 413 remote: lock: free
414 414 remote: wlock: free
415 415 remote: postclose-tip:32af7686d403 public book_32af
416 416 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=32af7686d403cf45b5d95f2d70cebea587ac806a HG_NODE_LAST=32af7686d403cf45b5d95f2d70cebea587ac806a HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:http:$LOCALIP: (glob)
417 417 updating bookmark book_32af
418 418 pre-close-tip:02de42196ebe draft book_02de
419 419 postclose-tip:02de42196ebe draft book_02de
420 420 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
421 421 http://localhost:$HGPORT2/ HG_URL=http://localhost:$HGPORT2/
422 422 $ cat other-error.log
423 423
424 424 Check final content.
425 425
426 426 $ hg -R other log -G
427 427 o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D
428 428 |
429 429 o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
430 430 |
431 431 o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
432 432 |
433 433 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
434 434 | |
435 435 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
436 436 | |/|
437 437 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
438 438 |/ /
439 439 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
440 440 |/
441 441 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
442 442
443 443 $ hg -R other debugobsolete
444 444 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
445 445 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
446 446 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
447 447 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
448 448 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
449 449 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
450 450 7777777777777777777777777777777777777777 32af7686d403cf45b5d95f2d70cebea587ac806a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
451 451
452 452 (check that no 'pending' files remain)
453 453
454 454 $ ls -1 other/.hg/bookmarks*
455 455 other/.hg/bookmarks
456 456 $ ls -1 other/.hg/store/phaseroots*
457 457 other/.hg/store/phaseroots
458 458 $ ls -1 other/.hg/store/00changelog.i*
459 459 other/.hg/store/00changelog.i
460 460
461 461 Error Handling
462 462 ==============
463 463
464 464 Check that errors are properly returned to the client during push.
465 465
466 466 Setting up
467 467
468 468 $ cat > failpush.py << EOF
469 469 > """A small extension that makes push fails when using bundle2
470 470 >
471 471 > used to test error handling in bundle2
472 472 > """
473 473 >
474 474 > from mercurial import error
475 475 > from mercurial import bundle2
476 476 > from mercurial import exchange
477 477 > from mercurial import extensions
478 478 > from mercurial import registrar
479 479 > cmdtable = {}
480 480 > command = registrar.command(cmdtable)
481 481 >
482 482 > configtable = {}
483 483 > configitem = registrar.configitem(configtable)
484 484 > configitem(b'failpush', b'reason',
485 485 > default=None,
486 486 > )
487 487 >
488 488 > def _pushbundle2failpart(pushop, bundler):
489 489 > reason = pushop.ui.config(b'failpush', b'reason')
490 490 > part = None
491 491 > if reason == b'abort':
492 492 > bundler.newpart(b'test:abort')
493 493 > if reason == b'unknown':
494 494 > bundler.newpart(b'test:unknown')
495 495 > if reason == b'race':
496 496 > # 20 Bytes of crap
497 497 > bundler.newpart(b'check:heads', data=b'01234567890123456789')
498 498 >
499 499 > @bundle2.parthandler(b"test:abort")
500 500 > def handleabort(op, part):
501 501 > raise error.Abort(b'Abandon ship!', hint=b"don't panic")
502 502 >
503 503 > def uisetup(ui):
504 504 > exchange.b2partsgenmapping[b'failpart'] = _pushbundle2failpart
505 505 > exchange.b2partsgenorder.insert(0, b'failpart')
506 506 >
507 507 > EOF
508 508
509 509 $ cd main
510 510 $ hg up tip
511 511 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
512 512 $ echo 'I' > I
513 513 $ hg add I
514 514 $ hg ci -m 'I'
515 515 pre-close-tip:e7ec4e813ba6 draft
516 516 postclose-tip:e7ec4e813ba6 draft
517 517 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
518 518 $ hg id
519 519 e7ec4e813ba6 tip
520 520 $ cd ..
521 521
522 522 $ cat << EOF >> $HGRCPATH
523 523 > [extensions]
524 524 > failpush=$TESTTMP/failpush.py
525 525 > EOF
526 526
527 527 $ killdaemons.py
528 528 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
529 529 $ cat other.pid >> $DAEMON_PIDS
530 530
531 531 Doing the actual push: Abort error
532 532
533 533 $ cat << EOF >> $HGRCPATH
534 534 > [failpush]
535 535 > reason = abort
536 536 > EOF
537 537
538 538 $ hg -R main push other -r e7ec4e813ba6
539 539 pushing to other
540 540 searching for changes
541 541 abort: Abandon ship!
542 542 (don't panic)
543 543 [255]
544 544
545 545 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
546 546 pushing to ssh://user@dummy/other
547 547 searching for changes
548 548 remote: Abandon ship!
549 549 remote: (don't panic)
550 550 abort: push failed on remote
551 551 [255]
552 552
553 553 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
554 554 pushing to http://localhost:$HGPORT2/
555 555 searching for changes
556 556 remote: Abandon ship!
557 557 remote: (don't panic)
558 558 abort: push failed on remote
559 559 [255]
560 560
561 561
562 562 Doing the actual push: unknown mandatory parts
563 563
564 564 $ cat << EOF >> $HGRCPATH
565 565 > [failpush]
566 566 > reason = unknown
567 567 > EOF
568 568
569 569 $ hg -R main push other -r e7ec4e813ba6
570 570 pushing to other
571 571 searching for changes
572 572 abort: missing support for test:unknown
573 573 [255]
574 574
575 575 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
576 576 pushing to ssh://user@dummy/other
577 577 searching for changes
578 578 abort: missing support for test:unknown
579 579 [255]
580 580
581 581 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
582 582 pushing to http://localhost:$HGPORT2/
583 583 searching for changes
584 584 abort: missing support for test:unknown
585 585 [255]
586 586
587 587 Doing the actual push: race
588 588
589 589 $ cat << EOF >> $HGRCPATH
590 590 > [failpush]
591 591 > reason = race
592 592 > EOF
593 593
594 594 $ hg -R main push other -r e7ec4e813ba6
595 595 pushing to other
596 596 searching for changes
597 597 abort: push failed:
598 598 'remote repository changed while pushing - please try again'
599 599 [255]
600 600
601 601 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
602 602 pushing to ssh://user@dummy/other
603 603 searching for changes
604 604 abort: push failed:
605 605 'remote repository changed while pushing - please try again'
606 606 [255]
607 607
608 608 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
609 609 pushing to http://localhost:$HGPORT2/
610 610 searching for changes
611 611 abort: push failed:
612 612 'remote repository changed while pushing - please try again'
613 613 [255]
614 614
615 615 Doing the actual push: hook abort
616 616
617 617 $ cat << EOF >> $HGRCPATH
618 618 > [failpush]
619 619 > reason =
620 620 > [hooks]
621 621 > pretxnclose.failpush = sh -c "echo 'You shall not pass!'; false"
622 622 > txnabort.failpush = sh -c "echo 'Cleaning up the mess...'"
623 623 > EOF
624 624
625 625 $ killdaemons.py
626 626 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
627 627 $ cat other.pid >> $DAEMON_PIDS
628 628
629 629 $ hg -R main push other -r e7ec4e813ba6
630 630 pushing to other
631 631 searching for changes
632 632 remote: adding changesets
633 633 remote: adding manifests
634 634 remote: adding file changes
635 635 remote: pre-close-tip:e7ec4e813ba6 draft
636 636 remote: You shall not pass!
637 637 remote: transaction abort!
638 638 remote: Cleaning up the mess...
639 639 remote: rollback completed
640 640 abort: pretxnclose.failpush hook exited with status 1
641 641 [255]
642 642
643 643 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
644 644 pushing to ssh://user@dummy/other
645 645 searching for changes
646 646 remote: adding changesets
647 647 remote: adding manifests
648 648 remote: adding file changes
649 649 remote: pre-close-tip:e7ec4e813ba6 draft
650 650 remote: You shall not pass!
651 651 remote: transaction abort!
652 652 remote: Cleaning up the mess...
653 653 remote: rollback completed
654 654 remote: pretxnclose.failpush hook exited with status 1
655 655 abort: push failed on remote
656 656 [255]
657 657
658 658 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
659 659 pushing to http://localhost:$HGPORT2/
660 660 searching for changes
661 661 remote: adding changesets
662 662 remote: adding manifests
663 663 remote: adding file changes
664 664 remote: pre-close-tip:e7ec4e813ba6 draft
665 665 remote: You shall not pass!
666 666 remote: transaction abort!
667 667 remote: Cleaning up the mess...
668 668 remote: rollback completed
669 669 remote: pretxnclose.failpush hook exited with status 1
670 670 abort: push failed on remote
671 671 [255]
672 672
673 673 (check that no 'pending' files remain)
674 674
675 675 $ ls -1 other/.hg/bookmarks*
676 676 other/.hg/bookmarks
677 677 $ ls -1 other/.hg/store/phaseroots*
678 678 other/.hg/store/phaseroots
679 679 $ ls -1 other/.hg/store/00changelog.i*
680 680 other/.hg/store/00changelog.i
681 681
682 682 Check error from hook during the unbundling process itself
683 683
684 684 $ cat << EOF >> $HGRCPATH
685 685 > pretxnchangegroup = sh -c "echo 'Fail early!'; false"
686 686 > EOF
687 687 $ killdaemons.py # reload http config
688 688 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
689 689 $ cat other.pid >> $DAEMON_PIDS
690 690
691 691 $ hg -R main push other -r e7ec4e813ba6
692 692 pushing to other
693 693 searching for changes
694 694 remote: adding changesets
695 695 remote: adding manifests
696 696 remote: adding file changes
697 697 remote: Fail early!
698 698 remote: transaction abort!
699 699 remote: Cleaning up the mess...
700 700 remote: rollback completed
701 701 abort: pretxnchangegroup hook exited with status 1
702 702 [255]
703 703 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
704 704 pushing to ssh://user@dummy/other
705 705 searching for changes
706 706 remote: adding changesets
707 707 remote: adding manifests
708 708 remote: adding file changes
709 709 remote: Fail early!
710 710 remote: transaction abort!
711 711 remote: Cleaning up the mess...
712 712 remote: rollback completed
713 713 remote: pretxnchangegroup hook exited with status 1
714 714 abort: push failed on remote
715 715 [255]
716 716 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
717 717 pushing to http://localhost:$HGPORT2/
718 718 searching for changes
719 719 remote: adding changesets
720 720 remote: adding manifests
721 721 remote: adding file changes
722 722 remote: Fail early!
723 723 remote: transaction abort!
724 724 remote: Cleaning up the mess...
725 725 remote: rollback completed
726 726 remote: pretxnchangegroup hook exited with status 1
727 727 abort: push failed on remote
728 728 [255]
729 729
730 730 Check output capture control.
731 731
732 732 (should be still forced for http, disabled for local and ssh)
733 733
734 734 $ cat >> $HGRCPATH << EOF
735 735 > [experimental]
736 736 > bundle2-output-capture=False
737 737 > EOF
738 738
739 739 $ hg -R main push other -r e7ec4e813ba6
740 740 pushing to other
741 741 searching for changes
742 742 adding changesets
743 743 adding manifests
744 744 adding file changes
745 745 Fail early!
746 746 transaction abort!
747 747 Cleaning up the mess...
748 748 rollback completed
749 749 abort: pretxnchangegroup hook exited with status 1
750 750 [255]
751 751 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
752 752 pushing to ssh://user@dummy/other
753 753 searching for changes
754 754 remote: adding changesets
755 755 remote: adding manifests
756 756 remote: adding file changes
757 757 remote: Fail early!
758 758 remote: transaction abort!
759 759 remote: Cleaning up the mess...
760 760 remote: rollback completed
761 761 remote: pretxnchangegroup hook exited with status 1
762 762 abort: push failed on remote
763 763 [255]
764 764 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
765 765 pushing to http://localhost:$HGPORT2/
766 766 searching for changes
767 767 remote: adding changesets
768 768 remote: adding manifests
769 769 remote: adding file changes
770 770 remote: Fail early!
771 771 remote: transaction abort!
772 772 remote: Cleaning up the mess...
773 773 remote: rollback completed
774 774 remote: pretxnchangegroup hook exited with status 1
775 775 abort: push failed on remote
776 776 [255]
777 777
778 778 Check abort from mandatory pushkey
779 779
780 780 $ cat > mandatorypart.py << EOF
781 781 > from mercurial import exchange
782 782 > from mercurial import pushkey
783 783 > from mercurial import node
784 784 > from mercurial import error
785 785 > @exchange.b2partsgenerator(b'failingpuskey')
786 786 > def addfailingpushey(pushop, bundler):
787 787 > enc = pushkey.encode
788 788 > part = bundler.newpart(b'pushkey')
789 789 > part.addparam(b'namespace', enc(b'phases'))
790 790 > part.addparam(b'key', enc(b'cd010b8cd998f3981a5a8115f94f8da4ab506089'))
791 791 > part.addparam(b'old', enc(b'0')) # successful update
792 792 > part.addparam(b'new', enc(b'0'))
793 793 > def fail(pushop, exc):
794 794 > raise error.Abort(b'Correct phase push failed (because hooks)')
795 795 > pushop.pkfailcb[part.id] = fail
796 796 > EOF
797 797 $ cat >> $HGRCPATH << EOF
798 798 > [hooks]
799 799 > pretxnchangegroup=
800 800 > pretxnclose.failpush=
801 801 > prepushkey.failpush = sh -c "echo 'do not push the key !'; false"
802 802 > [extensions]
803 803 > mandatorypart=$TESTTMP/mandatorypart.py
804 804 > EOF
805 805 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config
806 806 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
807 807 $ cat other.pid >> $DAEMON_PIDS
808 808
809 809 (Failure from a hook)
810 810
811 811 $ hg -R main push other -r e7ec4e813ba6
812 812 pushing to other
813 813 searching for changes
814 814 adding changesets
815 815 adding manifests
816 816 adding file changes
817 817 do not push the key !
818 818 pushkey-abort: prepushkey.failpush hook exited with status 1
819 819 transaction abort!
820 820 Cleaning up the mess...
821 821 rollback completed
822 822 abort: Correct phase push failed (because hooks)
823 823 [255]
824 824 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
825 825 pushing to ssh://user@dummy/other
826 826 searching for changes
827 827 remote: adding changesets
828 828 remote: adding manifests
829 829 remote: adding file changes
830 830 remote: do not push the key !
831 831 remote: pushkey-abort: prepushkey.failpush hook exited with status 1
832 832 remote: transaction abort!
833 833 remote: Cleaning up the mess...
834 834 remote: rollback completed
835 835 abort: Correct phase push failed (because hooks)
836 836 [255]
837 837 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
838 838 pushing to http://localhost:$HGPORT2/
839 839 searching for changes
840 840 remote: adding changesets
841 841 remote: adding manifests
842 842 remote: adding file changes
843 843 remote: do not push the key !
844 844 remote: pushkey-abort: prepushkey.failpush hook exited with status 1
845 845 remote: transaction abort!
846 846 remote: Cleaning up the mess...
847 847 remote: rollback completed
848 848 abort: Correct phase push failed (because hooks)
849 849 [255]
850 850
851 851 (Failure from a the pushkey)
852 852
853 853 $ cat > mandatorypart.py << EOF
854 854 > from mercurial import exchange
855 855 > from mercurial import pushkey
856 856 > from mercurial import node
857 857 > from mercurial import error
858 858 > @exchange.b2partsgenerator(b'failingpuskey')
859 859 > def addfailingpushey(pushop, bundler):
860 860 > enc = pushkey.encode
861 861 > part = bundler.newpart(b'pushkey')
862 862 > part.addparam(b'namespace', enc(b'phases'))
863 863 > part.addparam(b'key', enc(b'cd010b8cd998f3981a5a8115f94f8da4ab506089'))
864 864 > part.addparam(b'old', enc(b'4')) # will fail
865 865 > part.addparam(b'new', enc(b'3'))
866 866 > def fail(pushop, exc):
867 867 > raise error.Abort(b'Clown phase push failed')
868 868 > pushop.pkfailcb[part.id] = fail
869 869 > EOF
870 870 $ cat >> $HGRCPATH << EOF
871 871 > [hooks]
872 872 > prepushkey.failpush =
873 873 > EOF
874 874 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config
875 875 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
876 876 $ cat other.pid >> $DAEMON_PIDS
877 877
878 878 $ hg -R main push other -r e7ec4e813ba6
879 879 pushing to other
880 880 searching for changes
881 881 adding changesets
882 882 adding manifests
883 883 adding file changes
884 884 transaction abort!
885 885 Cleaning up the mess...
886 886 rollback completed
887 887 pushkey: lock state after "phases"
888 888 lock: free
889 889 wlock: free
890 890 abort: Clown phase push failed
891 891 [255]
892 892 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
893 893 pushing to ssh://user@dummy/other
894 894 searching for changes
895 895 remote: adding changesets
896 896 remote: adding manifests
897 897 remote: adding file changes
898 898 remote: transaction abort!
899 899 remote: Cleaning up the mess...
900 900 remote: rollback completed
901 901 remote: pushkey: lock state after "phases"
902 902 remote: lock: free
903 903 remote: wlock: free
904 904 abort: Clown phase push failed
905 905 [255]
906 906 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
907 907 pushing to http://localhost:$HGPORT2/
908 908 searching for changes
909 909 remote: adding changesets
910 910 remote: adding manifests
911 911 remote: adding file changes
912 912 remote: transaction abort!
913 913 remote: Cleaning up the mess...
914 914 remote: rollback completed
915 915 remote: pushkey: lock state after "phases"
916 916 remote: lock: free
917 917 remote: wlock: free
918 918 abort: Clown phase push failed
919 919 [255]
920 920
921 921 Test lazily acquiring the lock during unbundle
922 922 $ cp $TESTTMP/hgrc.orig $HGRCPATH
923 923 $ cat >> $HGRCPATH <<EOF
924 924 > [ui]
925 925 > ssh="$PYTHON" "$TESTDIR/dummyssh"
926 926 > EOF
927 927
928 928 $ cat >> $TESTTMP/locktester.py <<EOF
929 929 > import os
930 930 > from mercurial import bundle2, error, extensions
931 931 > def checklock(orig, repo, *args, **kwargs):
932 932 > if repo.svfs.lexists(b"lock"):
933 933 > raise error.Abort(b"Lock should not be taken")
934 934 > return orig(repo, *args, **kwargs)
935 935 > def extsetup(ui):
936 936 > extensions.wrapfunction(bundle2, b'processbundle', checklock)
937 937 > EOF
938 938
939 939 $ hg init lazylock
940 940 $ cat >> lazylock/.hg/hgrc <<EOF
941 941 > [extensions]
942 942 > locktester=$TESTTMP/locktester.py
943 943 > EOF
944 944
945 945 $ hg clone -q ssh://user@dummy/lazylock lazylockclient
946 946 $ cd lazylockclient
947 947 $ touch a && hg ci -Aqm a
948 948 $ hg push
949 949 pushing to ssh://user@dummy/lazylock
950 950 searching for changes
951 951 remote: Lock should not be taken
952 952 abort: push failed on remote
953 953 [255]
954 954
955 955 $ cat >> ../lazylock/.hg/hgrc <<EOF
956 956 > [experimental]
957 957 > bundle2lazylocking=True
958 958 > EOF
959 959 $ hg push
960 960 pushing to ssh://user@dummy/lazylock
961 961 searching for changes
962 962 remote: adding changesets
963 963 remote: adding manifests
964 964 remote: adding file changes
965 965 remote: added 1 changesets with 1 changes to 1 files
966 966
967 967 $ cd ..
968 968
969 969 Servers can disable bundle1 for clone/pull operations
970 970
971 971 $ killdaemons.py
972 972 $ hg init bundle2onlyserver
973 973 $ cd bundle2onlyserver
974 974 $ cat > .hg/hgrc << EOF
975 975 > [server]
976 976 > bundle1.pull = false
977 977 > EOF
978 978
979 979 $ touch foo
980 980 $ hg -q commit -A -m initial
981 981
982 982 $ hg serve -p $HGPORT -d --pid-file=hg.pid
983 983 $ cat hg.pid >> $DAEMON_PIDS
984 984
985 985 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
986 986 requesting all changes
987 987 abort: remote error:
988 988 incompatible Mercurial client; bundle2 required
989 989 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
990 [255]
990 [100]
991 991 $ killdaemons.py
992 992 $ cd ..
993 993
994 994 bundle1 can still pull non-generaldelta repos when generaldelta bundle1 disabled
995 995
996 996 $ hg --config format.usegeneraldelta=false init notgdserver
997 997 $ cd notgdserver
998 998 $ cat > .hg/hgrc << EOF
999 999 > [server]
1000 1000 > bundle1gd.pull = false
1001 1001 > EOF
1002 1002
1003 1003 $ touch foo
1004 1004 $ hg -q commit -A -m initial
1005 1005 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1006 1006 $ cat hg.pid >> $DAEMON_PIDS
1007 1007
1008 1008 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-1
1009 1009 requesting all changes
1010 1010 adding changesets
1011 1011 adding manifests
1012 1012 adding file changes
1013 1013 added 1 changesets with 1 changes to 1 files
1014 1014 new changesets 96ee1d7354c4
1015 1015 updating to branch default
1016 1016 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1017 1017
1018 1018 $ killdaemons.py
1019 1019 $ cd ../bundle2onlyserver
1020 1020
1021 1021 bundle1 pull can be disabled for generaldelta repos only
1022 1022
1023 1023 $ cat > .hg/hgrc << EOF
1024 1024 > [server]
1025 1025 > bundle1gd.pull = false
1026 1026 > EOF
1027 1027
1028 1028 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1029 1029 $ cat hg.pid >> $DAEMON_PIDS
1030 1030 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
1031 1031 requesting all changes
1032 1032 abort: remote error:
1033 1033 incompatible Mercurial client; bundle2 required
1034 1034 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1035 [255]
1035 [100]
1036 1036
1037 1037 $ killdaemons.py
1038 1038
1039 1039 Verify the global server.bundle1 option works
1040 1040
1041 1041 $ cd ..
1042 1042 $ cat > bundle2onlyserver/.hg/hgrc << EOF
1043 1043 > [server]
1044 1044 > bundle1 = false
1045 1045 > EOF
1046 1046 $ hg serve -R bundle2onlyserver -p $HGPORT -d --pid-file=hg.pid
1047 1047 $ cat hg.pid >> $DAEMON_PIDS
1048 1048 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT not-bundle2
1049 1049 requesting all changes
1050 1050 abort: remote error:
1051 1051 incompatible Mercurial client; bundle2 required
1052 1052 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1053 [255]
1053 [100]
1054 1054 $ killdaemons.py
1055 1055
1056 1056 $ hg --config devel.legacy.exchange=bundle1 clone ssh://user@dummy/bundle2onlyserver not-bundle2-ssh
1057 1057 requesting all changes
1058 1058 adding changesets
1059 1059 remote: abort: incompatible Mercurial client; bundle2 required
1060 1060 remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1061 1061 transaction abort!
1062 1062 rollback completed
1063 1063 abort: stream ended unexpectedly (got 0 bytes, expected 4)
1064 1064 [255]
1065 1065
1066 1066 $ cat > bundle2onlyserver/.hg/hgrc << EOF
1067 1067 > [server]
1068 1068 > bundle1gd = false
1069 1069 > EOF
1070 1070 $ hg serve -R bundle2onlyserver -p $HGPORT -d --pid-file=hg.pid
1071 1071 $ cat hg.pid >> $DAEMON_PIDS
1072 1072
1073 1073 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
1074 1074 requesting all changes
1075 1075 abort: remote error:
1076 1076 incompatible Mercurial client; bundle2 required
1077 1077 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1078 [255]
1078 [100]
1079 1079
1080 1080 $ killdaemons.py
1081 1081
1082 1082 $ cd notgdserver
1083 1083 $ cat > .hg/hgrc << EOF
1084 1084 > [server]
1085 1085 > bundle1gd = false
1086 1086 > EOF
1087 1087 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1088 1088 $ cat hg.pid >> $DAEMON_PIDS
1089 1089
1090 1090 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-2
1091 1091 requesting all changes
1092 1092 adding changesets
1093 1093 adding manifests
1094 1094 adding file changes
1095 1095 added 1 changesets with 1 changes to 1 files
1096 1096 new changesets 96ee1d7354c4
1097 1097 updating to branch default
1098 1098 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1099 1099
1100 1100 $ killdaemons.py
1101 1101 $ cd ../bundle2onlyserver
1102 1102
1103 1103 Verify bundle1 pushes can be disabled
1104 1104
1105 1105 $ cat > .hg/hgrc << EOF
1106 1106 > [server]
1107 1107 > bundle1.push = false
1108 1108 > [web]
1109 1109 > allow_push = *
1110 1110 > push_ssl = false
1111 1111 > EOF
1112 1112
1113 1113 $ hg serve -p $HGPORT -d --pid-file=hg.pid -E error.log
1114 1114 $ cat hg.pid >> $DAEMON_PIDS
1115 1115 $ cd ..
1116 1116
1117 1117 $ hg clone http://localhost:$HGPORT bundle2-only
1118 1118 requesting all changes
1119 1119 adding changesets
1120 1120 adding manifests
1121 1121 adding file changes
1122 1122 added 1 changesets with 1 changes to 1 files
1123 1123 new changesets 96ee1d7354c4
1124 1124 updating to branch default
1125 1125 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1126 1126 $ cd bundle2-only
1127 1127 $ echo commit > foo
1128 1128 $ hg commit -m commit
1129 1129 $ hg --config devel.legacy.exchange=bundle1 push
1130 1130 pushing to http://localhost:$HGPORT/
1131 1131 searching for changes
1132 1132 abort: remote error:
1133 1133 incompatible Mercurial client; bundle2 required
1134 1134 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1135 [255]
1135 [100]
1136 1136
1137 1137 (also check with ssh)
1138 1138
1139 1139 $ hg --config devel.legacy.exchange=bundle1 push ssh://user@dummy/bundle2onlyserver
1140 1140 pushing to ssh://user@dummy/bundle2onlyserver
1141 1141 searching for changes
1142 1142 remote: abort: incompatible Mercurial client; bundle2 required
1143 1143 remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1144 1144 [1]
1145 1145
1146 1146 $ hg push
1147 1147 pushing to http://localhost:$HGPORT/
1148 1148 searching for changes
1149 1149 remote: adding changesets
1150 1150 remote: adding manifests
1151 1151 remote: adding file changes
1152 1152 remote: added 1 changesets with 1 changes to 1 files
@@ -1,1309 +1,1309 b''
1 1 #testcases sshv1 sshv2
2 2
3 3 #if sshv2
4 4 $ cat >> $HGRCPATH << EOF
5 5 > [experimental]
6 6 > sshpeer.advertise-v2 = true
7 7 > sshserver.support-v2 = true
8 8 > EOF
9 9 #endif
10 10
11 11 Prepare repo a:
12 12
13 13 $ hg init a
14 14 $ cd a
15 15 $ echo a > a
16 16 $ hg add a
17 17 $ hg commit -m test
18 18 $ echo first line > b
19 19 $ hg add b
20 20
21 21 Create a non-inlined filelog:
22 22
23 23 $ "$PYTHON" -c 'open("data1", "wb").write(b"".join(b"%d\n" % x for x in range(10000)))'
24 24 $ for j in 0 1 2 3 4 5 6 7 8 9; do
25 25 > cat data1 >> b
26 26 > hg commit -m test
27 27 > done
28 28
29 29 List files in store/data (should show a 'b.d'):
30 30
31 31 #if reporevlogstore
32 32 $ for i in .hg/store/data/*; do
33 33 > echo $i
34 34 > done
35 35 .hg/store/data/a.i
36 36 .hg/store/data/b.d
37 37 .hg/store/data/b.i
38 38 #endif
39 39
40 40 Trigger branchcache creation:
41 41
42 42 $ hg branches
43 43 default 10:a7949464abda
44 44 $ ls .hg/cache
45 45 branch2-served
46 46 rbc-names-v1
47 47 rbc-revs-v1
48 48
49 49 Default operation:
50 50
51 51 $ hg clone . ../b
52 52 updating to branch default
53 53 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
54 54 $ cd ../b
55 55
56 56 Ensure branchcache got copied over:
57 57
58 58 $ ls .hg/cache
59 59 branch2-served
60 60 rbc-names-v1
61 61 rbc-revs-v1
62 62
63 63 $ cat a
64 64 a
65 65 $ hg verify
66 66 checking changesets
67 67 checking manifests
68 68 crosschecking files in changesets and manifests
69 69 checking files
70 70 checked 11 changesets with 11 changes to 2 files
71 71
72 72 Invalid dest '' must abort:
73 73
74 74 $ hg clone . ''
75 75 abort: empty destination path is not valid
76 76 [255]
77 77
78 78 No update, with debug option:
79 79
80 80 #if hardlink
81 81 $ hg --debug clone -U . ../c --config progress.debug=true
82 82 linking: 1 files
83 83 linking: 2 files
84 84 linking: 3 files
85 85 linking: 4 files
86 86 linking: 5 files
87 87 linking: 6 files
88 88 linking: 7 files
89 89 linking: 8 files
90 90 linked 8 files (reporevlogstore !)
91 91 linking: 9 files (reposimplestore !)
92 92 linking: 10 files (reposimplestore !)
93 93 linking: 11 files (reposimplestore !)
94 94 linking: 12 files (reposimplestore !)
95 95 linking: 13 files (reposimplestore !)
96 96 linking: 14 files (reposimplestore !)
97 97 linking: 15 files (reposimplestore !)
98 98 linking: 16 files (reposimplestore !)
99 99 linking: 17 files (reposimplestore !)
100 100 linking: 18 files (reposimplestore !)
101 101 linked 18 files (reposimplestore !)
102 102 #else
103 103 $ hg --debug clone -U . ../c --config progress.debug=true
104 104 linking: 1 files
105 105 copying: 2 files
106 106 copying: 3 files
107 107 copying: 4 files
108 108 copying: 5 files
109 109 copying: 6 files
110 110 copying: 7 files
111 111 copying: 8 files
112 112 copied 8 files (reporevlogstore !)
113 113 copying: 9 files (reposimplestore !)
114 114 copying: 10 files (reposimplestore !)
115 115 copying: 11 files (reposimplestore !)
116 116 copying: 12 files (reposimplestore !)
117 117 copying: 13 files (reposimplestore !)
118 118 copying: 14 files (reposimplestore !)
119 119 copying: 15 files (reposimplestore !)
120 120 copying: 16 files (reposimplestore !)
121 121 copying: 17 files (reposimplestore !)
122 122 copying: 18 files (reposimplestore !)
123 123 copied 18 files (reposimplestore !)
124 124 #endif
125 125 $ cd ../c
126 126
127 127 Ensure branchcache got copied over:
128 128
129 129 $ ls .hg/cache
130 130 branch2-served
131 131 rbc-names-v1
132 132 rbc-revs-v1
133 133
134 134 $ cat a 2>/dev/null || echo "a not present"
135 135 a not present
136 136 $ hg verify
137 137 checking changesets
138 138 checking manifests
139 139 crosschecking files in changesets and manifests
140 140 checking files
141 141 checked 11 changesets with 11 changes to 2 files
142 142
143 143 Default destination:
144 144
145 145 $ mkdir ../d
146 146 $ cd ../d
147 147 $ hg clone ../a
148 148 destination directory: a
149 149 updating to branch default
150 150 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
151 151 $ cd a
152 152 $ hg cat a
153 153 a
154 154 $ cd ../..
155 155
156 156 Check that we drop the 'file:' from the path before writing the .hgrc:
157 157
158 158 $ hg clone file:a e
159 159 updating to branch default
160 160 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
161 161 $ grep 'file:' e/.hg/hgrc
162 162 [1]
163 163
164 164 Check that path aliases are expanded:
165 165
166 166 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
167 167 $ hg -R f showconfig paths.default
168 168 $TESTTMP/a#0
169 169
170 170 Use --pull:
171 171
172 172 $ hg clone --pull a g
173 173 requesting all changes
174 174 adding changesets
175 175 adding manifests
176 176 adding file changes
177 177 added 11 changesets with 11 changes to 2 files
178 178 new changesets acb14030fe0a:a7949464abda
179 179 updating to branch default
180 180 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
181 181 $ hg -R g verify
182 182 checking changesets
183 183 checking manifests
184 184 crosschecking files in changesets and manifests
185 185 checking files
186 186 checked 11 changesets with 11 changes to 2 files
187 187
188 188 Invalid dest '' with --pull must abort (issue2528):
189 189
190 190 $ hg clone --pull a ''
191 191 abort: empty destination path is not valid
192 192 [255]
193 193
194 194 Clone to '.':
195 195
196 196 $ mkdir h
197 197 $ cd h
198 198 $ hg clone ../a .
199 199 updating to branch default
200 200 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
201 201 $ cd ..
202 202
203 203
204 204 *** Tests for option -u ***
205 205
206 206 Adding some more history to repo a:
207 207
208 208 $ cd a
209 209 $ hg tag ref1
210 210 $ echo the quick brown fox >a
211 211 $ hg ci -m "hacked default"
212 212 $ hg up ref1
213 213 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
214 214 $ hg branch stable
215 215 marked working directory as branch stable
216 216 (branches are permanent and global, did you want a bookmark?)
217 217 $ echo some text >a
218 218 $ hg ci -m "starting branch stable"
219 219 $ hg tag ref2
220 220 $ echo some more text >a
221 221 $ hg ci -m "another change for branch stable"
222 222 $ hg up ref2
223 223 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
224 224 $ hg parents
225 225 changeset: 13:e8ece76546a6
226 226 branch: stable
227 227 tag: ref2
228 228 parent: 10:a7949464abda
229 229 user: test
230 230 date: Thu Jan 01 00:00:00 1970 +0000
231 231 summary: starting branch stable
232 232
233 233
234 234 Repo a has two heads:
235 235
236 236 $ hg heads
237 237 changeset: 15:0aae7cf88f0d
238 238 branch: stable
239 239 tag: tip
240 240 user: test
241 241 date: Thu Jan 01 00:00:00 1970 +0000
242 242 summary: another change for branch stable
243 243
244 244 changeset: 12:f21241060d6a
245 245 user: test
246 246 date: Thu Jan 01 00:00:00 1970 +0000
247 247 summary: hacked default
248 248
249 249
250 250 $ cd ..
251 251
252 252
253 253 Testing --noupdate with --updaterev (must abort):
254 254
255 255 $ hg clone --noupdate --updaterev 1 a ua
256 256 abort: cannot specify both --noupdate and --updaterev
257 257 [10]
258 258
259 259
260 260 Testing clone -u:
261 261
262 262 $ hg clone -u . a ua
263 263 updating to branch stable
264 264 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
265 265
266 266 Repo ua has both heads:
267 267
268 268 $ hg -R ua heads
269 269 changeset: 15:0aae7cf88f0d
270 270 branch: stable
271 271 tag: tip
272 272 user: test
273 273 date: Thu Jan 01 00:00:00 1970 +0000
274 274 summary: another change for branch stable
275 275
276 276 changeset: 12:f21241060d6a
277 277 user: test
278 278 date: Thu Jan 01 00:00:00 1970 +0000
279 279 summary: hacked default
280 280
281 281
282 282 Same revision checked out in repo a and ua:
283 283
284 284 $ hg -R a parents --template "{node|short}\n"
285 285 e8ece76546a6
286 286 $ hg -R ua parents --template "{node|short}\n"
287 287 e8ece76546a6
288 288
289 289 $ rm -r ua
290 290
291 291
292 292 Testing clone --pull -u:
293 293
294 294 $ hg clone --pull -u . a ua
295 295 requesting all changes
296 296 adding changesets
297 297 adding manifests
298 298 adding file changes
299 299 added 16 changesets with 16 changes to 3 files (+1 heads)
300 300 new changesets acb14030fe0a:0aae7cf88f0d
301 301 updating to branch stable
302 302 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
303 303
304 304 Repo ua has both heads:
305 305
306 306 $ hg -R ua heads
307 307 changeset: 15:0aae7cf88f0d
308 308 branch: stable
309 309 tag: tip
310 310 user: test
311 311 date: Thu Jan 01 00:00:00 1970 +0000
312 312 summary: another change for branch stable
313 313
314 314 changeset: 12:f21241060d6a
315 315 user: test
316 316 date: Thu Jan 01 00:00:00 1970 +0000
317 317 summary: hacked default
318 318
319 319
320 320 Same revision checked out in repo a and ua:
321 321
322 322 $ hg -R a parents --template "{node|short}\n"
323 323 e8ece76546a6
324 324 $ hg -R ua parents --template "{node|short}\n"
325 325 e8ece76546a6
326 326
327 327 $ rm -r ua
328 328
329 329
330 330 Testing clone -u <branch>:
331 331
332 332 $ hg clone -u stable a ua
333 333 updating to branch stable
334 334 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
335 335
336 336 Repo ua has both heads:
337 337
338 338 $ hg -R ua heads
339 339 changeset: 15:0aae7cf88f0d
340 340 branch: stable
341 341 tag: tip
342 342 user: test
343 343 date: Thu Jan 01 00:00:00 1970 +0000
344 344 summary: another change for branch stable
345 345
346 346 changeset: 12:f21241060d6a
347 347 user: test
348 348 date: Thu Jan 01 00:00:00 1970 +0000
349 349 summary: hacked default
350 350
351 351
352 352 Branch 'stable' is checked out:
353 353
354 354 $ hg -R ua parents
355 355 changeset: 15:0aae7cf88f0d
356 356 branch: stable
357 357 tag: tip
358 358 user: test
359 359 date: Thu Jan 01 00:00:00 1970 +0000
360 360 summary: another change for branch stable
361 361
362 362
363 363 $ rm -r ua
364 364
365 365
366 366 Testing default checkout:
367 367
368 368 $ hg clone a ua
369 369 updating to branch default
370 370 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
371 371
372 372 Repo ua has both heads:
373 373
374 374 $ hg -R ua heads
375 375 changeset: 15:0aae7cf88f0d
376 376 branch: stable
377 377 tag: tip
378 378 user: test
379 379 date: Thu Jan 01 00:00:00 1970 +0000
380 380 summary: another change for branch stable
381 381
382 382 changeset: 12:f21241060d6a
383 383 user: test
384 384 date: Thu Jan 01 00:00:00 1970 +0000
385 385 summary: hacked default
386 386
387 387
388 388 Branch 'default' is checked out:
389 389
390 390 $ hg -R ua parents
391 391 changeset: 12:f21241060d6a
392 392 user: test
393 393 date: Thu Jan 01 00:00:00 1970 +0000
394 394 summary: hacked default
395 395
396 396 Test clone with a branch named "@" (issue3677)
397 397
398 398 $ hg -R ua branch @
399 399 marked working directory as branch @
400 400 $ hg -R ua commit -m 'created branch @'
401 401 $ hg clone ua atbranch
402 402 updating to branch default
403 403 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
404 404 $ hg -R atbranch heads
405 405 changeset: 16:798b6d97153e
406 406 branch: @
407 407 tag: tip
408 408 parent: 12:f21241060d6a
409 409 user: test
410 410 date: Thu Jan 01 00:00:00 1970 +0000
411 411 summary: created branch @
412 412
413 413 changeset: 15:0aae7cf88f0d
414 414 branch: stable
415 415 user: test
416 416 date: Thu Jan 01 00:00:00 1970 +0000
417 417 summary: another change for branch stable
418 418
419 419 changeset: 12:f21241060d6a
420 420 user: test
421 421 date: Thu Jan 01 00:00:00 1970 +0000
422 422 summary: hacked default
423 423
424 424 $ hg -R atbranch parents
425 425 changeset: 12:f21241060d6a
426 426 user: test
427 427 date: Thu Jan 01 00:00:00 1970 +0000
428 428 summary: hacked default
429 429
430 430
431 431 $ rm -r ua atbranch
432 432
433 433
434 434 Testing #<branch>:
435 435
436 436 $ hg clone -u . a#stable ua
437 437 adding changesets
438 438 adding manifests
439 439 adding file changes
440 440 added 14 changesets with 14 changes to 3 files
441 441 new changesets acb14030fe0a:0aae7cf88f0d
442 442 updating to branch stable
443 443 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
444 444
445 445 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
446 446
447 447 $ hg -R ua heads
448 448 changeset: 13:0aae7cf88f0d
449 449 branch: stable
450 450 tag: tip
451 451 user: test
452 452 date: Thu Jan 01 00:00:00 1970 +0000
453 453 summary: another change for branch stable
454 454
455 455 changeset: 10:a7949464abda
456 456 user: test
457 457 date: Thu Jan 01 00:00:00 1970 +0000
458 458 summary: test
459 459
460 460
461 461 Same revision checked out in repo a and ua:
462 462
463 463 $ hg -R a parents --template "{node|short}\n"
464 464 e8ece76546a6
465 465 $ hg -R ua parents --template "{node|short}\n"
466 466 e8ece76546a6
467 467
468 468 $ rm -r ua
469 469
470 470
471 471 Testing -u -r <branch>:
472 472
473 473 $ hg clone -u . -r stable a ua
474 474 adding changesets
475 475 adding manifests
476 476 adding file changes
477 477 added 14 changesets with 14 changes to 3 files
478 478 new changesets acb14030fe0a:0aae7cf88f0d
479 479 updating to branch stable
480 480 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
481 481
482 482 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
483 483
484 484 $ hg -R ua heads
485 485 changeset: 13:0aae7cf88f0d
486 486 branch: stable
487 487 tag: tip
488 488 user: test
489 489 date: Thu Jan 01 00:00:00 1970 +0000
490 490 summary: another change for branch stable
491 491
492 492 changeset: 10:a7949464abda
493 493 user: test
494 494 date: Thu Jan 01 00:00:00 1970 +0000
495 495 summary: test
496 496
497 497
498 498 Same revision checked out in repo a and ua:
499 499
500 500 $ hg -R a parents --template "{node|short}\n"
501 501 e8ece76546a6
502 502 $ hg -R ua parents --template "{node|short}\n"
503 503 e8ece76546a6
504 504
505 505 $ rm -r ua
506 506
507 507
508 508 Testing -r <branch>:
509 509
510 510 $ hg clone -r stable a ua
511 511 adding changesets
512 512 adding manifests
513 513 adding file changes
514 514 added 14 changesets with 14 changes to 3 files
515 515 new changesets acb14030fe0a:0aae7cf88f0d
516 516 updating to branch stable
517 517 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
518 518
519 519 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
520 520
521 521 $ hg -R ua heads
522 522 changeset: 13:0aae7cf88f0d
523 523 branch: stable
524 524 tag: tip
525 525 user: test
526 526 date: Thu Jan 01 00:00:00 1970 +0000
527 527 summary: another change for branch stable
528 528
529 529 changeset: 10:a7949464abda
530 530 user: test
531 531 date: Thu Jan 01 00:00:00 1970 +0000
532 532 summary: test
533 533
534 534
535 535 Branch 'stable' is checked out:
536 536
537 537 $ hg -R ua parents
538 538 changeset: 13:0aae7cf88f0d
539 539 branch: stable
540 540 tag: tip
541 541 user: test
542 542 date: Thu Jan 01 00:00:00 1970 +0000
543 543 summary: another change for branch stable
544 544
545 545
546 546 $ rm -r ua
547 547
548 548
549 549 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
550 550 iterable in addbranchrevs()
551 551
552 552 $ cat <<EOF > simpleclone.py
553 553 > from mercurial import hg, ui as uimod
554 554 > myui = uimod.ui.load()
555 555 > repo = hg.repository(myui, b'a')
556 556 > hg.clone(myui, {}, repo, dest=b"ua")
557 557 > EOF
558 558
559 559 $ "$PYTHON" simpleclone.py
560 560 updating to branch default
561 561 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
562 562
563 563 $ rm -r ua
564 564
565 565 $ cat <<EOF > branchclone.py
566 566 > from mercurial import extensions, hg, ui as uimod
567 567 > myui = uimod.ui.load()
568 568 > extensions.loadall(myui)
569 569 > extensions.populateui(myui)
570 570 > repo = hg.repository(myui, b'a')
571 571 > hg.clone(myui, {}, repo, dest=b"ua", branch=[b"stable"])
572 572 > EOF
573 573
574 574 $ "$PYTHON" branchclone.py
575 575 adding changesets
576 576 adding manifests
577 577 adding file changes
578 578 added 14 changesets with 14 changes to 3 files
579 579 new changesets acb14030fe0a:0aae7cf88f0d
580 580 updating to branch stable
581 581 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
582 582 $ rm -r ua
583 583
584 584
585 585 Test clone with special '@' bookmark:
586 586 $ cd a
587 587 $ hg bookmark -r a7949464abda @ # branch point of stable from default
588 588 $ hg clone . ../i
589 589 updating to bookmark @
590 590 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
591 591 $ hg id -i ../i
592 592 a7949464abda
593 593 $ rm -r ../i
594 594
595 595 $ hg bookmark -f -r stable @
596 596 $ hg bookmarks
597 597 @ 15:0aae7cf88f0d
598 598 $ hg clone . ../i
599 599 updating to bookmark @ on branch stable
600 600 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
601 601 $ hg id -i ../i
602 602 0aae7cf88f0d
603 603 $ cd "$TESTTMP"
604 604
605 605
606 606 Testing failures:
607 607
608 608 $ mkdir fail
609 609 $ cd fail
610 610
611 611 No local source
612 612
613 613 $ hg clone a b
614 614 abort: repository a not found!
615 615 [255]
616 616
617 617 Invalid URL
618 618
619 619 $ hg clone http://invalid:url/a b
620 620 abort: error: nonnumeric port: 'url'
621 [255]
621 [100]
622 622
623 623 No remote source
624 624
625 625 #if windows
626 626 $ hg clone http://$LOCALIP:3121/a b
627 627 abort: error: * (glob)
628 628 [255]
629 629 #else
630 630 $ hg clone http://$LOCALIP:3121/a b
631 631 abort: error: *refused* (glob)
632 [255]
632 [100]
633 633 #endif
634 634 $ rm -rf b # work around bug with http clone
635 635
636 636
637 637 #if unix-permissions no-root
638 638
639 639 Inaccessible source
640 640
641 641 $ mkdir a
642 642 $ chmod 000 a
643 643 $ hg clone a b
644 644 abort: Permission denied: *$TESTTMP/fail/a/.hg* (glob)
645 645 [255]
646 646
647 647 Inaccessible destination
648 648
649 649 $ hg init b
650 650 $ cd b
651 651 $ hg clone . ../a
652 652 abort: Permission denied: *../a* (glob)
653 653 [255]
654 654 $ cd ..
655 655 $ chmod 700 a
656 656 $ rm -r a b
657 657
658 658 #endif
659 659
660 660
661 661 #if fifo
662 662
663 663 Source of wrong type
664 664
665 665 $ mkfifo a
666 666 $ hg clone a b
667 667 abort: $ENOTDIR$: *$TESTTMP/fail/a/.hg* (glob)
668 668 [255]
669 669 $ rm a
670 670
671 671 #endif
672 672
673 673 Default destination, same directory
674 674
675 675 $ hg init q
676 676 $ hg clone q
677 677 destination directory: q
678 678 abort: destination 'q' is not empty
679 679 [255]
680 680
681 681 destination directory not empty
682 682
683 683 $ mkdir a
684 684 $ echo stuff > a/a
685 685 $ hg clone q a
686 686 abort: destination 'a' is not empty
687 687 [255]
688 688
689 689
690 690 #if unix-permissions no-root
691 691
692 692 leave existing directory in place after clone failure
693 693
694 694 $ hg init c
695 695 $ cd c
696 696 $ echo c > c
697 697 $ hg commit -A -m test
698 698 adding c
699 699 $ chmod -rx .hg/store/data
700 700 $ cd ..
701 701 $ mkdir d
702 702 $ hg clone c d 2> err
703 703 [255]
704 704 $ test -d d
705 705 $ test -d d/.hg
706 706 [1]
707 707
708 708 re-enable perm to allow deletion
709 709
710 710 $ chmod +rx c/.hg/store/data
711 711
712 712 #endif
713 713
714 714 $ cd ..
715 715
716 716 Test clone from the repository in (emulated) revlog format 0 (issue4203):
717 717
718 718 $ mkdir issue4203
719 719 $ mkdir -p src/.hg
720 720 $ echo foo > src/foo
721 721 $ hg -R src add src/foo
722 722 $ hg -R src commit -m '#0'
723 723 $ hg -R src log -q
724 724 0:e1bab28bca43
725 725 $ hg -R src debugrevlog -c | egrep 'format|flags'
726 726 format : 0
727 727 flags : (none)
728 728 $ hg root -R src -T json | sed 's|\\\\|\\|g'
729 729 [
730 730 {
731 731 "hgpath": "$TESTTMP/src/.hg",
732 732 "reporoot": "$TESTTMP/src",
733 733 "storepath": "$TESTTMP/src/.hg"
734 734 }
735 735 ]
736 736 $ hg clone -U -q src dst
737 737 $ hg -R dst log -q
738 738 0:e1bab28bca43
739 739
740 740 Create repositories to test auto sharing functionality
741 741
742 742 $ cat >> $HGRCPATH << EOF
743 743 > [extensions]
744 744 > share=
745 745 > EOF
746 746
747 747 $ hg init empty
748 748 $ hg init source1a
749 749 $ cd source1a
750 750 $ echo initial1 > foo
751 751 $ hg -q commit -A -m initial
752 752 $ echo second > foo
753 753 $ hg commit -m second
754 754 $ cd ..
755 755
756 756 $ hg init filteredrev0
757 757 $ cd filteredrev0
758 758 $ cat >> .hg/hgrc << EOF
759 759 > [experimental]
760 760 > evolution.createmarkers=True
761 761 > EOF
762 762 $ echo initial1 > foo
763 763 $ hg -q commit -A -m initial0
764 764 $ hg -q up -r null
765 765 $ echo initial2 > foo
766 766 $ hg -q commit -A -m initial1
767 767 $ hg debugobsolete c05d5c47a5cf81401869999f3d05f7d699d2b29a e082c1832e09a7d1e78b7fd49a592d372de854c8
768 768 1 new obsolescence markers
769 769 obsoleted 1 changesets
770 770 $ cd ..
771 771
772 772 $ hg -q clone --pull source1a source1b
773 773 $ cd source1a
774 774 $ hg bookmark bookA
775 775 $ echo 1a > foo
776 776 $ hg commit -m 1a
777 777 $ cd ../source1b
778 778 $ hg -q up -r 0
779 779 $ echo head1 > foo
780 780 $ hg commit -m head1
781 781 created new head
782 782 $ hg bookmark head1
783 783 $ hg -q up -r 0
784 784 $ echo head2 > foo
785 785 $ hg commit -m head2
786 786 created new head
787 787 $ hg bookmark head2
788 788 $ hg -q up -r 0
789 789 $ hg branch branch1
790 790 marked working directory as branch branch1
791 791 (branches are permanent and global, did you want a bookmark?)
792 792 $ echo branch1 > foo
793 793 $ hg commit -m branch1
794 794 $ hg -q up -r 0
795 795 $ hg branch branch2
796 796 marked working directory as branch branch2
797 797 $ echo branch2 > foo
798 798 $ hg commit -m branch2
799 799 $ cd ..
800 800 $ hg init source2
801 801 $ cd source2
802 802 $ echo initial2 > foo
803 803 $ hg -q commit -A -m initial2
804 804 $ echo second > foo
805 805 $ hg commit -m second
806 806 $ cd ..
807 807
808 808 Clone with auto share from an empty repo should not result in share
809 809
810 810 $ mkdir share
811 811 $ hg --config share.pool=share clone empty share-empty
812 812 (not using pooled storage: remote appears to be empty)
813 813 updating to branch default
814 814 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
815 815 $ ls share
816 816 $ test -d share-empty/.hg/store
817 817 $ test -f share-empty/.hg/sharedpath
818 818 [1]
819 819
820 820 Clone with auto share from a repo with filtered revision 0 should not result in share
821 821
822 822 $ hg --config share.pool=share clone filteredrev0 share-filtered
823 823 (not using pooled storage: unable to resolve identity of remote)
824 824 requesting all changes
825 825 adding changesets
826 826 adding manifests
827 827 adding file changes
828 828 added 1 changesets with 1 changes to 1 files
829 829 new changesets e082c1832e09
830 830 updating to branch default
831 831 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
832 832
833 833 Clone from repo with content should result in shared store being created
834 834
835 835 $ hg --config share.pool=share clone source1a share-dest1a
836 836 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
837 837 requesting all changes
838 838 adding changesets
839 839 adding manifests
840 840 adding file changes
841 841 added 3 changesets with 3 changes to 1 files
842 842 new changesets b5f04eac9d8f:e5bfe23c0b47
843 843 searching for changes
844 844 no changes found
845 845 adding remote bookmark bookA
846 846 updating working directory
847 847 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
848 848
849 849 The shared repo should have been created
850 850
851 851 $ ls share
852 852 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
853 853
854 854 The destination should point to it
855 855
856 856 $ cat share-dest1a/.hg/sharedpath; echo
857 857 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg
858 858
859 859 The destination should have bookmarks
860 860
861 861 $ hg -R share-dest1a bookmarks
862 862 bookA 2:e5bfe23c0b47
863 863
864 864 The default path should be the remote, not the share
865 865
866 866 $ hg -R share-dest1a config paths.default
867 867 $TESTTMP/source1a
868 868
869 869 Clone with existing share dir should result in pull + share
870 870
871 871 $ hg --config share.pool=share clone source1b share-dest1b
872 872 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
873 873 searching for changes
874 874 adding changesets
875 875 adding manifests
876 876 adding file changes
877 877 adding remote bookmark head1
878 878 adding remote bookmark head2
879 879 added 4 changesets with 4 changes to 1 files (+4 heads)
880 880 new changesets 4a8dc1ab4c13:6bacf4683960
881 881 updating working directory
882 882 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
883 883
884 884 $ ls share
885 885 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
886 886
887 887 $ cat share-dest1b/.hg/sharedpath; echo
888 888 $TESTTMP/share/b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1/.hg
889 889
890 890 We only get bookmarks from the remote, not everything in the share
891 891
892 892 $ hg -R share-dest1b bookmarks
893 893 head1 3:4a8dc1ab4c13
894 894 head2 4:99f71071f117
895 895
896 896 Default path should be source, not share.
897 897
898 898 $ hg -R share-dest1b config paths.default
899 899 $TESTTMP/source1b
900 900
901 901 Checked out revision should be head of default branch
902 902
903 903 $ hg -R share-dest1b log -r .
904 904 changeset: 4:99f71071f117
905 905 bookmark: head2
906 906 parent: 0:b5f04eac9d8f
907 907 user: test
908 908 date: Thu Jan 01 00:00:00 1970 +0000
909 909 summary: head2
910 910
911 911
912 912 Clone from unrelated repo should result in new share
913 913
914 914 $ hg --config share.pool=share clone source2 share-dest2
915 915 (sharing from new pooled repository 22aeff664783fd44c6d9b435618173c118c3448e)
916 916 requesting all changes
917 917 adding changesets
918 918 adding manifests
919 919 adding file changes
920 920 added 2 changesets with 2 changes to 1 files
921 921 new changesets 22aeff664783:63cf6c3dba4a
922 922 searching for changes
923 923 no changes found
924 924 updating working directory
925 925 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
926 926
927 927 $ ls share
928 928 22aeff664783fd44c6d9b435618173c118c3448e
929 929 b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1
930 930
931 931 remote naming mode works as advertised
932 932
933 933 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1a share-remote1a
934 934 (sharing from new pooled repository 195bb1fcdb595c14a6c13e0269129ed78f6debde)
935 935 requesting all changes
936 936 adding changesets
937 937 adding manifests
938 938 adding file changes
939 939 added 3 changesets with 3 changes to 1 files
940 940 new changesets b5f04eac9d8f:e5bfe23c0b47
941 941 searching for changes
942 942 no changes found
943 943 adding remote bookmark bookA
944 944 updating working directory
945 945 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
946 946
947 947 $ ls shareremote
948 948 195bb1fcdb595c14a6c13e0269129ed78f6debde
949 949
950 950 $ hg --config share.pool=shareremote --config share.poolnaming=remote clone source1b share-remote1b
951 951 (sharing from new pooled repository c0d4f83847ca2a873741feb7048a45085fd47c46)
952 952 requesting all changes
953 953 adding changesets
954 954 adding manifests
955 955 adding file changes
956 956 added 6 changesets with 6 changes to 1 files (+4 heads)
957 957 new changesets b5f04eac9d8f:6bacf4683960
958 958 searching for changes
959 959 no changes found
960 960 adding remote bookmark head1
961 961 adding remote bookmark head2
962 962 updating working directory
963 963 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
964 964
965 965 $ ls shareremote
966 966 195bb1fcdb595c14a6c13e0269129ed78f6debde
967 967 c0d4f83847ca2a873741feb7048a45085fd47c46
968 968
969 969 request to clone a single revision is respected in sharing mode
970 970
971 971 $ hg --config share.pool=sharerevs clone -r 4a8dc1ab4c13 source1b share-1arev
972 972 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
973 973 adding changesets
974 974 adding manifests
975 975 adding file changes
976 976 added 2 changesets with 2 changes to 1 files
977 977 new changesets b5f04eac9d8f:4a8dc1ab4c13
978 978 no changes found
979 979 adding remote bookmark head1
980 980 updating working directory
981 981 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
982 982
983 983 $ hg -R share-1arev log -G
984 984 @ changeset: 1:4a8dc1ab4c13
985 985 | bookmark: head1
986 986 | tag: tip
987 987 | user: test
988 988 | date: Thu Jan 01 00:00:00 1970 +0000
989 989 | summary: head1
990 990 |
991 991 o changeset: 0:b5f04eac9d8f
992 992 user: test
993 993 date: Thu Jan 01 00:00:00 1970 +0000
994 994 summary: initial
995 995
996 996
997 997 making another clone should only pull down requested rev
998 998
999 999 $ hg --config share.pool=sharerevs clone -r 99f71071f117 source1b share-1brev
1000 1000 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1001 1001 searching for changes
1002 1002 adding changesets
1003 1003 adding manifests
1004 1004 adding file changes
1005 1005 adding remote bookmark head1
1006 1006 adding remote bookmark head2
1007 1007 added 1 changesets with 1 changes to 1 files (+1 heads)
1008 1008 new changesets 99f71071f117
1009 1009 updating working directory
1010 1010 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1011 1011
1012 1012 $ hg -R share-1brev log -G
1013 1013 @ changeset: 2:99f71071f117
1014 1014 | bookmark: head2
1015 1015 | tag: tip
1016 1016 | parent: 0:b5f04eac9d8f
1017 1017 | user: test
1018 1018 | date: Thu Jan 01 00:00:00 1970 +0000
1019 1019 | summary: head2
1020 1020 |
1021 1021 | o changeset: 1:4a8dc1ab4c13
1022 1022 |/ bookmark: head1
1023 1023 | user: test
1024 1024 | date: Thu Jan 01 00:00:00 1970 +0000
1025 1025 | summary: head1
1026 1026 |
1027 1027 o changeset: 0:b5f04eac9d8f
1028 1028 user: test
1029 1029 date: Thu Jan 01 00:00:00 1970 +0000
1030 1030 summary: initial
1031 1031
1032 1032
1033 1033 Request to clone a single branch is respected in sharing mode
1034 1034
1035 1035 $ hg --config share.pool=sharebranch clone -b branch1 source1b share-1bbranch1
1036 1036 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1037 1037 adding changesets
1038 1038 adding manifests
1039 1039 adding file changes
1040 1040 added 2 changesets with 2 changes to 1 files
1041 1041 new changesets b5f04eac9d8f:5f92a6c1a1b1
1042 1042 no changes found
1043 1043 updating working directory
1044 1044 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1045 1045
1046 1046 $ hg -R share-1bbranch1 log -G
1047 1047 o changeset: 1:5f92a6c1a1b1
1048 1048 | branch: branch1
1049 1049 | tag: tip
1050 1050 | user: test
1051 1051 | date: Thu Jan 01 00:00:00 1970 +0000
1052 1052 | summary: branch1
1053 1053 |
1054 1054 @ changeset: 0:b5f04eac9d8f
1055 1055 user: test
1056 1056 date: Thu Jan 01 00:00:00 1970 +0000
1057 1057 summary: initial
1058 1058
1059 1059
1060 1060 $ hg --config share.pool=sharebranch clone -b branch2 source1b share-1bbranch2
1061 1061 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1062 1062 searching for changes
1063 1063 adding changesets
1064 1064 adding manifests
1065 1065 adding file changes
1066 1066 added 1 changesets with 1 changes to 1 files (+1 heads)
1067 1067 new changesets 6bacf4683960
1068 1068 updating working directory
1069 1069 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1070 1070
1071 1071 $ hg -R share-1bbranch2 log -G
1072 1072 o changeset: 2:6bacf4683960
1073 1073 | branch: branch2
1074 1074 | tag: tip
1075 1075 | parent: 0:b5f04eac9d8f
1076 1076 | user: test
1077 1077 | date: Thu Jan 01 00:00:00 1970 +0000
1078 1078 | summary: branch2
1079 1079 |
1080 1080 | o changeset: 1:5f92a6c1a1b1
1081 1081 |/ branch: branch1
1082 1082 | user: test
1083 1083 | date: Thu Jan 01 00:00:00 1970 +0000
1084 1084 | summary: branch1
1085 1085 |
1086 1086 @ changeset: 0:b5f04eac9d8f
1087 1087 user: test
1088 1088 date: Thu Jan 01 00:00:00 1970 +0000
1089 1089 summary: initial
1090 1090
1091 1091
1092 1092 -U is respected in share clone mode
1093 1093
1094 1094 $ hg --config share.pool=share clone -U source1a share-1anowc
1095 1095 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1096 1096 searching for changes
1097 1097 no changes found
1098 1098 adding remote bookmark bookA
1099 1099
1100 1100 $ ls -A share-1anowc
1101 1101 .hg
1102 1102
1103 1103 Test that auto sharing doesn't cause failure of "hg clone local remote"
1104 1104
1105 1105 $ cd $TESTTMP
1106 1106 $ hg -R a id -r 0
1107 1107 acb14030fe0a
1108 1108 $ hg id -R remote -r 0
1109 1109 abort: repository remote not found!
1110 1110 [255]
1111 1111 $ hg --config share.pool=share -q clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" a ssh://user@dummy/remote
1112 1112 $ hg -R remote id -r 0
1113 1113 acb14030fe0a
1114 1114
1115 1115 Cloning into pooled storage doesn't race (issue5104)
1116 1116
1117 1117 $ HGPOSTLOCKDELAY=2.0 hg --config share.pool=racepool --config extensions.lockdelay=$TESTDIR/lockdelay.py clone source1a share-destrace1 > race1.log 2>&1 &
1118 1118 $ HGPRELOCKDELAY=1.0 hg --config share.pool=racepool --config extensions.lockdelay=$TESTDIR/lockdelay.py clone source1a share-destrace2 > race2.log 2>&1
1119 1119 $ wait
1120 1120
1121 1121 $ hg -R share-destrace1 log -r tip
1122 1122 changeset: 2:e5bfe23c0b47
1123 1123 bookmark: bookA
1124 1124 tag: tip
1125 1125 user: test
1126 1126 date: Thu Jan 01 00:00:00 1970 +0000
1127 1127 summary: 1a
1128 1128
1129 1129
1130 1130 $ hg -R share-destrace2 log -r tip
1131 1131 changeset: 2:e5bfe23c0b47
1132 1132 bookmark: bookA
1133 1133 tag: tip
1134 1134 user: test
1135 1135 date: Thu Jan 01 00:00:00 1970 +0000
1136 1136 summary: 1a
1137 1137
1138 1138 One repo should be new, the other should be shared from the pool. We
1139 1139 don't care which is which, so we just make sure we always print the
1140 1140 one containing "new pooled" first, then one one containing "existing
1141 1141 pooled".
1142 1142
1143 1143 $ (grep 'new pooled' race1.log > /dev/null && cat race1.log || cat race2.log) | grep -v lock
1144 1144 (sharing from new pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1145 1145 requesting all changes
1146 1146 adding changesets
1147 1147 adding manifests
1148 1148 adding file changes
1149 1149 added 3 changesets with 3 changes to 1 files
1150 1150 new changesets b5f04eac9d8f:e5bfe23c0b47
1151 1151 searching for changes
1152 1152 no changes found
1153 1153 adding remote bookmark bookA
1154 1154 updating working directory
1155 1155 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1156 1156
1157 1157 $ (grep 'existing pooled' race1.log > /dev/null && cat race1.log || cat race2.log) | grep -v lock
1158 1158 (sharing from existing pooled repository b5f04eac9d8f7a6a9fcb070243cccea7dc5ea0c1)
1159 1159 searching for changes
1160 1160 no changes found
1161 1161 adding remote bookmark bookA
1162 1162 updating working directory
1163 1163 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1164 1164
1165 1165 SEC: check for unsafe ssh url
1166 1166
1167 1167 $ cat >> $HGRCPATH << EOF
1168 1168 > [ui]
1169 1169 > ssh = sh -c "read l; read l; read l"
1170 1170 > EOF
1171 1171
1172 1172 $ hg clone 'ssh://-oProxyCommand=touch${IFS}owned/path'
1173 1173 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path'
1174 1174 [255]
1175 1175 $ hg clone 'ssh://%2DoProxyCommand=touch${IFS}owned/path'
1176 1176 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch${IFS}owned/path'
1177 1177 [255]
1178 1178 $ hg clone 'ssh://fakehost|touch%20owned/path'
1179 1179 abort: no suitable response from remote hg!
1180 1180 [255]
1181 1181 $ hg clone 'ssh://fakehost%7Ctouch%20owned/path'
1182 1182 abort: no suitable response from remote hg!
1183 1183 [255]
1184 1184
1185 1185 $ hg clone 'ssh://-oProxyCommand=touch owned%20foo@example.com/nonexistent/path'
1186 1186 abort: potentially unsafe url: 'ssh://-oProxyCommand=touch owned foo@example.com/nonexistent/path'
1187 1187 [255]
1188 1188
1189 1189 #if windows
1190 1190 $ hg clone "ssh://%26touch%20owned%20/" --debug
1191 1191 running sh -c "read l; read l; read l" "&touch owned " "hg -R . serve --stdio"
1192 1192 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1193 1193 sending hello command
1194 1194 sending between command
1195 1195 abort: no suitable response from remote hg!
1196 1196 [255]
1197 1197 $ hg clone "ssh://example.com:%26touch%20owned%20/" --debug
1198 1198 running sh -c "read l; read l; read l" -p "&touch owned " example.com "hg -R . serve --stdio"
1199 1199 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1200 1200 sending hello command
1201 1201 sending between command
1202 1202 abort: no suitable response from remote hg!
1203 1203 [255]
1204 1204 #else
1205 1205 $ hg clone "ssh://%3btouch%20owned%20/" --debug
1206 1206 running sh -c "read l; read l; read l" ';touch owned ' 'hg -R . serve --stdio'
1207 1207 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1208 1208 sending hello command
1209 1209 sending between command
1210 1210 abort: no suitable response from remote hg!
1211 1211 [255]
1212 1212 $ hg clone "ssh://example.com:%3btouch%20owned%20/" --debug
1213 1213 running sh -c "read l; read l; read l" -p ';touch owned ' example.com 'hg -R . serve --stdio'
1214 1214 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1215 1215 sending hello command
1216 1216 sending between command
1217 1217 abort: no suitable response from remote hg!
1218 1218 [255]
1219 1219 #endif
1220 1220
1221 1221 $ hg clone "ssh://v-alid.example.com/" --debug
1222 1222 running sh -c "read l; read l; read l" v-alid\.example\.com ['"]hg -R \. serve --stdio['"] (re)
1223 1223 sending upgrade request: * proto=exp-ssh-v2-0003 (glob) (sshv2 !)
1224 1224 sending hello command
1225 1225 sending between command
1226 1226 abort: no suitable response from remote hg!
1227 1227 [255]
1228 1228
1229 1229 We should not have created a file named owned - if it exists, the
1230 1230 attack succeeded.
1231 1231 $ if test -f owned; then echo 'you got owned'; fi
1232 1232
1233 1233 Cloning without fsmonitor enabled does not print a warning for small repos
1234 1234
1235 1235 $ hg clone a fsmonitor-default
1236 1236 updating to bookmark @ on branch stable
1237 1237 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1238 1238
1239 1239 Lower the warning threshold to simulate a large repo
1240 1240
1241 1241 $ cat >> $HGRCPATH << EOF
1242 1242 > [fsmonitor]
1243 1243 > warn_update_file_count = 2
1244 1244 > warn_update_file_count_rust = 2
1245 1245 > EOF
1246 1246
1247 1247 We should see a warning about no fsmonitor on supported platforms
1248 1248
1249 1249 #if linuxormacos no-fsmonitor
1250 1250 $ hg clone a nofsmonitor
1251 1251 updating to bookmark @ on branch stable
1252 1252 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor")
1253 1253 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1254 1254 #else
1255 1255 $ hg clone a nofsmonitor
1256 1256 updating to bookmark @ on branch stable
1257 1257 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1258 1258 #endif
1259 1259
1260 1260 We should not see warning about fsmonitor when it is enabled
1261 1261
1262 1262 #if fsmonitor
1263 1263 $ hg clone a fsmonitor-enabled
1264 1264 updating to bookmark @ on branch stable
1265 1265 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1266 1266 #endif
1267 1267
1268 1268 We can disable the fsmonitor warning
1269 1269
1270 1270 $ hg --config fsmonitor.warn_when_unused=false clone a fsmonitor-disable-warning
1271 1271 updating to bookmark @ on branch stable
1272 1272 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1273 1273
1274 1274 Loaded fsmonitor but disabled in config should still print warning
1275 1275
1276 1276 #if linuxormacos fsmonitor
1277 1277 $ hg --config fsmonitor.mode=off clone a fsmonitor-mode-off
1278 1278 updating to bookmark @ on branch stable
1279 1279 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor") (fsmonitor !)
1280 1280 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1281 1281 #endif
1282 1282
1283 1283 Warning not printed if working directory isn't empty
1284 1284
1285 1285 $ hg -q clone a fsmonitor-update
1286 1286 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor") (?)
1287 1287 $ cd fsmonitor-update
1288 1288 $ hg up acb14030fe0a
1289 1289 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1290 1290 (leaving bookmark @)
1291 1291 $ hg up cf0fe1914066
1292 1292 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1293 1293
1294 1294 `hg update` from null revision also prints
1295 1295
1296 1296 $ hg up null
1297 1297 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1298 1298
1299 1299 #if linuxormacos no-fsmonitor
1300 1300 $ hg up cf0fe1914066
1301 1301 (warning: large working directory being used without fsmonitor enabled; enable fsmonitor to improve performance; see "hg help -e fsmonitor")
1302 1302 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1303 1303 #else
1304 1304 $ hg up cf0fe1914066
1305 1305 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1306 1306 #endif
1307 1307
1308 1308 $ cd ..
1309 1309
@@ -1,120 +1,120 b''
1 1 $ hg init repo
2 2 $ cd repo
3 3 $ for n in 0 1 2 3 4 5 6 7 8 9 10 11; do
4 4 > echo $n > $n
5 5 > hg ci -qAm $n
6 6 > done
7 7
8 8 test revset support
9 9
10 10 $ cat <<'EOF' >> .hg/hgrc
11 11 > [extdata]
12 12 > filedata = file:extdata.txt
13 13 > notes = notes.txt
14 14 > shelldata = shell:cat extdata.txt | grep 2
15 15 > emptygrep = shell:cat extdata.txt | grep empty
16 16 > badparse = shell:cat badparse.txt
17 17 > EOF
18 18 $ cat <<'EOF' > extdata.txt
19 19 > 2 another comment on 2
20 20 > 3
21 21 > EOF
22 22 $ cat <<'EOF' > notes.txt
23 23 > f6ed this change is great!
24 24 > e834 this is buggy :(
25 25 > 0625 first post
26 26 > bogusnode gives no error
27 27 > a ambiguous node gives no error
28 28 > EOF
29 29
30 30 $ hg log -qr "extdata(filedata)"
31 31 2:f6ed99a58333
32 32 3:9de260b1e88e
33 33 $ hg log -qr "extdata(shelldata)"
34 34 2:f6ed99a58333
35 35
36 36 test weight of extdata() revset
37 37
38 38 $ hg debugrevspec -p optimized "extdata(filedata) & 3"
39 39 * optimized:
40 40 (andsmally
41 41 (func
42 42 (symbol 'extdata')
43 43 (symbol 'filedata'))
44 44 (symbol '3'))
45 45 3
46 46
47 47 test non-zero exit of shell command
48 48
49 49 $ hg log -qr "extdata(emptygrep)"
50 50 abort: extdata command 'cat extdata.txt | grep empty' failed: exited with status 1
51 51 [255]
52 52
53 53 test bad extdata() revset source
54 54
55 55 $ hg log -qr "extdata()"
56 56 hg: parse error: extdata takes at least 1 string argument
57 57 [255]
58 58 $ hg log -qr "extdata(unknown)"
59 59 abort: unknown extdata source 'unknown'
60 60 [255]
61 61
62 62 test a zero-exiting source that emits garbage to confuse the revset parser
63 63
64 64 $ cat > badparse.txt <<'EOF'
65 65 > +---------------------------------------+
66 66 > 9de260b1e88e
67 67 > EOF
68 68
69 69 It might be nice if this error message mentioned where the bad string
70 70 came from (eg line X of extdata source S), but the important thing is
71 71 that we don't crash before we can print the parse error.
72 72 $ hg log -qr "extdata(badparse)"
73 73 hg: parse error at 0: not a prefix: +
74 74 (+---------------------------------------+
75 75 ^ here)
76 76 [255]
77 77
78 78 test template support:
79 79
80 80 $ hg log -r:3 -T "{node|short}{if(extdata('notes'), ' # {extdata('notes')}')}\n"
81 81 06254b906311 # first post
82 82 e8342c9a2ed1 # this is buggy :(
83 83 f6ed99a58333 # this change is great!
84 84 9de260b1e88e
85 85
86 86 test template cache:
87 87
88 88 $ hg log -r:3 -T '{rev} "{extdata("notes")}" "{extdata("shelldata")}"\n'
89 89 0 "first post" ""
90 90 1 "this is buggy :(" ""
91 91 2 "this change is great!" "another comment on 2"
92 92 3 "" ""
93 93
94 94 test bad extdata() template source
95 95
96 96 $ hg log -T "{extdata()}\n"
97 97 hg: parse error: extdata expects one argument
98 98 [255]
99 99 $ hg log -T "{extdata('unknown')}\n"
100 100 abort: unknown extdata source 'unknown'
101 101 [255]
102 102 $ hg log -T "{extdata(unknown)}\n"
103 103 hg: parse error: empty data source specified
104 104 (did you mean extdata('unknown')?)
105 105 [255]
106 106 $ hg log -T "{extdata('{unknown}')}\n"
107 107 hg: parse error: empty data source specified
108 108 [255]
109 109
110 110 we don't fix up relative file URLs, but we do run shell commands in repo root
111 111
112 112 $ mkdir sub
113 113 $ cd sub
114 114 $ hg log -qr "extdata(filedata)"
115 115 abort: error: $ENOENT$
116 [255]
116 [100]
117 117 $ hg log -qr "extdata(shelldata)"
118 118 2:f6ed99a58333
119 119
120 120 $ cd ..
@@ -1,1306 +1,1306 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 [255]
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 [255]
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 [255]
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 [255]
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 [255]
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 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 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 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 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 !)
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 129 write(21) -> Content-Length: 450\r\n (no-py3 !)
130 130 write(2) -> \r\n (no-py3 !)
131 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 !)
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 [255]
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 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 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 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 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 !)
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 174 write(21) -> Content-Length: 450\r\n (no-py3 !)
175 175 write(2) -> \r\n (no-py3 !)
176 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 !)
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 [255]
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 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 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 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 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 !)
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 239 write(21) -> Content-Length: 463\r\n (no-py3 !)
240 240 write(2) -> \r\n (no-py3 !)
241 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 !)
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 [255]
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 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 !)
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 310 abort: HTTP request error (incomplete response; expected 450 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 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 324 sendall(20 from 450) -> (0) batch branchmap bund (py36 !)
325 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 326 write(20 from 450) -> (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 331 write(21 from 21) -> (22) Content-Length: 450\r\n (no-py3 !)
332 332 write(2 from 2) -> (20) \r\n (no-py3 !)
333 333 write(20 from 450) -> (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 344 $ hg serve --config badserver.closeaftersendbytes=728 -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 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 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 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 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 370 write(36 from 36) -> (692) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
371 371 write(23 from 23) -> (669) Server: badhttpserver\r\n (no-py3 !)
372 372 write(37 from 37) -> (632) Date: $HTTP_DATE$\r\n (no-py3 !)
373 373 write(41 from 41) -> (591) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
374 374 write(21 from 21) -> (570) Content-Length: 450\r\n (no-py3 !)
375 375 write(2 from 2) -> (568) \r\n (no-py3 !)
376 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 !)
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 404 $ hg serve --config badserver.closeaftersendbytes=793 -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 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 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 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 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 429 write(36 from 36) -> (757) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
430 430 write(23 from 23) -> (734) Server: badhttpserver\r\n (no-py3 !)
431 431 write(37 from 37) -> (697) Date: $HTTP_DATE$\r\n (no-py3 !)
432 432 write(41 from 41) -> (656) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
433 433 write(21 from 21) -> (635) Content-Length: 450\r\n (no-py3 !)
434 434 write(2 from 2) -> (633) \r\n (no-py3 !)
435 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 !)
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 466 $ hg serve --config badserver.closeaftersendbytes=940 -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 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 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 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 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 493 write(36 from 36) -> (904) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
494 494 write(23 from 23) -> (881) Server: badhttpserver\r\n (no-py3 !)
495 495 write(37 from 37) -> (844) Date: $HTTP_DATE$\r\n (no-py3 !)
496 496 write(41 from 41) -> (803) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
497 497 write(21 from 21) -> (782) Content-Length: 450\r\n (no-py3 !)
498 498 write(2 from 2) -> (780) \r\n (no-py3 !)
499 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 !)
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 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)
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 547 $ hg serve --config badserver.closeaftersendbytes=973 -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 576 $ hg serve --config badserver.closeaftersendbytes=978 -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 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 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 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 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 598 write(36 from 36) -> (942) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
599 599 write(23 from 23) -> (919) Server: badhttpserver\r\n (no-py3 !)
600 600 write(37 from 37) -> (882) Date: $HTTP_DATE$\r\n (no-py3 !)
601 601 write(41 from 41) -> (841) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
602 602 write(21 from 21) -> (820) Content-Length: 450\r\n (no-py3 !)
603 603 write(2 from 2) -> (818) \r\n (no-py3 !)
604 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 !)
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 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)
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 654 $ hg serve --config badserver.closeaftersendbytes=1002 -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 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 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 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 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 676 write(36 from 36) -> (966) HTTP/1.1 200 Script output follows\r\n (no-py3 !)
677 677 write(23 from 23) -> (943) Server: badhttpserver\r\n (no-py3 !)
678 678 write(37 from 37) -> (906) Date: $HTTP_DATE$\r\n (no-py3 !)
679 679 write(41 from 41) -> (865) Content-Type: application/mercurial-0.1\r\n (no-py3 !)
680 680 write(21 from 21) -> (844) Content-Length: 450\r\n (no-py3 !)
681 681 write(2 from 2) -> (842) \r\n (no-py3 !)
682 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 !)
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 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)
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 736 $ hg serve --config badserver.closeaftersendbytes=999 -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 781 $ hg serve --config badserver.closeaftersendbytes=1008 -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 828 $ hg serve --config badserver.closeaftersendbytes=1011 -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 874 $ hg serve --config badserver.closeaftersendbytes=1020 -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 923 $ hg serve --config badserver.closeaftersendbytes=1067 -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 976 $ hg serve --config badserver.closeaftersendbytes=1088 -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 1032 $ hg serve --config badserver.closeaftersendbytes=1549 -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 1089 $ hg serve --config badserver.closeaftersendbytes=1580 -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 1151 # $ hg serve --config badserver.closeaftersendbytes=1755 -p $HGPORT -d --pid-file=hg.pid -E error.log
1152 1152 $ hg serve --config badserver.closeaftersendbytes=1862 -p $HGPORT -d --pid-file=hg.pid -E error.log
1153 1153 $ cat hg.pid > $DAEMON_PIDS
1154 1154
1155 1155 $ hg clone http://localhost:$HGPORT/ clone
1156 1156 requesting all changes
1157 1157 adding changesets
1158 1158 adding manifests
1159 1159 adding file changes
1160 1160 added 1 changesets with 1 changes to 1 files
1161 1161 new changesets 96ee1d7354c4
1162 1162 updating to branch default
1163 1163 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1164 1164
1165 1165 $ killdaemons.py $DAEMON_PIDS
1166 1166
1167 1167 #if py36
1168 1168 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -25
1169 1169 sendall(9 from 9) -> (851) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1170 1170 sendall(9 from 9) -> (842) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1171 1171 sendall(47 from 47) -> (795) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1172 1172 sendall(9 from 9) -> (786) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1173 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 1174 sendall(9 from 9) -> (304) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1175 1175 sendall(9 from 9) -> (295) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1176 1176 sendall(38 from 38) -> (257) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1177 1177 sendall(9 from 9) -> (248) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1178 1178 sendall(64 from 64) -> (184) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1179 1179 sendall(9 from 9) -> (175) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1180 1180 sendall(9 from 9) -> (166) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1181 1181 sendall(41 from 41) -> (125) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1182 1182 sendall(9 from 9) -> (116) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1183 1183 sendall(9 from 9) -> (107) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
1184 1184 sendall(35 from 35) -> (72) 1d\\r\\n\x16cache:rev-branch-cache\x00\x00\x00\x03\x00\x00\\r\\n (esc)
1185 1185 sendall(9 from 9) -> (63) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
1186 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)
1187 1187 sendall(9 from 9) -> (9) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1188 1188 sendall(9 from 9) -> (0) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1189 1189 write limit reached; closing socket
1190 1190 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1191 1191 Traceback (most recent call last):
1192 1192 Exception: connection closed after sending N bytes
1193 1193
1194 1194
1195 1195 #else
1196 1196 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -26
1197 1197 write(9 from 9) -> (851) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1198 1198 write(9 from 9) -> (842) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1199 1199 write(47 from 47) -> (795) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1200 1200 write(9 from 9) -> (786) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1201 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 1202 write(9 from 9) -> (304) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1203 1203 write(9 from 9) -> (295) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1204 1204 write(38 from 38) -> (257) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1205 1205 write(9 from 9) -> (248) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1206 1206 write(64 from 64) -> (184) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1207 1207 write(9 from 9) -> (175) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1208 1208 write(9 from 9) -> (166) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1209 1209 write(41 from 41) -> (125) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1210 1210 write(9 from 9) -> (116) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1211 1211 write(9 from 9) -> (107) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
1212 1212 write(35 from 35) -> (72) 1d\\r\\n\x16cache:rev-branch-cache\x00\x00\x00\x03\x00\x00\\r\\n (esc)
1213 1213 write(9 from 9) -> (63) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
1214 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)
1215 1215 write(9 from 9) -> (9) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1216 1216 write(9 from 9) -> (0) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1217 1217 write limit reached; closing socket
1218 1218 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1219 1219 Traceback (most recent call last):
1220 1220 Exception: connection closed after sending N bytes
1221 1221
1222 1222 write(27) -> 15\r\nInternal Server Error\r\n
1223 1223 #endif
1224 1224
1225 1225 $ rm -f error.log
1226 1226 $ rm -rf clone
1227 1227
1228 1228 Server sends a size 0 chunked-transfer size without terminating \r\n
1229 1229
1230 1230 $ hg serve --config badserver.closeaftersendbytes=1865 -p $HGPORT -d --pid-file=hg.pid -E error.log
1231 1231 $ cat hg.pid > $DAEMON_PIDS
1232 1232
1233 1233 $ hg clone http://localhost:$HGPORT/ clone
1234 1234 requesting all changes
1235 1235 adding changesets
1236 1236 adding manifests
1237 1237 adding file changes
1238 1238 added 1 changesets with 1 changes to 1 files
1239 1239 new changesets 96ee1d7354c4
1240 1240 updating to branch default
1241 1241 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1242 1242
1243 1243 $ killdaemons.py $DAEMON_PIDS
1244 1244
1245 1245 #if py36
1246 1246 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -26
1247 1247 sendall(9 from 9) -> (854) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1248 1248 sendall(9 from 9) -> (845) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1249 1249 sendall(47 from 47) -> (798) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1250 1250 sendall(9 from 9) -> (789) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1251 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 1252 sendall(9 from 9) -> (307) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1253 1253 sendall(9 from 9) -> (298) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1254 1254 sendall(38 from 38) -> (260) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1255 1255 sendall(9 from 9) -> (251) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1256 1256 sendall(64 from 64) -> (187) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1257 1257 sendall(9 from 9) -> (178) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1258 1258 sendall(9 from 9) -> (169) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1259 1259 sendall(41 from 41) -> (128) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1260 1260 sendall(9 from 9) -> (119) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1261 1261 sendall(9 from 9) -> (110) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
1262 1262 sendall(35 from 35) -> (75) 1d\\r\\n\x16cache:rev-branch-cache\x00\x00\x00\x03\x00\x00\\r\\n (esc)
1263 1263 sendall(9 from 9) -> (66) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
1264 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)
1265 1265 sendall(9 from 9) -> (12) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1266 1266 sendall(9 from 9) -> (3) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1267 1267 sendall(3 from 5) -> (0) 0\r\n
1268 1268 write limit reached; closing socket
1269 1269 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1270 1270 Traceback (most recent call last):
1271 1271 Exception: connection closed after sending N bytes
1272 1272
1273 1273
1274 1274 #else
1275 1275 $ "$PYTHON" $TESTDIR/filtertraceback.py < error.log | tail -27
1276 1276 write(9 from 9) -> (854) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1277 1277 write(9 from 9) -> (845) 4\\r\\n\x00\x00\x00)\\r\\n (esc)
1278 1278 write(47 from 47) -> (798) 29\\r\\n\x0bCHANGEGROUP\x00\x00\x00\x00\x01\x01\x07\x02 \x01version02nbchanges1\\r\\n (esc)
1279 1279 write(9 from 9) -> (789) 4\\r\\n\x00\x00\x01\xd2\\r\\n (esc)
1280 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 1281 write(9 from 9) -> (307) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1282 1282 write(9 from 9) -> (298) 4\\r\\n\x00\x00\x00 \\r\\n (esc)
1283 1283 write(38 from 38) -> (260) 20\\r\\n\x08LISTKEYS\x00\x00\x00\x01\x01\x00 \x06namespacephases\\r\\n (esc)
1284 1284 write(9 from 9) -> (251) 4\\r\\n\x00\x00\x00:\\r\\n (esc)
1285 1285 write(64 from 64) -> (187) 3a\r\n96ee1d7354c4ad7372047672c36a1f561e3a6a4c 1\npublishing True\r\n
1286 1286 write(9 from 9) -> (178) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1287 1287 write(9 from 9) -> (169) 4\\r\\n\x00\x00\x00#\\r\\n (esc)
1288 1288 write(41 from 41) -> (128) 23\\r\\n\x08LISTKEYS\x00\x00\x00\x02\x01\x00 namespacebookmarks\\r\\n (esc)
1289 1289 write(9 from 9) -> (119) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1290 1290 write(9 from 9) -> (110) 4\\r\\n\x00\x00\x00\x1d\\r\\n (esc)
1291 1291 write(35 from 35) -> (75) 1d\\r\\n\x16cache:rev-branch-cache\x00\x00\x00\x03\x00\x00\\r\\n (esc)
1292 1292 write(9 from 9) -> (66) 4\\r\\n\x00\x00\x00'\\r\\n (esc)
1293 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)
1294 1294 write(9 from 9) -> (12) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1295 1295 write(9 from 9) -> (3) 4\\r\\n\x00\x00\x00\x00\\r\\n (esc)
1296 1296 write(3 from 5) -> (0) 0\r\n
1297 1297 write limit reached; closing socket
1298 1298 $LOCALIP - - [$ERRDATE$] Exception happened during processing request '/?cmd=getbundle': (glob)
1299 1299 Traceback (most recent call last):
1300 1300 Exception: connection closed after sending N bytes
1301 1301
1302 1302 write(27) -> 15\r\nInternal Server Error\r\n
1303 1303 #endif
1304 1304
1305 1305 $ rm -f error.log
1306 1306 $ rm -rf clone
@@ -1,410 +1,410 b''
1 1 #require serve
2 2
3 3 This test is a duplicate of 'test-http.t', feel free to factor out
4 4 parts that are not bundle1/bundle2 specific.
5 5
6 6 $ cat << EOF >> $HGRCPATH
7 7 > [devel]
8 8 > # This test is dedicated to interaction through old bundle
9 9 > legacy.exchange = bundle1
10 10 > EOF
11 11
12 12 $ hg init test
13 13 $ cd test
14 14 $ echo foo>foo
15 15 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
16 16 $ echo foo>foo.d/foo
17 17 $ echo bar>foo.d/bAr.hg.d/BaR
18 18 $ echo bar>foo.d/baR.d.hg/bAR
19 19 $ hg commit -A -m 1
20 20 adding foo
21 21 adding foo.d/bAr.hg.d/BaR
22 22 adding foo.d/baR.d.hg/bAR
23 23 adding foo.d/foo
24 24 $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log
25 25 $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid
26 26
27 27 Test server address cannot be reused
28 28
29 29 $ hg serve -p $HGPORT1 2>&1
30 30 abort: cannot start server at 'localhost:$HGPORT1': $EADDRINUSE$
31 31 [255]
32 32
33 33 $ cd ..
34 34 $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
35 35
36 36 clone via stream
37 37
38 38 #if no-reposimplestore
39 39 $ hg clone --stream http://localhost:$HGPORT/ copy 2>&1
40 40 streaming all changes
41 41 6 files to transfer, 606 bytes of data
42 42 transferred * bytes in * seconds (*/sec) (glob)
43 43 searching for changes
44 44 no changes found
45 45 updating to branch default
46 46 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
47 47 $ hg verify -R copy
48 48 checking changesets
49 49 checking manifests
50 50 crosschecking files in changesets and manifests
51 51 checking files
52 52 checked 1 changesets with 4 changes to 4 files
53 53 #endif
54 54
55 55 try to clone via stream, should use pull instead
56 56
57 57 $ hg clone --stream http://localhost:$HGPORT1/ copy2
58 58 warning: stream clone requested but server has them disabled
59 59 requesting all changes
60 60 adding changesets
61 61 adding manifests
62 62 adding file changes
63 63 added 1 changesets with 4 changes to 4 files
64 64 new changesets 8b6053c928fe
65 65 updating to branch default
66 66 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 67
68 68 try to clone via stream but missing requirements, so should use pull instead
69 69
70 70 $ cat > $TESTTMP/removesupportedformat.py << EOF
71 71 > from mercurial import localrepo
72 72 > def extsetup(ui):
73 73 > localrepo.localrepository.supportedformats.remove(b'generaldelta')
74 74 > EOF
75 75
76 76 $ hg clone --config extensions.rsf=$TESTTMP/removesupportedformat.py --stream http://localhost:$HGPORT/ copy3
77 77 warning: stream clone requested but client is missing requirements: generaldelta
78 78 (see https://www.mercurial-scm.org/wiki/MissingRequirement for more information)
79 79 requesting all changes
80 80 adding changesets
81 81 adding manifests
82 82 adding file changes
83 83 added 1 changesets with 4 changes to 4 files
84 84 new changesets 8b6053c928fe
85 85 updating to branch default
86 86 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 87
88 88 clone via pull
89 89
90 90 $ hg clone http://localhost:$HGPORT1/ copy-pull
91 91 requesting all changes
92 92 adding changesets
93 93 adding manifests
94 94 adding file changes
95 95 added 1 changesets with 4 changes to 4 files
96 96 new changesets 8b6053c928fe
97 97 updating to branch default
98 98 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 99 $ hg verify -R copy-pull
100 100 checking changesets
101 101 checking manifests
102 102 crosschecking files in changesets and manifests
103 103 checking files
104 104 checked 1 changesets with 4 changes to 4 files
105 105 $ cd test
106 106 $ echo bar > bar
107 107 $ hg commit -A -d '1 0' -m 2
108 108 adding bar
109 109 $ cd ..
110 110
111 111 clone over http with --update
112 112
113 113 $ hg clone http://localhost:$HGPORT1/ updated --update 0
114 114 requesting all changes
115 115 adding changesets
116 116 adding manifests
117 117 adding file changes
118 118 added 2 changesets with 5 changes to 5 files
119 119 new changesets 8b6053c928fe:5fed3813f7f5
120 120 updating to branch default
121 121 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
122 122 $ hg log -r . -R updated
123 123 changeset: 0:8b6053c928fe
124 124 user: test
125 125 date: Thu Jan 01 00:00:00 1970 +0000
126 126 summary: 1
127 127
128 128 $ rm -rf updated
129 129
130 130 incoming via HTTP
131 131
132 132 $ hg clone http://localhost:$HGPORT1/ --rev 0 partial
133 133 adding changesets
134 134 adding manifests
135 135 adding file changes
136 136 added 1 changesets with 4 changes to 4 files
137 137 new changesets 8b6053c928fe
138 138 updating to branch default
139 139 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 140 $ cd partial
141 141 $ touch LOCAL
142 142 $ hg ci -qAm LOCAL
143 143 $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n'
144 144 comparing with http://localhost:$HGPORT1/
145 145 searching for changes
146 146 2
147 147 $ cd ..
148 148
149 149 pull
150 150
151 151 $ cd copy-pull
152 152 $ cat >> .hg/hgrc <<EOF
153 153 > [hooks]
154 154 > changegroup = sh -c "printenv.py --line changegroup"
155 155 > EOF
156 156 $ hg pull
157 157 pulling from http://localhost:$HGPORT1/
158 158 searching for changes
159 159 adding changesets
160 160 adding manifests
161 161 adding file changes
162 162 added 1 changesets with 1 changes to 1 files
163 163 new changesets 5fed3813f7f5
164 164 changegroup hook: HG_HOOKNAME=changegroup
165 165 HG_HOOKTYPE=changegroup
166 166 HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d
167 167 HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d
168 168 HG_SOURCE=pull
169 169 HG_TXNID=TXN:$ID$
170 170 HG_TXNNAME=pull
171 171 http://localhost:$HGPORT1/
172 172 HG_URL=http://localhost:$HGPORT1/
173 173
174 174 (run 'hg update' to get a working copy)
175 175 $ cd ..
176 176
177 177 clone from invalid URL
178 178
179 179 $ hg clone http://localhost:$HGPORT/bad
180 180 abort: HTTP Error 404: Not Found
181 [255]
181 [100]
182 182
183 183 test http authentication
184 184 + use the same server to test server side streaming preference
185 185
186 186 $ cd test
187 187
188 188 $ hg serve --config extensions.x=$TESTDIR/httpserverauth.py -p $HGPORT2 -d \
189 189 > --pid-file=pid --config server.preferuncompressed=True \
190 190 > --config web.push_ssl=False --config web.allow_push=* -A ../access.log
191 191 $ cat pid >> $DAEMON_PIDS
192 192
193 193 $ cat << EOF > get_pass.py
194 194 > import getpass
195 195 > def newgetpass(arg):
196 196 > return "pass"
197 197 > getpass.getpass = newgetpass
198 198 > EOF
199 199
200 200 $ hg id http://localhost:$HGPORT2/
201 201 abort: http authorization required for http://localhost:$HGPORT2/
202 202 [255]
203 203 $ hg id http://localhost:$HGPORT2/
204 204 abort: http authorization required for http://localhost:$HGPORT2/
205 205 [255]
206 206 $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
207 207 http authorization required for http://localhost:$HGPORT2/
208 208 realm: mercurial
209 209 user: user
210 210 password: 5fed3813f7f5
211 211 $ hg id http://user:pass@localhost:$HGPORT2/
212 212 5fed3813f7f5
213 213 $ echo '[auth]' >> .hg/hgrc
214 214 $ echo 'l.schemes=http' >> .hg/hgrc
215 215 $ echo 'l.prefix=lo' >> .hg/hgrc
216 216 $ echo 'l.username=user' >> .hg/hgrc
217 217 $ echo 'l.password=pass' >> .hg/hgrc
218 218 $ hg id http://localhost:$HGPORT2/
219 219 5fed3813f7f5
220 220 $ hg id http://localhost:$HGPORT2/
221 221 5fed3813f7f5
222 222 $ hg id http://user@localhost:$HGPORT2/
223 223 5fed3813f7f5
224 224
225 225 #if no-reposimplestore
226 226 $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1
227 227 streaming all changes
228 228 7 files to transfer, 916 bytes of data
229 229 transferred * bytes in * seconds (*/sec) (glob)
230 230 searching for changes
231 231 no changes found
232 232 updating to branch default
233 233 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
234 234 #endif
235 235
236 236 --pull should override server's preferuncompressed
237 237
238 238 $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1
239 239 requesting all changes
240 240 adding changesets
241 241 adding manifests
242 242 adding file changes
243 243 added 2 changesets with 5 changes to 5 files
244 244 new changesets 8b6053c928fe:5fed3813f7f5
245 245 updating to branch default
246 246 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
247 247
248 248 $ hg id http://user2@localhost:$HGPORT2/
249 249 abort: http authorization required for http://localhost:$HGPORT2/
250 250 [255]
251 251 $ hg id http://user:pass2@localhost:$HGPORT2/
252 252 abort: HTTP Error 403: no
253 [255]
253 [100]
254 254
255 255 $ hg -R dest-pull tag -r tip top
256 256 $ hg -R dest-pull push http://user:pass@localhost:$HGPORT2/
257 257 pushing to http://user:***@localhost:$HGPORT2/
258 258 searching for changes
259 259 remote: adding changesets
260 260 remote: adding manifests
261 261 remote: adding file changes
262 262 remote: added 1 changesets with 1 changes to 1 files
263 263 $ hg rollback -q
264 264
265 265 $ sed 's/.*] "/"/' < ../access.log
266 266 "GET /?cmd=capabilities HTTP/1.1" 401 -
267 267 "GET /?cmd=capabilities HTTP/1.1" 401 -
268 268 "GET /?cmd=capabilities HTTP/1.1" 401 -
269 269 "GET /?cmd=capabilities HTTP/1.1" 200 -
270 270 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
271 271 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
272 272 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
273 273 "GET /?cmd=capabilities HTTP/1.1" 401 -
274 274 "GET /?cmd=capabilities HTTP/1.1" 200 -
275 275 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
276 276 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
277 277 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
278 278 "GET /?cmd=capabilities HTTP/1.1" 401 -
279 279 "GET /?cmd=capabilities HTTP/1.1" 200 -
280 280 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
281 281 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
282 282 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
283 283 "GET /?cmd=capabilities HTTP/1.1" 401 -
284 284 "GET /?cmd=capabilities HTTP/1.1" 200 -
285 285 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
286 286 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
287 287 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
288 288 "GET /?cmd=capabilities HTTP/1.1" 401 -
289 289 "GET /?cmd=capabilities HTTP/1.1" 200 -
290 290 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
291 291 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
292 292 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
293 293 "GET /?cmd=capabilities HTTP/1.1" 401 - (no-reposimplestore !)
294 294 "GET /?cmd=capabilities HTTP/1.1" 200 - (no-reposimplestore !)
295 295 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (no-reposimplestore !)
296 296 "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (no-reposimplestore !)
297 297 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (no-reposimplestore !)
298 298 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (no-reposimplestore !)
299 299 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (no-reposimplestore !)
300 300 "GET /?cmd=capabilities HTTP/1.1" 401 - (no-reposimplestore !)
301 301 "GET /?cmd=capabilities HTTP/1.1" 200 - (no-reposimplestore !)
302 302 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (no-reposimplestore !)
303 303 "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
304 304 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
305 305 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
306 306 "GET /?cmd=capabilities HTTP/1.1" 401 -
307 307 "GET /?cmd=capabilities HTTP/1.1" 401 -
308 308 "GET /?cmd=capabilities HTTP/1.1" 403 -
309 309 "GET /?cmd=capabilities HTTP/1.1" 401 -
310 310 "GET /?cmd=capabilities HTTP/1.1" 200 -
311 311 "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
312 312 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
313 313 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
314 314 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
315 315 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
316 316 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=686173686564+5eb5abfefeea63c80dd7553bcc3783f37e0c5524* (glob)
317 317 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull
318 318
319 319 $ cd ..
320 320
321 321 clone of serve with repo in root and unserved subrepo (issue2970)
322 322
323 323 $ hg --cwd test init sub
324 324 $ echo empty > test/sub/empty
325 325 $ hg --cwd test/sub add empty
326 326 $ hg --cwd test/sub commit -qm 'add empty'
327 327 $ hg --cwd test/sub tag -r 0 something
328 328 $ echo sub = sub > test/.hgsub
329 329 $ hg --cwd test add .hgsub
330 330 $ hg --cwd test commit -qm 'add subrepo'
331 331 $ hg clone http://localhost:$HGPORT noslash-clone
332 332 requesting all changes
333 333 adding changesets
334 334 adding manifests
335 335 adding file changes
336 336 added 3 changesets with 7 changes to 7 files
337 337 new changesets 8b6053c928fe:56f9bc90cce6
338 338 updating to branch default
339 339 cloning subrepo sub from http://localhost:$HGPORT/sub
340 340 abort: HTTP Error 404: Not Found
341 [255]
341 [100]
342 342 $ hg clone http://localhost:$HGPORT/ slash-clone
343 343 requesting all changes
344 344 adding changesets
345 345 adding manifests
346 346 adding file changes
347 347 added 3 changesets with 7 changes to 7 files
348 348 new changesets 8b6053c928fe:56f9bc90cce6
349 349 updating to branch default
350 350 cloning subrepo sub from http://localhost:$HGPORT/sub
351 351 abort: HTTP Error 404: Not Found
352 [255]
352 [100]
353 353
354 354 check error log
355 355
356 356 $ cat error.log
357 357
358 358 Check error reporting while pulling/cloning
359 359
360 360 $ $RUNTESTDIR/killdaemons.py
361 361 $ hg serve -R test -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py
362 362 $ cat hg3.pid >> $DAEMON_PIDS
363 363 $ hg clone http://localhost:$HGPORT/ abort-clone
364 364 requesting all changes
365 365 abort: remote error:
366 366 this is an exercise
367 [255]
367 [100]
368 368 $ cat error.log
369 369
370 370 disable pull-based clones
371 371
372 372 $ hg serve -R test -p $HGPORT1 -d --pid-file=hg4.pid -E error.log --config server.disablefullbundle=True
373 373 $ cat hg4.pid >> $DAEMON_PIDS
374 374 $ hg clone http://localhost:$HGPORT1/ disable-pull-clone
375 375 requesting all changes
376 376 abort: remote error:
377 377 server has pull-based clones disabled
378 [255]
378 [100]
379 379
380 380 #if no-reposimplestore
381 381 ... but keep stream clones working
382 382
383 383 $ hg clone --stream --noupdate http://localhost:$HGPORT1/ test-stream-clone
384 384 streaming all changes
385 385 * files to transfer, * of data (glob)
386 386 transferred * in * seconds (* KB/sec) (glob)
387 387 searching for changes
388 388 no changes found
389 389 #endif
390 390
391 391 ... and also keep partial clones and pulls working
392 392 $ hg clone http://localhost:$HGPORT1 --rev 0 test-partial-clone
393 393 adding changesets
394 394 adding manifests
395 395 adding file changes
396 396 added 1 changesets with 4 changes to 4 files
397 397 new changesets 8b6053c928fe
398 398 updating to branch default
399 399 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 400 $ hg pull -R test-partial-clone
401 401 pulling from http://localhost:$HGPORT1/
402 402 searching for changes
403 403 adding changesets
404 404 adding manifests
405 405 adding file changes
406 406 added 2 changesets with 3 changes to 3 files
407 407 new changesets 5fed3813f7f5:56f9bc90cce6
408 408 (run 'hg update' to get a working copy)
409 409
410 410 $ cat error.log
@@ -1,1498 +1,1498 b''
1 1 $ cat > fakeremoteuser.py << EOF
2 2 > import os
3 3 > from mercurial.hgweb import hgweb_mod
4 4 > from mercurial import wireprotov1server
5 5 > class testenvhgweb(hgweb_mod.hgweb):
6 6 > def __call__(self, env, respond):
7 7 > # Allow REMOTE_USER to define authenticated user.
8 8 > if r'REMOTE_USER' in os.environ:
9 9 > env[r'REMOTE_USER'] = os.environ[r'REMOTE_USER']
10 10 > # Allow REQUEST_METHOD to override HTTP method
11 11 > if r'REQUEST_METHOD' in os.environ:
12 12 > env[r'REQUEST_METHOD'] = os.environ[r'REQUEST_METHOD']
13 13 > return super(testenvhgweb, self).__call__(env, respond)
14 14 > hgweb_mod.hgweb = testenvhgweb
15 15 >
16 16 > @wireprotov1server.wireprotocommand(b'customreadnoperm')
17 17 > def customread(repo, proto):
18 18 > return b'read-only command no defined permissions\n'
19 19 > @wireprotov1server.wireprotocommand(b'customwritenoperm')
20 20 > def customwritenoperm(repo, proto):
21 21 > return b'write command no defined permissions\n'
22 22 > @wireprotov1server.wireprotocommand(b'customreadwithperm', permission=b'pull')
23 23 > def customreadwithperm(repo, proto):
24 24 > return b'read-only command w/ defined permissions\n'
25 25 > @wireprotov1server.wireprotocommand(b'customwritewithperm', permission=b'push')
26 26 > def customwritewithperm(repo, proto):
27 27 > return b'write command w/ defined permissions\n'
28 28 > EOF
29 29
30 30 $ cat >> $HGRCPATH << EOF
31 31 > [extensions]
32 32 > fakeremoteuser = $TESTTMP/fakeremoteuser.py
33 33 > strip =
34 34 > EOF
35 35
36 36 $ hg init test
37 37 $ cd test
38 38 $ echo a > a
39 39 $ hg ci -Ama
40 40 adding a
41 41 $ cd ..
42 42 $ hg clone test test2
43 43 updating to branch default
44 44 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 45 $ cd test2
46 46 $ echo a >> a
47 47 $ hg ci -mb
48 48 $ hg book bm -r 0
49 49 $ cd ../test
50 50
51 51 web.deny_read=* prevents access to wire protocol for all users
52 52
53 53 $ cat > .hg/hgrc <<EOF
54 54 > [web]
55 55 > deny_read = *
56 56 > EOF
57 57
58 58 $ hg serve -p $HGPORT -d --pid-file hg.pid
59 59 $ cat hg.pid > $DAEMON_PIDS
60 60
61 61 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities'
62 62 401 read not authorized
63 63
64 64 0
65 65 read not authorized
66 66 [1]
67 67
68 68 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out'
69 69 401 read not authorized
70 70
71 71 0
72 72 read not authorized
73 73 [1]
74 74
75 75 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
76 76 401 read not authorized
77 77
78 78 0
79 79 read not authorized
80 80 [1]
81 81
82 82 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
83 83 401 read not authorized
84 84
85 85 0
86 86 read not authorized
87 87 [1]
88 88
89 89 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
90 90 401 read not authorized
91 91
92 92 0
93 93 read not authorized
94 94 [1]
95 95
96 96 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
97 97 401 read not authorized
98 98
99 99 0
100 100 read not authorized
101 101 [1]
102 102
103 103 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
104 104 401 read not authorized
105 105
106 106 0
107 107 read not authorized
108 108 [1]
109 109
110 110 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
111 111 401 read not authorized
112 112
113 113 0
114 114 read not authorized
115 115 [1]
116 116
117 117 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
118 118 pulling from http://localhost:$HGPORT/
119 119 abort: authorization failed
120 120 [255]
121 121
122 122 $ killdaemons.py
123 123
124 124 web.deny_read=* with REMOTE_USER set still locks out clients
125 125
126 126 $ REMOTE_USER=authed_user hg serve -p $HGPORT -d --pid-file hg.pid
127 127 $ cat hg.pid > $DAEMON_PIDS
128 128
129 129 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities'
130 130 401 read not authorized
131 131
132 132 0
133 133 read not authorized
134 134 [1]
135 135
136 136 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out'
137 137 401 read not authorized
138 138
139 139 0
140 140 read not authorized
141 141 [1]
142 142
143 143 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
144 144 401 read not authorized
145 145
146 146 0
147 147 read not authorized
148 148 [1]
149 149
150 150 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
151 151 401 read not authorized
152 152
153 153 0
154 154 read not authorized
155 155 [1]
156 156
157 157 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
158 158 401 read not authorized
159 159
160 160 0
161 161 read not authorized
162 162 [1]
163 163
164 164 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
165 165 401 read not authorized
166 166
167 167 0
168 168 read not authorized
169 169 [1]
170 170
171 171 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
172 172 401 read not authorized
173 173
174 174 0
175 175 read not authorized
176 176 [1]
177 177
178 178 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
179 179 pulling from http://localhost:$HGPORT/
180 180 abort: authorization failed
181 181 [255]
182 182
183 183 $ killdaemons.py
184 184
185 185 web.deny_read=<user> denies access to unauthenticated user
186 186
187 187 $ cat > .hg/hgrc <<EOF
188 188 > [web]
189 189 > deny_read = baduser1,baduser2
190 190 > EOF
191 191
192 192 $ hg serve -p $HGPORT -d --pid-file hg.pid
193 193 $ cat hg.pid > $DAEMON_PIDS
194 194
195 195 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
196 196 401 read not authorized
197 197
198 198 0
199 199 read not authorized
200 200 [1]
201 201
202 202 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
203 203 401 read not authorized
204 204
205 205 0
206 206 read not authorized
207 207 [1]
208 208
209 209 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
210 210 401 read not authorized
211 211
212 212 0
213 213 read not authorized
214 214 [1]
215 215
216 216 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
217 217 401 read not authorized
218 218
219 219 0
220 220 read not authorized
221 221 [1]
222 222
223 223 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
224 224 401 read not authorized
225 225
226 226 0
227 227 read not authorized
228 228 [1]
229 229
230 230 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
231 231 401 read not authorized
232 232
233 233 0
234 234 read not authorized
235 235 [1]
236 236
237 237 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
238 238 pulling from http://localhost:$HGPORT/
239 239 abort: authorization failed
240 240 [255]
241 241
242 242 $ killdaemons.py
243 243
244 244 web.deny_read=<user> denies access to users in deny list
245 245
246 246 $ REMOTE_USER=baduser2 hg serve -p $HGPORT -d --pid-file hg.pid
247 247 $ cat hg.pid > $DAEMON_PIDS
248 248
249 249 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
250 250 401 read not authorized
251 251
252 252 0
253 253 read not authorized
254 254 [1]
255 255
256 256 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
257 257 401 read not authorized
258 258
259 259 0
260 260 read not authorized
261 261 [1]
262 262
263 263 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
264 264 401 read not authorized
265 265
266 266 0
267 267 read not authorized
268 268 [1]
269 269
270 270 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
271 271 401 read not authorized
272 272
273 273 0
274 274 read not authorized
275 275 [1]
276 276
277 277 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
278 278 401 read not authorized
279 279
280 280 0
281 281 read not authorized
282 282 [1]
283 283
284 284 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
285 285 401 read not authorized
286 286
287 287 0
288 288 read not authorized
289 289 [1]
290 290
291 291 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
292 292 pulling from http://localhost:$HGPORT/
293 293 abort: authorization failed
294 294 [255]
295 295
296 296 $ killdaemons.py
297 297
298 298 web.deny_read=<user> allows access to authenticated users not in list
299 299
300 300 $ REMOTE_USER=gooduser hg serve -p $HGPORT -d --pid-file hg.pid
301 301 $ cat hg.pid > $DAEMON_PIDS
302 302
303 303 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
304 304 200 Script output follows
305 305
306 306 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1
307 307 publishing True (no-eol)
308 308
309 309 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
310 310 200 Script output follows
311 311
312 312 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1
313 313 publishing True (no-eol)
314 314
315 315 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
316 316 405 push requires POST request
317 317
318 318 0
319 319 push requires POST request
320 320 [1]
321 321
322 322 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
323 323 200 Script output follows
324 324
325 325 read-only command w/ defined permissions
326 326
327 327 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
328 328 405 push requires POST request
329 329
330 330 0
331 331 push requires POST request
332 332 [1]
333 333
334 334 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
335 335 405 push requires POST request
336 336
337 337 0
338 338 push requires POST request
339 339 [1]
340 340
341 341 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
342 342 pulling from http://localhost:$HGPORT/
343 343 searching for changes
344 344 no changes found
345 345
346 346 $ killdaemons.py
347 347
348 348 web.allow_read=* allows reads for unauthenticated users
349 349
350 350 $ cat > .hg/hgrc <<EOF
351 351 > [web]
352 352 > allow_read = *
353 353 > EOF
354 354
355 355 $ hg serve -p $HGPORT -d --pid-file hg.pid
356 356 $ cat hg.pid > $DAEMON_PIDS
357 357
358 358 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
359 359 200 Script output follows
360 360
361 361 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1
362 362 publishing True (no-eol)
363 363
364 364 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
365 365 200 Script output follows
366 366
367 367 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1
368 368 publishing True (no-eol)
369 369
370 370 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
371 371 405 push requires POST request
372 372
373 373 0
374 374 push requires POST request
375 375 [1]
376 376
377 377 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
378 378 200 Script output follows
379 379
380 380 read-only command w/ defined permissions
381 381
382 382 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
383 383 405 push requires POST request
384 384
385 385 0
386 386 push requires POST request
387 387 [1]
388 388
389 389 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
390 390 405 push requires POST request
391 391
392 392 0
393 393 push requires POST request
394 394 [1]
395 395
396 396 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
397 397 pulling from http://localhost:$HGPORT/
398 398 searching for changes
399 399 no changes found
400 400
401 401 $ killdaemons.py
402 402
403 403 web.allow_read=* allows read for authenticated user
404 404
405 405 $ REMOTE_USER=authed_user hg serve -p $HGPORT -d --pid-file hg.pid
406 406 $ cat hg.pid > $DAEMON_PIDS
407 407
408 408 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
409 409 200 Script output follows
410 410
411 411 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1
412 412 publishing True (no-eol)
413 413
414 414 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
415 415 200 Script output follows
416 416
417 417 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1
418 418 publishing True (no-eol)
419 419
420 420 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
421 421 405 push requires POST request
422 422
423 423 0
424 424 push requires POST request
425 425 [1]
426 426
427 427 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
428 428 200 Script output follows
429 429
430 430 read-only command w/ defined permissions
431 431
432 432 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
433 433 405 push requires POST request
434 434
435 435 0
436 436 push requires POST request
437 437 [1]
438 438
439 439 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
440 440 405 push requires POST request
441 441
442 442 0
443 443 push requires POST request
444 444 [1]
445 445
446 446 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
447 447 pulling from http://localhost:$HGPORT/
448 448 searching for changes
449 449 no changes found
450 450
451 451 $ killdaemons.py
452 452
453 453 web.allow_read=<user> does not allow unauthenticated users to read
454 454
455 455 $ cat > .hg/hgrc <<EOF
456 456 > [web]
457 457 > allow_read = gooduser
458 458 > EOF
459 459
460 460 $ hg serve -p $HGPORT -d --pid-file hg.pid
461 461 $ cat hg.pid > $DAEMON_PIDS
462 462
463 463 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
464 464 401 read not authorized
465 465
466 466 0
467 467 read not authorized
468 468 [1]
469 469
470 470 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
471 471 401 read not authorized
472 472
473 473 0
474 474 read not authorized
475 475 [1]
476 476
477 477 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
478 478 401 read not authorized
479 479
480 480 0
481 481 read not authorized
482 482 [1]
483 483
484 484 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
485 485 401 read not authorized
486 486
487 487 0
488 488 read not authorized
489 489 [1]
490 490
491 491 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
492 492 401 read not authorized
493 493
494 494 0
495 495 read not authorized
496 496 [1]
497 497
498 498 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
499 499 401 read not authorized
500 500
501 501 0
502 502 read not authorized
503 503 [1]
504 504
505 505 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
506 506 pulling from http://localhost:$HGPORT/
507 507 abort: authorization failed
508 508 [255]
509 509
510 510 $ killdaemons.py
511 511
512 512 web.allow_read=<user> does not allow user not in list to read
513 513
514 514 $ REMOTE_USER=baduser hg serve -p $HGPORT -d --pid-file hg.pid
515 515 $ cat hg.pid > $DAEMON_PIDS
516 516
517 517 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
518 518 401 read not authorized
519 519
520 520 0
521 521 read not authorized
522 522 [1]
523 523
524 524 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
525 525 401 read not authorized
526 526
527 527 0
528 528 read not authorized
529 529 [1]
530 530
531 531 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
532 532 401 read not authorized
533 533
534 534 0
535 535 read not authorized
536 536 [1]
537 537
538 538 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
539 539 401 read not authorized
540 540
541 541 0
542 542 read not authorized
543 543 [1]
544 544
545 545 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
546 546 401 read not authorized
547 547
548 548 0
549 549 read not authorized
550 550 [1]
551 551
552 552 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
553 553 401 read not authorized
554 554
555 555 0
556 556 read not authorized
557 557 [1]
558 558
559 559 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
560 560 pulling from http://localhost:$HGPORT/
561 561 abort: authorization failed
562 562 [255]
563 563
564 564 $ killdaemons.py
565 565
566 566 web.allow_read=<user> allows read from user in list
567 567
568 568 $ REMOTE_USER=gooduser hg serve -p $HGPORT -d --pid-file hg.pid
569 569 $ cat hg.pid > $DAEMON_PIDS
570 570
571 571 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
572 572 200 Script output follows
573 573
574 574 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1
575 575 publishing True (no-eol)
576 576
577 577 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
578 578 200 Script output follows
579 579
580 580 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1
581 581 publishing True (no-eol)
582 582
583 583 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
584 584 405 push requires POST request
585 585
586 586 0
587 587 push requires POST request
588 588 [1]
589 589
590 590 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
591 591 200 Script output follows
592 592
593 593 read-only command w/ defined permissions
594 594
595 595 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
596 596 405 push requires POST request
597 597
598 598 0
599 599 push requires POST request
600 600 [1]
601 601
602 602 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
603 603 405 push requires POST request
604 604
605 605 0
606 606 push requires POST request
607 607 [1]
608 608
609 609 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
610 610 pulling from http://localhost:$HGPORT/
611 611 searching for changes
612 612 no changes found
613 613
614 614 $ killdaemons.py
615 615
616 616 web.deny_read takes precedence over web.allow_read
617 617
618 618 $ cat > .hg/hgrc <<EOF
619 619 > [web]
620 620 > allow_read = baduser
621 621 > deny_read = baduser
622 622 > EOF
623 623
624 624 $ REMOTE_USER=baduser hg serve -p $HGPORT -d --pid-file hg.pid
625 625 $ cat hg.pid > $DAEMON_PIDS
626 626
627 627 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
628 628 401 read not authorized
629 629
630 630 0
631 631 read not authorized
632 632 [1]
633 633
634 634 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
635 635 401 read not authorized
636 636
637 637 0
638 638 read not authorized
639 639 [1]
640 640
641 641 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
642 642 401 read not authorized
643 643
644 644 0
645 645 read not authorized
646 646 [1]
647 647
648 648 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
649 649 401 read not authorized
650 650
651 651 0
652 652 read not authorized
653 653 [1]
654 654
655 655 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
656 656 401 read not authorized
657 657
658 658 0
659 659 read not authorized
660 660 [1]
661 661
662 662 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
663 663 401 read not authorized
664 664
665 665 0
666 666 read not authorized
667 667 [1]
668 668
669 669 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
670 670 pulling from http://localhost:$HGPORT/
671 671 abort: authorization failed
672 672 [255]
673 673
674 674 $ killdaemons.py
675 675
676 676 web.allow-pull=false denies read access to repo
677 677
678 678 $ cat > .hg/hgrc <<EOF
679 679 > [web]
680 680 > allow-pull = false
681 681 > EOF
682 682
683 683 $ hg serve -p $HGPORT -d --pid-file hg.pid
684 684 $ cat hg.pid > $DAEMON_PIDS
685 685
686 686 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities'
687 687 401 pull not authorized
688 688
689 689 0
690 690 pull not authorized
691 691 [1]
692 692
693 693 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases'
694 694 401 pull not authorized
695 695
696 696 0
697 697 pull not authorized
698 698 [1]
699 699
700 700 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases'
701 701 401 pull not authorized
702 702
703 703 0
704 704 pull not authorized
705 705 [1]
706 706
707 707 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
708 708 405 push requires POST request
709 709
710 710 0
711 711 push requires POST request
712 712 [1]
713 713
714 714 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
715 715 401 pull not authorized
716 716
717 717 0
718 718 pull not authorized
719 719 [1]
720 720
721 721 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
722 722 405 push requires POST request
723 723
724 724 0
725 725 push requires POST request
726 726 [1]
727 727
728 728 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
729 729 405 push requires POST request
730 730
731 731 0
732 732 push requires POST request
733 733 [1]
734 734
735 735 $ hg --cwd ../test2 pull http://localhost:$HGPORT/
736 736 pulling from http://localhost:$HGPORT/
737 737 abort: authorization failed
738 738 [255]
739 739
740 740 $ killdaemons.py
741 741
742 742 Attempting a write command with HTTP GET fails
743 743
744 744 $ cat > .hg/hgrc <<EOF
745 745 > EOF
746 746
747 747 $ REQUEST_METHOD=GET hg serve -p $HGPORT -d --pid-file hg.pid
748 748 $ cat hg.pid > $DAEMON_PIDS
749 749
750 750 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
751 751 405 push requires POST request
752 752
753 753 0
754 754 push requires POST request
755 755 [1]
756 756
757 757 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
758 758 405 push requires POST request
759 759
760 760 0
761 761 push requires POST request
762 762 [1]
763 763
764 764 $ hg bookmarks
765 765 no bookmarks set
766 766 $ hg bookmark -d bm
767 767 abort: bookmark 'bm' does not exist
768 768 [255]
769 769
770 770 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
771 771 405 push requires POST request
772 772
773 773 0
774 774 push requires POST request
775 775 [1]
776 776
777 777 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
778 778 405 push requires POST request
779 779
780 780 0
781 781 push requires POST request
782 782 [1]
783 783
784 784 $ killdaemons.py
785 785
786 786 Attempting a write command with an unknown HTTP verb fails
787 787
788 788 $ REQUEST_METHOD=someverb hg serve -p $HGPORT -d --pid-file hg.pid
789 789 $ cat hg.pid > $DAEMON_PIDS
790 790
791 791 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
792 792 405 push requires POST request
793 793
794 794 0
795 795 push requires POST request
796 796 [1]
797 797
798 798 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
799 799 405 push requires POST request
800 800
801 801 0
802 802 push requires POST request
803 803 [1]
804 804
805 805 $ hg bookmarks
806 806 no bookmarks set
807 807 $ hg bookmark -d bm
808 808 abort: bookmark 'bm' does not exist
809 809 [255]
810 810
811 811 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
812 812 405 push requires POST request
813 813
814 814 0
815 815 push requires POST request
816 816 [1]
817 817
818 818 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
819 819 405 push requires POST request
820 820
821 821 0
822 822 push requires POST request
823 823 [1]
824 824
825 825 $ killdaemons.py
826 826
827 827 Pushing on a plaintext channel is disabled by default
828 828
829 829 $ cat > .hg/hgrc <<EOF
830 830 > EOF
831 831
832 832 $ REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid
833 833 $ cat hg.pid > $DAEMON_PIDS
834 834
835 835 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
836 836 403 ssl required
837 837
838 838 0
839 839 ssl required
840 840 [1]
841 841
842 842 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
843 843 403 ssl required
844 844
845 845 0
846 846 ssl required
847 847 [1]
848 848
849 849 $ hg bookmarks
850 850 no bookmarks set
851 851
852 852 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
853 853 403 ssl required
854 854
855 855 0
856 856 ssl required
857 857 [1]
858 858
859 859 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
860 860 403 ssl required
861 861
862 862 0
863 863 ssl required
864 864 [1]
865 865
866 866 Reset server to remove REQUEST_METHOD hack to test hg client
867 867
868 868 $ killdaemons.py
869 869 $ hg serve -p $HGPORT -d --pid-file hg.pid
870 870 $ cat hg.pid > $DAEMON_PIDS
871 871
872 872 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
873 873 pushing to http://localhost:$HGPORT/
874 874 searching for changes
875 875 no changes found
876 876 abort: HTTP Error 403: ssl required
877 [255]
877 [100]
878 878
879 879 $ hg --cwd ../test2 push http://localhost:$HGPORT/
880 880 pushing to http://localhost:$HGPORT/
881 881 searching for changes
882 882 abort: HTTP Error 403: ssl required
883 [255]
883 [100]
884 884
885 885 $ killdaemons.py
886 886
887 887 web.deny_push=* denies pushing to unauthenticated users
888 888
889 889 $ cat > .hg/hgrc <<EOF
890 890 > [web]
891 891 > push_ssl = false
892 892 > deny_push = *
893 893 > EOF
894 894
895 895 $ REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid
896 896 $ cat hg.pid > $DAEMON_PIDS
897 897
898 898 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
899 899 401 push not authorized
900 900
901 901 0
902 902 push not authorized
903 903 [1]
904 904
905 905 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
906 906 401 push not authorized
907 907
908 908 0
909 909 push not authorized
910 910 [1]
911 911
912 912 $ hg bookmarks
913 913 no bookmarks set
914 914
915 915 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
916 916 401 push not authorized
917 917
918 918 0
919 919 push not authorized
920 920 [1]
921 921
922 922 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
923 923 401 push not authorized
924 924
925 925 0
926 926 push not authorized
927 927 [1]
928 928
929 929 Reset server to remove REQUEST_METHOD hack to test hg client
930 930
931 931 $ killdaemons.py
932 932 $ hg serve -p $HGPORT -d --pid-file hg.pid
933 933 $ cat hg.pid > $DAEMON_PIDS
934 934
935 935 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
936 936 pushing to http://localhost:$HGPORT/
937 937 searching for changes
938 938 no changes found
939 939 abort: authorization failed
940 940 [255]
941 941
942 942 $ hg --cwd ../test2 push http://localhost:$HGPORT/
943 943 pushing to http://localhost:$HGPORT/
944 944 searching for changes
945 945 abort: authorization failed
946 946 [255]
947 947
948 948 $ killdaemons.py
949 949
950 950 web.deny_push=* denies pushing to authenticated users
951 951
952 952 $ REMOTE_USER=someuser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid
953 953 $ cat hg.pid > $DAEMON_PIDS
954 954
955 955 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
956 956 401 push not authorized
957 957
958 958 0
959 959 push not authorized
960 960 [1]
961 961
962 962 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
963 963 401 push not authorized
964 964
965 965 0
966 966 push not authorized
967 967 [1]
968 968
969 969 $ hg bookmarks
970 970 no bookmarks set
971 971
972 972 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
973 973 401 push not authorized
974 974
975 975 0
976 976 push not authorized
977 977 [1]
978 978
979 979 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
980 980 401 push not authorized
981 981
982 982 0
983 983 push not authorized
984 984 [1]
985 985
986 986 Reset server to remove REQUEST_METHOD hack to test hg client
987 987
988 988 $ killdaemons.py
989 989 $ REMOTE_USER=someuser hg serve -p $HGPORT -d --pid-file hg.pid
990 990 $ cat hg.pid > $DAEMON_PIDS
991 991
992 992 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
993 993 pushing to http://localhost:$HGPORT/
994 994 searching for changes
995 995 no changes found
996 996 abort: authorization failed
997 997 [255]
998 998
999 999 $ hg --cwd ../test2 push http://localhost:$HGPORT/
1000 1000 pushing to http://localhost:$HGPORT/
1001 1001 searching for changes
1002 1002 abort: authorization failed
1003 1003 [255]
1004 1004
1005 1005 $ killdaemons.py
1006 1006
1007 1007 web.deny_push=<user> denies pushing to user in list
1008 1008
1009 1009 $ cat > .hg/hgrc <<EOF
1010 1010 > [web]
1011 1011 > push_ssl = false
1012 1012 > deny_push = baduser
1013 1013 > EOF
1014 1014
1015 1015 $ REMOTE_USER=baduser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid
1016 1016 $ cat hg.pid > $DAEMON_PIDS
1017 1017
1018 1018 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1019 1019 401 push not authorized
1020 1020
1021 1021 0
1022 1022 push not authorized
1023 1023 [1]
1024 1024
1025 1025 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1026 1026 401 push not authorized
1027 1027
1028 1028 0
1029 1029 push not authorized
1030 1030 [1]
1031 1031
1032 1032 $ hg bookmarks
1033 1033 no bookmarks set
1034 1034
1035 1035 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
1036 1036 401 push not authorized
1037 1037
1038 1038 0
1039 1039 push not authorized
1040 1040 [1]
1041 1041
1042 1042 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
1043 1043 401 push not authorized
1044 1044
1045 1045 0
1046 1046 push not authorized
1047 1047 [1]
1048 1048
1049 1049 Reset server to remove REQUEST_METHOD hack to test hg client
1050 1050
1051 1051 $ killdaemons.py
1052 1052 $ REMOTE_USER=baduser hg serve -p $HGPORT -d --pid-file hg.pid
1053 1053 $ cat hg.pid > $DAEMON_PIDS
1054 1054
1055 1055 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
1056 1056 pushing to http://localhost:$HGPORT/
1057 1057 searching for changes
1058 1058 no changes found
1059 1059 abort: authorization failed
1060 1060 [255]
1061 1061
1062 1062 $ hg --cwd ../test2 push http://localhost:$HGPORT/
1063 1063 pushing to http://localhost:$HGPORT/
1064 1064 searching for changes
1065 1065 abort: authorization failed
1066 1066 [255]
1067 1067
1068 1068 $ killdaemons.py
1069 1069
1070 1070 web.deny_push=<user> denies pushing to user not in list because allow-push isn't set
1071 1071
1072 1072 $ REMOTE_USER=gooduser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid
1073 1073 $ cat hg.pid > $DAEMON_PIDS
1074 1074
1075 1075 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1076 1076 401 push not authorized
1077 1077
1078 1078 0
1079 1079 push not authorized
1080 1080 [1]
1081 1081
1082 1082 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1083 1083 401 push not authorized
1084 1084
1085 1085 0
1086 1086 push not authorized
1087 1087 [1]
1088 1088
1089 1089 $ hg bookmarks
1090 1090 no bookmarks set
1091 1091
1092 1092 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
1093 1093 401 push not authorized
1094 1094
1095 1095 0
1096 1096 push not authorized
1097 1097 [1]
1098 1098
1099 1099 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
1100 1100 401 push not authorized
1101 1101
1102 1102 0
1103 1103 push not authorized
1104 1104 [1]
1105 1105
1106 1106 Reset server to remove REQUEST_METHOD hack to test hg client
1107 1107
1108 1108 $ killdaemons.py
1109 1109 $ REMOTE_USER=gooduser hg serve -p $HGPORT -d --pid-file hg.pid
1110 1110 $ cat hg.pid > $DAEMON_PIDS
1111 1111
1112 1112 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
1113 1113 pushing to http://localhost:$HGPORT/
1114 1114 searching for changes
1115 1115 no changes found
1116 1116 abort: authorization failed
1117 1117 [255]
1118 1118
1119 1119 $ hg --cwd ../test2 push http://localhost:$HGPORT/
1120 1120 pushing to http://localhost:$HGPORT/
1121 1121 searching for changes
1122 1122 abort: authorization failed
1123 1123 [255]
1124 1124
1125 1125 $ killdaemons.py
1126 1126
1127 1127 web.allow-push=* allows pushes from unauthenticated users
1128 1128
1129 1129 $ cat > .hg/hgrc <<EOF
1130 1130 > [web]
1131 1131 > push_ssl = false
1132 1132 > allow-push = *
1133 1133 > EOF
1134 1134
1135 1135 $ REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid
1136 1136 $ cat hg.pid > $DAEMON_PIDS
1137 1137
1138 1138 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1139 1139 200 Script output follows
1140 1140
1141 1141 1
1142 1142
1143 1143 $ hg bookmarks
1144 1144 bm 0:cb9a9f314b8b
1145 1145 $ hg book -d bm
1146 1146
1147 1147 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
1148 1148 200 Script output follows
1149 1149
1150 1150 write command no defined permissions
1151 1151
1152 1152 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
1153 1153 200 Script output follows
1154 1154
1155 1155 write command w/ defined permissions
1156 1156
1157 1157 Reset server to remove REQUEST_METHOD hack to test hg client
1158 1158
1159 1159 $ killdaemons.py
1160 1160 $ hg serve -p $HGPORT -d --pid-file hg.pid
1161 1161 $ cat hg.pid > $DAEMON_PIDS
1162 1162
1163 1163 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
1164 1164 pushing to http://localhost:$HGPORT/
1165 1165 searching for changes
1166 1166 no changes found
1167 1167 exporting bookmark bm
1168 1168 [1]
1169 1169
1170 1170 $ hg book -d bm
1171 1171
1172 1172 $ hg --cwd ../test2 push http://localhost:$HGPORT/
1173 1173 pushing to http://localhost:$HGPORT/
1174 1174 searching for changes
1175 1175 remote: adding changesets
1176 1176 remote: adding manifests
1177 1177 remote: adding file changes
1178 1178 remote: added 1 changesets with 1 changes to 1 files
1179 1179
1180 1180 $ hg strip -r 1:
1181 1181 saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg
1182 1182
1183 1183 $ killdaemons.py
1184 1184
1185 1185 web.allow-push=* allows pushes from authenticated users
1186 1186
1187 1187 $ REMOTE_USER=someuser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid
1188 1188 $ cat hg.pid > $DAEMON_PIDS
1189 1189
1190 1190 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1191 1191 200 Script output follows
1192 1192
1193 1193 1
1194 1194
1195 1195 $ hg bookmarks
1196 1196 bm 0:cb9a9f314b8b
1197 1197 $ hg book -d bm
1198 1198
1199 1199 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
1200 1200 200 Script output follows
1201 1201
1202 1202 write command no defined permissions
1203 1203
1204 1204 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
1205 1205 200 Script output follows
1206 1206
1207 1207 write command w/ defined permissions
1208 1208
1209 1209 Reset server to remove REQUEST_METHOD hack to test hg client
1210 1210
1211 1211 $ killdaemons.py
1212 1212 $ REMOTE_USER=someuser hg serve -p $HGPORT -d --pid-file hg.pid
1213 1213 $ cat hg.pid > $DAEMON_PIDS
1214 1214
1215 1215 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
1216 1216 pushing to http://localhost:$HGPORT/
1217 1217 searching for changes
1218 1218 no changes found
1219 1219 exporting bookmark bm
1220 1220 [1]
1221 1221
1222 1222 $ hg book -d bm
1223 1223
1224 1224 $ hg --cwd ../test2 push http://localhost:$HGPORT/
1225 1225 pushing to http://localhost:$HGPORT/
1226 1226 searching for changes
1227 1227 remote: adding changesets
1228 1228 remote: adding manifests
1229 1229 remote: adding file changes
1230 1230 remote: added 1 changesets with 1 changes to 1 files
1231 1231
1232 1232 $ hg strip -r 1:
1233 1233 saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg
1234 1234
1235 1235 $ killdaemons.py
1236 1236
1237 1237 web.allow-push=<user> denies push to user not in list
1238 1238
1239 1239 $ cat > .hg/hgrc <<EOF
1240 1240 > [web]
1241 1241 > push_ssl = false
1242 1242 > allow-push = gooduser
1243 1243 > EOF
1244 1244
1245 1245 $ REMOTE_USER=baduser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid
1246 1246 $ cat hg.pid > $DAEMON_PIDS
1247 1247
1248 1248 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1249 1249 401 push not authorized
1250 1250
1251 1251 0
1252 1252 push not authorized
1253 1253 [1]
1254 1254
1255 1255 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1256 1256 401 push not authorized
1257 1257
1258 1258 0
1259 1259 push not authorized
1260 1260 [1]
1261 1261
1262 1262 $ hg bookmarks
1263 1263 no bookmarks set
1264 1264
1265 1265 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
1266 1266 401 push not authorized
1267 1267
1268 1268 0
1269 1269 push not authorized
1270 1270 [1]
1271 1271
1272 1272 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
1273 1273 401 push not authorized
1274 1274
1275 1275 0
1276 1276 push not authorized
1277 1277 [1]
1278 1278
1279 1279 Reset server to remove REQUEST_METHOD hack to test hg client
1280 1280
1281 1281 $ killdaemons.py
1282 1282 $ REMOTE_USER=baduser hg serve -p $HGPORT -d --pid-file hg.pid
1283 1283 $ cat hg.pid > $DAEMON_PIDS
1284 1284
1285 1285 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
1286 1286 pushing to http://localhost:$HGPORT/
1287 1287 searching for changes
1288 1288 no changes found
1289 1289 abort: authorization failed
1290 1290 [255]
1291 1291
1292 1292 $ hg --cwd ../test2 push http://localhost:$HGPORT/
1293 1293 pushing to http://localhost:$HGPORT/
1294 1294 searching for changes
1295 1295 abort: authorization failed
1296 1296 [255]
1297 1297
1298 1298 $ killdaemons.py
1299 1299
1300 1300 web.allow-push=<user> allows push from user in list
1301 1301
1302 1302 $ REMOTE_USER=gooduser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid
1303 1303 $ cat hg.pid > $DAEMON_PIDS
1304 1304
1305 1305 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1306 1306 200 Script output follows
1307 1307
1308 1308 1
1309 1309
1310 1310 $ hg bookmarks
1311 1311 bm 0:cb9a9f314b8b
1312 1312 $ hg book -d bm
1313 1313
1314 1314 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1315 1315 200 Script output follows
1316 1316
1317 1317 1
1318 1318
1319 1319 $ hg bookmarks
1320 1320 bm 0:cb9a9f314b8b
1321 1321 $ hg book -d bm
1322 1322
1323 1323 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
1324 1324 200 Script output follows
1325 1325
1326 1326 write command no defined permissions
1327 1327
1328 1328 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
1329 1329 200 Script output follows
1330 1330
1331 1331 write command w/ defined permissions
1332 1332
1333 1333 Reset server to remove REQUEST_METHOD hack to test hg client
1334 1334
1335 1335 $ killdaemons.py
1336 1336 $ REMOTE_USER=gooduser hg serve -p $HGPORT -d --pid-file hg.pid
1337 1337 $ cat hg.pid > $DAEMON_PIDS
1338 1338
1339 1339 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
1340 1340 pushing to http://localhost:$HGPORT/
1341 1341 searching for changes
1342 1342 no changes found
1343 1343 exporting bookmark bm
1344 1344 [1]
1345 1345
1346 1346 $ hg book -d bm
1347 1347
1348 1348 $ hg --cwd ../test2 push http://localhost:$HGPORT/
1349 1349 pushing to http://localhost:$HGPORT/
1350 1350 searching for changes
1351 1351 remote: adding changesets
1352 1352 remote: adding manifests
1353 1353 remote: adding file changes
1354 1354 remote: added 1 changesets with 1 changes to 1 files
1355 1355
1356 1356 $ hg strip -r 1:
1357 1357 saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg
1358 1358
1359 1359 $ killdaemons.py
1360 1360
1361 1361 web.deny_push takes precedence over web.allow_push
1362 1362
1363 1363 $ cat > .hg/hgrc <<EOF
1364 1364 > [web]
1365 1365 > push_ssl = false
1366 1366 > allow-push = someuser
1367 1367 > deny_push = someuser
1368 1368 > EOF
1369 1369
1370 1370 $ REMOTE_USER=someuser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid
1371 1371 $ cat hg.pid > $DAEMON_PIDS
1372 1372
1373 1373 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1374 1374 401 push not authorized
1375 1375
1376 1376 0
1377 1377 push not authorized
1378 1378 [1]
1379 1379
1380 1380 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1381 1381 401 push not authorized
1382 1382
1383 1383 0
1384 1384 push not authorized
1385 1385 [1]
1386 1386
1387 1387 $ hg bookmarks
1388 1388 no bookmarks set
1389 1389
1390 1390 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
1391 1391 401 push not authorized
1392 1392
1393 1393 0
1394 1394 push not authorized
1395 1395 [1]
1396 1396
1397 1397 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
1398 1398 401 push not authorized
1399 1399
1400 1400 0
1401 1401 push not authorized
1402 1402 [1]
1403 1403
1404 1404 Reset server to remove REQUEST_METHOD hack to test hg client
1405 1405
1406 1406 $ killdaemons.py
1407 1407 $ REMOTE_USER=someuser hg serve -p $HGPORT -d --pid-file hg.pid
1408 1408 $ cat hg.pid > $DAEMON_PIDS
1409 1409
1410 1410 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
1411 1411 pushing to http://localhost:$HGPORT/
1412 1412 searching for changes
1413 1413 no changes found
1414 1414 abort: authorization failed
1415 1415 [255]
1416 1416
1417 1417 $ hg --cwd ../test2 push http://localhost:$HGPORT/
1418 1418 pushing to http://localhost:$HGPORT/
1419 1419 searching for changes
1420 1420 abort: authorization failed
1421 1421 [255]
1422 1422
1423 1423 $ killdaemons.py
1424 1424
1425 1425 web.allow-push has no effect if web.deny_read is set
1426 1426
1427 1427 $ cat > .hg/hgrc <<EOF
1428 1428 > [web]
1429 1429 > push_ssl = false
1430 1430 > allow-push = *
1431 1431 > deny_read = *
1432 1432 > EOF
1433 1433
1434 1434 $ REQUEST_METHOD=POST REMOTE_USER=someuser hg serve -p $HGPORT -d --pid-file hg.pid
1435 1435 $ cat hg.pid > $DAEMON_PIDS
1436 1436
1437 1437 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1438 1438 401 read not authorized
1439 1439
1440 1440 0
1441 1441 read not authorized
1442 1442 [1]
1443 1443
1444 1444 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b'
1445 1445 401 read not authorized
1446 1446
1447 1447 0
1448 1448 read not authorized
1449 1449 [1]
1450 1450
1451 1451 $ hg bookmarks
1452 1452 no bookmarks set
1453 1453
1454 1454 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm'
1455 1455 401 read not authorized
1456 1456
1457 1457 0
1458 1458 read not authorized
1459 1459 [1]
1460 1460
1461 1461 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm'
1462 1462 401 read not authorized
1463 1463
1464 1464 0
1465 1465 read not authorized
1466 1466 [1]
1467 1467
1468 1468 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm'
1469 1469 401 read not authorized
1470 1470
1471 1471 0
1472 1472 read not authorized
1473 1473 [1]
1474 1474
1475 1475 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm'
1476 1476 401 read not authorized
1477 1477
1478 1478 0
1479 1479 read not authorized
1480 1480 [1]
1481 1481
1482 1482 Reset server to remove REQUEST_METHOD hack to test hg client
1483 1483
1484 1484 $ killdaemons.py
1485 1485 $ REMOTE_USER=someuser hg serve -p $HGPORT -d --pid-file hg.pid
1486 1486 $ cat hg.pid > $DAEMON_PIDS
1487 1487
1488 1488 $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/
1489 1489 pushing to http://localhost:$HGPORT/
1490 1490 abort: authorization failed
1491 1491 [255]
1492 1492
1493 1493 $ hg --cwd ../test2 push http://localhost:$HGPORT/
1494 1494 pushing to http://localhost:$HGPORT/
1495 1495 abort: authorization failed
1496 1496 [255]
1497 1497
1498 1498 $ killdaemons.py
@@ -1,122 +1,122 b''
1 1 #require serve
2 2
3 3 $ hg init a
4 4 $ cd a
5 5 $ echo a > a
6 6 $ hg ci -Ama -d '1123456789 0'
7 7 adding a
8 8 $ hg serve --config server.uncompressed=True -p $HGPORT -d --pid-file=hg.pid
9 9 $ cat hg.pid >> $DAEMON_PIDS
10 10 $ cd ..
11 11 $ tinyproxy.py $HGPORT1 localhost 2>proxy.log >/dev/null </dev/null &
12 12 $ while [ ! -f proxy.pid ]; do sleep 0; done
13 13 $ cat proxy.pid >> $DAEMON_PIDS
14 14
15 15 url for proxy, stream
16 16
17 17 $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone --stream http://localhost:$HGPORT/ b
18 18 streaming all changes
19 19 6 files to transfer, 412 bytes of data (reporevlogstore !)
20 20 4 files to transfer, 330 bytes of data (reposimplestore !)
21 21 transferred * bytes in * seconds (*/sec) (glob)
22 22 updating to branch default
23 23 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 24 $ cd b
25 25 $ hg verify
26 26 checking changesets
27 27 checking manifests
28 28 crosschecking files in changesets and manifests
29 29 checking files
30 30 checked 1 changesets with 1 changes to 1 files
31 31 $ cd ..
32 32
33 33 url for proxy, pull
34 34
35 35 $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone http://localhost:$HGPORT/ b-pull
36 36 requesting all changes
37 37 adding changesets
38 38 adding manifests
39 39 adding file changes
40 40 added 1 changesets with 1 changes to 1 files
41 41 new changesets 83180e7845de
42 42 updating to branch default
43 43 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
44 44 $ cd b-pull
45 45 $ hg verify
46 46 checking changesets
47 47 checking manifests
48 48 crosschecking files in changesets and manifests
49 49 checking files
50 50 checked 1 changesets with 1 changes to 1 files
51 51 $ cd ..
52 52
53 53 host:port for proxy
54 54
55 55 $ http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ c
56 56 requesting all changes
57 57 adding changesets
58 58 adding manifests
59 59 adding file changes
60 60 added 1 changesets with 1 changes to 1 files
61 61 new changesets 83180e7845de
62 62 updating to branch default
63 63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 64
65 65 proxy url with user name and password
66 66
67 67 $ http_proxy=http://user:passwd@localhost:$HGPORT1 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ d
68 68 requesting all changes
69 69 adding changesets
70 70 adding manifests
71 71 adding file changes
72 72 added 1 changesets with 1 changes to 1 files
73 73 new changesets 83180e7845de
74 74 updating to branch default
75 75 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 76
77 77 url with user name and password
78 78
79 79 $ http_proxy=http://user:passwd@localhost:$HGPORT1 hg clone --config http_proxy.always=True http://user:passwd@localhost:$HGPORT/ e
80 80 requesting all changes
81 81 adding changesets
82 82 adding manifests
83 83 adding file changes
84 84 added 1 changesets with 1 changes to 1 files
85 85 new changesets 83180e7845de
86 86 updating to branch default
87 87 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 88
89 89 bad host:port for proxy ("Protocol not supported" can happen on
90 90 misconfigured hosts)
91 91
92 92 $ http_proxy=localhost:$HGPORT2 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ f
93 93 abort: error: (Connection refused|Protocol not supported|.* actively refused it|\$EADDRNOTAVAIL\$|No route to host) (re)
94 [255]
94 [100]
95 95
96 96 do not use the proxy if it is in the no list
97 97
98 98 $ http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.no=localhost http://localhost:$HGPORT/ g
99 99 requesting all changes
100 100 adding changesets
101 101 adding manifests
102 102 adding file changes
103 103 added 1 changesets with 1 changes to 1 files
104 104 new changesets 83180e7845de
105 105 updating to branch default
106 106 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 107 $ cat proxy.log
108 108 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
109 109 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
110 110 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=0&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=bookmarks&stream=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
111 111 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
112 112 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
113 113 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
114 114 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
115 115 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
116 116 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
117 117 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
118 118 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
119 119 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
120 120 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
121 121 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
122 122 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (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 [255]
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 [255]
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 351 bundle2-output-part: "replycaps" 224 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 357 sending 1040 bytes
358 358 devel-peer-request: POST http://localhost:$HGPORT2/?cmd=unbundle
359 359 devel-peer-request: Content-length 1040
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 364 devel-peer-request: 1040 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 [255]
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 [255]
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 [255]
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 [255]
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 [255]
615 [100]
@@ -1,554 +1,554 b''
1 1 #require serve ssl
2 2
3 3 Proper https client requires the built-in ssl from Python 2.6.
4 4
5 5 Disable the system configuration which may set stricter TLS requirements.
6 6 This test expects that legacy TLS versions are supported.
7 7
8 8 $ OPENSSL_CONF=
9 9 $ export OPENSSL_CONF
10 10
11 11 Make server certificates:
12 12
13 13 $ CERTSDIR="$TESTDIR/sslcerts"
14 14 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub.pem" >> server.pem
15 15 $ PRIV=`pwd`/server.pem
16 16 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-not-yet.pem" > server-not-yet.pem
17 17 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-expired.pem" > server-expired.pem
18 18
19 19 $ hg init test
20 20 $ cd test
21 21 $ echo foo>foo
22 22 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
23 23 $ echo foo>foo.d/foo
24 24 $ echo bar>foo.d/bAr.hg.d/BaR
25 25 $ echo bar>foo.d/baR.d.hg/bAR
26 26 $ hg commit -A -m 1
27 27 adding foo
28 28 adding foo.d/bAr.hg.d/BaR
29 29 adding foo.d/baR.d.hg/bAR
30 30 adding foo.d/foo
31 31 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV
32 32 $ cat ../hg0.pid >> $DAEMON_PIDS
33 33
34 34 cacert not found
35 35
36 36 $ hg in --config web.cacerts=no-such.pem https://localhost:$HGPORT/
37 37 abort: could not find web.cacerts: no-such.pem
38 38 [255]
39 39
40 40 Test server address cannot be reused
41 41
42 42 $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
43 43 abort: cannot start server at 'localhost:$HGPORT': $EADDRINUSE$
44 44 [255]
45 45
46 46 $ cd ..
47 47
48 48 Our test cert is not signed by a trusted CA. It should fail to verify if
49 49 we are able to load CA certs.
50 50
51 51 #if no-defaultcacertsloaded
52 52 $ hg clone https://localhost:$HGPORT/ copy-pull
53 53 (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
54 54 abort: error: *certificate verify failed* (glob)
55 55 [255]
56 56 #endif
57 57
58 58 #if defaultcacertsloaded
59 59 $ hg clone https://localhost:$HGPORT/ copy-pull
60 60 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
61 61 abort: error: *certificate verify failed* (glob)
62 [255]
62 [100]
63 63 #endif
64 64
65 65 Specifying a per-host certificate file that doesn't exist will abort. The full
66 66 C:/path/to/msysroot will print on Windows.
67 67
68 68 $ hg --config hostsecurity.localhost:verifycertsfile=/does/not/exist clone https://localhost:$HGPORT/
69 69 abort: path specified by hostsecurity.localhost:verifycertsfile does not exist: */does/not/exist (glob)
70 70 [255]
71 71
72 72 A malformed per-host certificate file will raise an error
73 73
74 74 $ echo baddata > badca.pem
75 75 $ hg --config hostsecurity.localhost:verifycertsfile=badca.pem clone https://localhost:$HGPORT/
76 76 abort: error loading CA file badca.pem: * (glob)
77 77 (file is empty or malformed?)
78 78 [255]
79 79
80 80 A per-host certificate mismatching the server will fail verification
81 81
82 82 (modern ssl is able to discern whether the loaded cert is a CA cert)
83 83 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/client-cert.pem" clone https://localhost:$HGPORT/
84 84 (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
85 85 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
86 86 abort: error: *certificate verify failed* (glob)
87 [255]
87 [100]
88 88
89 89 A per-host certificate matching the server's cert will be accepted
90 90
91 91 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" clone -U https://localhost:$HGPORT/ perhostgood1
92 92 requesting all changes
93 93 adding changesets
94 94 adding manifests
95 95 adding file changes
96 96 added 1 changesets with 4 changes to 4 files
97 97 new changesets 8b6053c928fe
98 98
99 99 A per-host certificate with multiple certs and one matching will be accepted
100 100
101 101 $ cat "$CERTSDIR/client-cert.pem" "$CERTSDIR/pub.pem" > perhost.pem
102 102 $ hg --config hostsecurity.localhost:verifycertsfile=perhost.pem clone -U https://localhost:$HGPORT/ perhostgood2
103 103 requesting all changes
104 104 adding changesets
105 105 adding manifests
106 106 adding file changes
107 107 added 1 changesets with 4 changes to 4 files
108 108 new changesets 8b6053c928fe
109 109
110 110 Defining both per-host certificate and a fingerprint will print a warning
111 111
112 112 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 clone -U https://localhost:$HGPORT/ caandfingerwarning
113 113 (hostsecurity.localhost:verifycertsfile ignored when host fingerprints defined; using host fingerprints for verification)
114 114 requesting all changes
115 115 adding changesets
116 116 adding manifests
117 117 adding file changes
118 118 added 1 changesets with 4 changes to 4 files
119 119 new changesets 8b6053c928fe
120 120
121 121 $ DISABLECACERTS="--config devel.disableloaddefaultcerts=true"
122 122
123 123 Inability to verify peer certificate will result in abort
124 124
125 125 $ hg clone https://localhost:$HGPORT/ copy-pull $DISABLECACERTS
126 126 abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
127 127 (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
128 128 [255]
129 129
130 130 $ hg clone --insecure https://localhost:$HGPORT/ copy-pull
131 131 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
132 132 requesting all changes
133 133 adding changesets
134 134 adding manifests
135 135 adding file changes
136 136 added 1 changesets with 4 changes to 4 files
137 137 new changesets 8b6053c928fe
138 138 updating to branch default
139 139 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 140 $ hg verify -R copy-pull
141 141 checking changesets
142 142 checking manifests
143 143 crosschecking files in changesets and manifests
144 144 checking files
145 145 checked 1 changesets with 4 changes to 4 files
146 146 $ cd test
147 147 $ echo bar > bar
148 148 $ hg commit -A -d '1 0' -m 2
149 149 adding bar
150 150 $ cd ..
151 151
152 152 pull without cacert
153 153
154 154 $ cd copy-pull
155 155 $ cat >> .hg/hgrc <<EOF
156 156 > [hooks]
157 157 > changegroup = sh -c "printenv.py --line changegroup"
158 158 > EOF
159 159 $ hg pull $DISABLECACERTS
160 160 pulling from https://localhost:$HGPORT/
161 161 abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
162 162 (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
163 163 [255]
164 164
165 165 $ hg pull --insecure
166 166 pulling from https://localhost:$HGPORT/
167 167 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
168 168 searching for changes
169 169 adding changesets
170 170 adding manifests
171 171 adding file changes
172 172 added 1 changesets with 1 changes to 1 files
173 173 new changesets 5fed3813f7f5
174 174 changegroup hook: HG_HOOKNAME=changegroup
175 175 HG_HOOKTYPE=changegroup
176 176 HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d
177 177 HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d
178 178 HG_SOURCE=pull
179 179 HG_TXNID=TXN:$ID$
180 180 HG_TXNNAME=pull
181 181 https://localhost:$HGPORT/
182 182 HG_URL=https://localhost:$HGPORT/
183 183
184 184 (run 'hg update' to get a working copy)
185 185 $ cd ..
186 186
187 187 cacert configured in local repo
188 188
189 189 $ cp copy-pull/.hg/hgrc copy-pull/.hg/hgrc.bu
190 190 $ echo "[web]" >> copy-pull/.hg/hgrc
191 191 $ echo "cacerts=$CERTSDIR/pub.pem" >> copy-pull/.hg/hgrc
192 192 $ hg -R copy-pull pull
193 193 pulling from https://localhost:$HGPORT/
194 194 searching for changes
195 195 no changes found
196 196 $ mv copy-pull/.hg/hgrc.bu copy-pull/.hg/hgrc
197 197
198 198 cacert configured globally, also testing expansion of environment
199 199 variables in the filename
200 200
201 201 $ echo "[web]" >> $HGRCPATH
202 202 $ echo 'cacerts=$P/pub.pem' >> $HGRCPATH
203 203 $ P="$CERTSDIR" hg -R copy-pull pull
204 204 pulling from https://localhost:$HGPORT/
205 205 searching for changes
206 206 no changes found
207 207 $ P="$CERTSDIR" hg -R copy-pull pull --insecure
208 208 pulling from https://localhost:$HGPORT/
209 209 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
210 210 searching for changes
211 211 no changes found
212 212
213 213 empty cacert file
214 214
215 215 $ touch emptycafile
216 216
217 217 $ hg --config web.cacerts=emptycafile -R copy-pull pull
218 218 pulling from https://localhost:$HGPORT/
219 219 abort: error loading CA file emptycafile: * (glob)
220 220 (file is empty or malformed?)
221 221 [255]
222 222
223 223 cacert mismatch
224 224
225 225 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \
226 226 > https://$LOCALIP:$HGPORT/
227 227 pulling from https://*:$HGPORT/ (glob)
228 228 abort: $LOCALIP certificate error: certificate is for localhost (glob)
229 229 (set hostsecurity.$LOCALIP:certfingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e config setting or use --insecure to connect insecurely)
230 230 [255]
231 231 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \
232 232 > https://$LOCALIP:$HGPORT/ --insecure
233 233 pulling from https://*:$HGPORT/ (glob)
234 234 warning: connection security to $LOCALIP is disabled per current settings; communication is susceptible to eavesdropping and tampering (glob)
235 235 searching for changes
236 236 no changes found
237 237 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem"
238 238 pulling from https://localhost:$HGPORT/
239 239 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
240 240 abort: error: *certificate verify failed* (glob)
241 [255]
241 [100]
242 242 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem" \
243 243 > --insecure
244 244 pulling from https://localhost:$HGPORT/
245 245 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
246 246 searching for changes
247 247 no changes found
248 248
249 249 Test server cert which isn't valid yet
250 250
251 251 $ hg serve -R test -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem
252 252 $ cat hg1.pid >> $DAEMON_PIDS
253 253 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-not-yet.pem" \
254 254 > https://localhost:$HGPORT1/
255 255 pulling from https://localhost:$HGPORT1/
256 256 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
257 257 abort: error: *certificate verify failed* (glob)
258 [255]
258 [100]
259 259
260 260 Test server cert which no longer is valid
261 261
262 262 $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
263 263 $ cat hg2.pid >> $DAEMON_PIDS
264 264 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-expired.pem" \
265 265 > https://localhost:$HGPORT2/
266 266 pulling from https://localhost:$HGPORT2/
267 267 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
268 268 abort: error: *certificate verify failed* (glob)
269 [255]
269 [100]
270 270
271 271 Setting ciphers to an invalid value aborts
272 272 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/
273 273 abort: could not set ciphers: No cipher can be selected.
274 274 (change cipher string (invalid) in config)
275 275 [255]
276 276
277 277 $ P="$CERTSDIR" hg --config hostsecurity.localhost:ciphers=invalid -R copy-pull id https://localhost:$HGPORT/
278 278 abort: could not set ciphers: No cipher can be selected.
279 279 (change cipher string (invalid) in config)
280 280 [255]
281 281
282 282 Changing the cipher string works
283 283
284 284 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/
285 285 5fed3813f7f5
286 286
287 287 Fingerprints
288 288
289 289 - works without cacerts (hostfingerprints)
290 290 $ hg -R copy-pull id https://localhost:$HGPORT/ --insecure --config hostfingerprints.localhost=ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
291 291 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
292 292 5fed3813f7f5
293 293
294 294 - works without cacerts (hostsecurity)
295 295 $ hg -R copy-pull id https://localhost:$HGPORT/ --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
296 296 5fed3813f7f5
297 297
298 298 $ hg -R copy-pull id https://localhost:$HGPORT/ --config hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e
299 299 5fed3813f7f5
300 300
301 301 - multiple fingerprints specified and first matches
302 302 $ hg --config 'hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure
303 303 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
304 304 5fed3813f7f5
305 305
306 306 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
307 307 5fed3813f7f5
308 308
309 309 - multiple fingerprints specified and last matches
310 310 $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/ --insecure
311 311 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
312 312 5fed3813f7f5
313 313
314 314 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/
315 315 5fed3813f7f5
316 316
317 317 - multiple fingerprints specified and none match
318 318
319 319 $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure
320 320 abort: certificate for localhost has unexpected fingerprint ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
321 321 (check hostfingerprint configuration)
322 322 [255]
323 323
324 324 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
325 325 abort: certificate for localhost has unexpected fingerprint sha1:ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
326 326 (check hostsecurity configuration)
327 327 [255]
328 328
329 329 - fails when cert doesn't match hostname (port is ignored)
330 330 $ hg -R copy-pull id https://localhost:$HGPORT1/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
331 331 abort: certificate for localhost has unexpected fingerprint f4:2f:5a:0c:3e:52:5b:db:e7:24:a8:32:1d:18:97:6d:69:b5:87:84
332 332 (check hostfingerprint configuration)
333 333 [255]
334 334
335 335
336 336 - ignores that certificate doesn't match hostname
337 337 $ hg -R copy-pull id https://$LOCALIP:$HGPORT/ --config hostfingerprints.$LOCALIP=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
338 338 (SHA-1 fingerprint for $LOCALIP found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: $LOCALIP:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
339 339 5fed3813f7f5
340 340
341 341 Ports used by next test. Kill servers.
342 342
343 343 $ killdaemons.py hg0.pid
344 344 $ killdaemons.py hg1.pid
345 345 $ killdaemons.py hg2.pid
346 346
347 347 #if tls1.2
348 348 Start servers running supported TLS versions
349 349
350 350 $ cd test
351 351 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \
352 352 > --config devel.serverexactprotocol=tls1.0
353 353 $ cat ../hg0.pid >> $DAEMON_PIDS
354 354 $ hg serve -p $HGPORT1 -d --pid-file=../hg1.pid --certificate=$PRIV \
355 355 > --config devel.serverexactprotocol=tls1.1
356 356 $ cat ../hg1.pid >> $DAEMON_PIDS
357 357 $ hg serve -p $HGPORT2 -d --pid-file=../hg2.pid --certificate=$PRIV \
358 358 > --config devel.serverexactprotocol=tls1.2
359 359 $ cat ../hg2.pid >> $DAEMON_PIDS
360 360 $ cd ..
361 361
362 362 Clients talking same TLS versions work
363 363
364 364 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.0 id https://localhost:$HGPORT/
365 365 5fed3813f7f5
366 366 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT1/
367 367 5fed3813f7f5
368 368 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT2/
369 369 5fed3813f7f5
370 370
371 371 Clients requiring newer TLS version than what server supports fail
372 372
373 373 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/
374 374 (could not negotiate a common security protocol (tls1.1+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
375 375 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
376 376 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
377 377 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
378 [255]
378 [100]
379 379
380 380 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT/
381 381 (could not negotiate a common security protocol (tls1.1+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
382 382 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
383 383 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
384 384 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
385 [255]
385 [100]
386 386 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT/
387 387 (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
388 388 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
389 389 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
390 390 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
391 [255]
391 [100]
392 392 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT1/
393 393 (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
394 394 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
395 395 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
396 396 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
397 [255]
397 [100]
398 398
399 399 --insecure will allow TLS 1.0 connections and override configs
400 400
401 401 $ hg --config hostsecurity.minimumprotocol=tls1.2 id --insecure https://localhost:$HGPORT1/
402 402 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
403 403 5fed3813f7f5
404 404
405 405 The per-host config option overrides the default
406 406
407 407 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
408 408 > --config hostsecurity.minimumprotocol=tls1.2 \
409 409 > --config hostsecurity.localhost:minimumprotocol=tls1.0
410 410 5fed3813f7f5
411 411
412 412 The per-host config option by itself works
413 413
414 414 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
415 415 > --config hostsecurity.localhost:minimumprotocol=tls1.2
416 416 (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
417 417 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
418 418 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
419 419 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
420 [255]
420 [100]
421 421
422 422 .hg/hgrc file [hostsecurity] settings are applied to remote ui instances (issue5305)
423 423
424 424 $ cat >> copy-pull/.hg/hgrc << EOF
425 425 > [hostsecurity]
426 426 > localhost:minimumprotocol=tls1.2
427 427 > EOF
428 428 $ P="$CERTSDIR" hg -R copy-pull id https://localhost:$HGPORT/
429 429 (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
430 430 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
431 431 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
432 432 abort: error: .*(unsupported protocol|wrong ssl version).* (re)
433 [255]
433 [100]
434 434
435 435 $ killdaemons.py hg0.pid
436 436 $ killdaemons.py hg1.pid
437 437 $ killdaemons.py hg2.pid
438 438 #endif
439 439
440 440 Prepare for connecting through proxy
441 441
442 442 $ hg serve -R test -p $HGPORT -d --pid-file=hg0.pid --certificate=$PRIV
443 443 $ cat hg0.pid >> $DAEMON_PIDS
444 444 $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
445 445 $ cat hg2.pid >> $DAEMON_PIDS
446 446 tinyproxy.py doesn't fully detach, so killing it may result in extra output
447 447 from the shell. So don't kill it.
448 448 $ tinyproxy.py $HGPORT1 localhost >proxy.log </dev/null 2>&1 &
449 449 $ while [ ! -f proxy.pid ]; do sleep 0; done
450 450 $ cat proxy.pid >> $DAEMON_PIDS
451 451
452 452 $ echo "[http_proxy]" >> copy-pull/.hg/hgrc
453 453 $ echo "always=True" >> copy-pull/.hg/hgrc
454 454 $ echo "[hostfingerprints]" >> copy-pull/.hg/hgrc
455 455 $ echo "localhost =" >> copy-pull/.hg/hgrc
456 456
457 457 Test unvalidated https through proxy
458 458
459 459 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull --insecure
460 460 pulling from https://localhost:$HGPORT/
461 461 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
462 462 searching for changes
463 463 no changes found
464 464
465 465 Test https with cacert and fingerprint through proxy
466 466
467 467 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
468 468 > --config web.cacerts="$CERTSDIR/pub.pem"
469 469 pulling from https://localhost:$HGPORT/
470 470 searching for changes
471 471 no changes found
472 472 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull https://localhost:$HGPORT/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 --trace
473 473 pulling from https://*:$HGPORT/ (glob)
474 474 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, remove the old SHA-1 fingerprint from [hostfingerprints] and add the following entry to the new [hostsecurity] section: localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
475 475 searching for changes
476 476 no changes found
477 477
478 478 Test https with cert problems through proxy
479 479
480 480 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
481 481 > --config web.cacerts="$CERTSDIR/pub-other.pem"
482 482 pulling from https://localhost:$HGPORT/
483 483 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
484 484 abort: error: *certificate verify failed* (glob)
485 [255]
485 [100]
486 486 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
487 487 > --config web.cacerts="$CERTSDIR/pub-expired.pem" https://localhost:$HGPORT2/
488 488 pulling from https://localhost:$HGPORT2/
489 489 (the full certificate chain may not be available locally; see "hg help debugssl") (windows !)
490 490 abort: error: *certificate verify failed* (glob)
491 [255]
491 [100]
492 492
493 493
494 494 $ killdaemons.py hg0.pid
495 495
496 496 $ cd test
497 497
498 498 Missing certificate file(s) are detected
499 499
500 500 $ hg serve -p $HGPORT --certificate=/missing/certificate \
501 501 > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true
502 502 abort: referenced certificate file (*/missing/certificate) does not exist (glob)
503 503 [255]
504 504
505 505 $ hg serve -p $HGPORT --certificate=$PRIV \
506 506 > --config devel.servercafile=/missing/cafile --config devel.serverrequirecert=true
507 507 abort: referenced certificate file (*/missing/cafile) does not exist (glob)
508 508 [255]
509 509
510 510 Start hgweb that requires client certificates:
511 511
512 512 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \
513 513 > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true
514 514 $ cat ../hg0.pid >> $DAEMON_PIDS
515 515 $ cd ..
516 516
517 517 without client certificate:
518 518
519 519 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/
520 520 abort: error: .*(\$ECONNRESET\$|certificate required|handshake failure).* (re)
521 [255]
521 [100]
522 522
523 523 with client certificate:
524 524
525 525 $ cat << EOT >> $HGRCPATH
526 526 > [auth]
527 527 > l.prefix = localhost
528 528 > l.cert = $CERTSDIR/client-cert.pem
529 529 > l.key = $CERTSDIR/client-key.pem
530 530 > EOT
531 531
532 532 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
533 533 > --config auth.l.key="$CERTSDIR/client-key-decrypted.pem"
534 534 5fed3813f7f5
535 535
536 536 $ printf '1234\n' | env P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
537 537 > --config ui.interactive=True --config ui.nontty=True
538 538 passphrase for */client-key.pem: 5fed3813f7f5 (glob)
539 539
540 540 $ env P="$CERTSDIR" hg id https://localhost:$HGPORT/
541 541 abort: error: * (glob)
542 [255]
542 [100]
543 543
544 544 Missing certficate and key files result in error
545 545
546 546 $ hg id https://localhost:$HGPORT/ --config auth.l.cert=/missing/cert
547 547 abort: certificate file (*/missing/cert) does not exist; cannot connect to localhost (glob)
548 548 (restore missing file or fix references in Mercurial config)
549 549 [255]
550 550
551 551 $ hg id https://localhost:$HGPORT/ --config auth.l.key=/missing/key
552 552 abort: certificate file (*/missing/key) does not exist; cannot connect to localhost (glob)
553 553 (restore missing file or fix references in Mercurial config)
554 554 [255]
@@ -1,452 +1,452 b''
1 1 #testcases sshv1 sshv2
2 2
3 3 #if sshv2
4 4 $ cat >> $HGRCPATH << EOF
5 5 > [experimental]
6 6 > sshpeer.advertise-v2 = true
7 7 > sshserver.support-v2 = true
8 8 > EOF
9 9 #endif
10 10
11 11 This file contains testcases that tend to be related to the wire protocol part
12 12 of largefiles.
13 13
14 14 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
15 15 $ mkdir "${USERCACHE}"
16 16 $ cat >> $HGRCPATH <<EOF
17 17 > [extensions]
18 18 > largefiles=
19 19 > purge=
20 20 > rebase=
21 21 > transplant=
22 22 > [phases]
23 23 > publish=False
24 24 > [largefiles]
25 25 > minsize=2
26 26 > patterns=glob:**.dat
27 27 > usercache=${USERCACHE}
28 28 > [web]
29 29 > allow-archive = zip
30 30 > [hooks]
31 31 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
32 32 > EOF
33 33
34 34
35 35 #if serve
36 36 vanilla clients not locked out from largefiles servers on vanilla repos
37 37 $ mkdir r1
38 38 $ cd r1
39 39 $ hg init
40 40 $ echo c1 > f1
41 41 $ hg add f1
42 42 $ hg commit -m "m1"
43 43 Invoking status precommit hook
44 44 A f1
45 45 $ cd ..
46 46 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
47 47 $ cat hg.pid >> $DAEMON_PIDS
48 48 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
49 49 requesting all changes
50 50 adding changesets
51 51 adding manifests
52 52 adding file changes
53 53 added 1 changesets with 1 changes to 1 files
54 54 new changesets b6eb3a2e2efe (1 drafts)
55 55 updating to branch default
56 56 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
57 57
58 58 largefiles clients still work with vanilla servers
59 59 $ hg serve --config extensions.largefiles=! -R r1 -d -p $HGPORT1 --pid-file hg.pid
60 60 $ cat hg.pid >> $DAEMON_PIDS
61 61 $ hg clone http://localhost:$HGPORT1 r3
62 62 requesting all changes
63 63 adding changesets
64 64 adding manifests
65 65 adding file changes
66 66 added 1 changesets with 1 changes to 1 files
67 67 new changesets b6eb3a2e2efe (1 drafts)
68 68 updating to branch default
69 69 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 70 #endif
71 71
72 72 vanilla clients locked out from largefiles http repos
73 73 $ mkdir r4
74 74 $ cd r4
75 75 $ hg init
76 76 $ echo c1 > f1
77 77 $ hg add --large f1
78 78 $ hg commit -m "m1"
79 79 Invoking status precommit hook
80 80 A f1
81 81 $ cd ..
82 82
83 83 largefiles can be pushed locally (issue3583)
84 84 $ hg init dest
85 85 $ cd r4
86 86 $ hg outgoing ../dest
87 87 comparing with ../dest
88 88 searching for changes
89 89 changeset: 0:639881c12b4c
90 90 tag: tip
91 91 user: test
92 92 date: Thu Jan 01 00:00:00 1970 +0000
93 93 summary: m1
94 94
95 95 $ hg push ../dest
96 96 pushing to ../dest
97 97 searching for changes
98 98 adding changesets
99 99 adding manifests
100 100 adding file changes
101 101 added 1 changesets with 1 changes to 1 files
102 102
103 103 exit code with nothing outgoing (issue3611)
104 104 $ hg outgoing ../dest
105 105 comparing with ../dest
106 106 searching for changes
107 107 no changes found
108 108 [1]
109 109 $ cd ..
110 110
111 111 #if serve
112 112 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
113 113 $ cat hg.pid >> $DAEMON_PIDS
114 114 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
115 115 abort: remote error:
116 116
117 117 This repository uses the largefiles extension.
118 118
119 119 Please enable it in your Mercurial config file.
120 [255]
120 [100]
121 121
122 122 used all HGPORTs, kill all daemons
123 123 $ killdaemons.py
124 124 #endif
125 125
126 126 vanilla clients locked out from largefiles ssh repos
127 127 $ hg --config extensions.largefiles=! clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/r4 r5
128 128 remote:
129 129 remote: This repository uses the largefiles extension.
130 130 remote:
131 131 remote: Please enable it in your Mercurial config file.
132 132 remote:
133 133 remote: -
134 134 abort: remote error
135 135 (check previous remote output)
136 [255]
136 [100]
137 137
138 138 #if serve
139 139
140 140 largefiles clients refuse to push largefiles repos to vanilla servers
141 141 $ mkdir r6
142 142 $ cd r6
143 143 $ hg init
144 144 $ echo c1 > f1
145 145 $ hg add f1
146 146 $ hg commit -m "m1"
147 147 Invoking status precommit hook
148 148 A f1
149 149 $ cat >> .hg/hgrc <<!
150 150 > [web]
151 151 > push_ssl = false
152 152 > allow_push = *
153 153 > !
154 154 $ cd ..
155 155 $ hg clone r6 r7
156 156 updating to branch default
157 157 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 158 $ cd r7
159 159 $ echo c2 > f2
160 160 $ hg add --large f2
161 161 $ hg commit -m "m2"
162 162 Invoking status precommit hook
163 163 A f2
164 164 $ hg verify --large
165 165 checking changesets
166 166 checking manifests
167 167 crosschecking files in changesets and manifests
168 168 checking files
169 169 checked 2 changesets with 2 changes to 2 files
170 170 searching 1 changesets for largefiles
171 171 verified existence of 1 revisions of 1 largefiles
172 172 $ hg serve --config extensions.largefiles=! -R ../r6 -d -p $HGPORT --pid-file ../hg.pid
173 173 $ cat ../hg.pid >> $DAEMON_PIDS
174 174 $ hg push http://localhost:$HGPORT
175 175 pushing to http://localhost:$HGPORT/
176 176 searching for changes
177 177 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
178 178 [255]
179 179 $ cd ..
180 180
181 181 putlfile errors are shown (issue3123)
182 182 Corrupt the cached largefile in r7 and move it out of the servers usercache
183 183 $ mv r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 .
184 184 $ echo 'client side corruption' > r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
185 185 $ rm "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
186 186 $ hg init empty
187 187 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
188 188 > --config 'web.allow_push=*' --config web.push_ssl=False
189 189 $ cat hg.pid >> $DAEMON_PIDS
190 190 $ hg push -R r7 http://localhost:$HGPORT1
191 191 pushing to http://localhost:$HGPORT1/
192 192 searching for changes
193 193 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
194 194 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/
195 195 [255]
196 196 $ mv 4cdac4d8b084d0b599525cf732437fb337d422a8 r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
197 197 Push of file that exists on server but is corrupted - magic healing would be nice ... but too magic
198 198 $ echo "server side corruption" > empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
199 199 $ hg push -R r7 http://localhost:$HGPORT1
200 200 pushing to http://localhost:$HGPORT1/
201 201 searching for changes
202 202 remote: adding changesets
203 203 remote: adding manifests
204 204 remote: adding file changes
205 205 remote: added 2 changesets with 2 changes to 2 files
206 206 $ cat empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
207 207 server side corruption
208 208 $ rm -rf empty
209 209
210 210 Push a largefiles repository to a served empty repository
211 211 $ hg init r8
212 212 $ echo c3 > r8/f1
213 213 $ hg add --large r8/f1 -R r8
214 214 $ hg commit -m "m1" -R r8
215 215 Invoking status precommit hook
216 216 A f1
217 217 $ hg init empty
218 218 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
219 219 > --config 'web.allow_push=*' --config web.push_ssl=False
220 220 $ cat hg.pid >> $DAEMON_PIDS
221 221 $ rm "${USERCACHE}"/*
222 222 $ hg push -R r8 http://localhost:$HGPORT2/#default
223 223 pushing to http://localhost:$HGPORT2/
224 224 searching for changes
225 225 remote: adding changesets
226 226 remote: adding manifests
227 227 remote: adding file changes
228 228 remote: added 1 changesets with 1 changes to 1 files
229 229 $ [ -f "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
230 230 $ [ -f empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
231 231
232 232 Clone over http, no largefiles pulled on clone.
233 233
234 234 $ hg clone http://localhost:$HGPORT2/#default http-clone -U
235 235 adding changesets
236 236 adding manifests
237 237 adding file changes
238 238 added 1 changesets with 1 changes to 1 files
239 239 new changesets cf03e5bb9936 (1 drafts)
240 240
241 241 Archive contains largefiles
242 242 >>> import os
243 243 >>> from mercurial import urllibcompat
244 244 >>> u = 'http://localhost:%s/archive/default.zip' % os.environ['HGPORT2']
245 245 >>> with open('archive.zip', 'wb') as f:
246 246 ... f.write(urllibcompat.urlreq.urlopen(u).read()) and None
247 247 $ unzip -t archive.zip
248 248 Archive: archive.zip
249 249 testing: empty-default/.hg_archival.txt*OK (glob)
250 250 testing: empty-default/f1*OK (glob)
251 251 No errors detected in compressed data of archive.zip.
252 252
253 253 test 'verify' with remotestore:
254 254
255 255 $ rm "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90
256 256 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
257 257 $ hg -R http-clone verify --large --lfa
258 258 checking changesets
259 259 checking manifests
260 260 crosschecking files in changesets and manifests
261 261 checking files
262 262 checked 1 changesets with 1 changes to 1 files
263 263 searching 1 changesets for largefiles
264 264 changeset 0:cf03e5bb9936: f1 missing
265 265 verified existence of 1 revisions of 1 largefiles
266 266 [1]
267 267 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
268 268 $ hg -R http-clone -q verify --large --lfa
269 269
270 270 largefiles pulled on update - a largefile missing on the server:
271 271 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
272 272 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
273 273 getting changed largefiles
274 274 f1: largefile 02a439e5c31c526465ab1a0ca1f431f76b827b90 not available from http://localhost:$HGPORT2/
275 275 0 largefiles updated, 0 removed
276 276 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 277 $ hg -R http-clone st
278 278 ! f1
279 279 $ hg -R http-clone up -Cqr null
280 280
281 281 largefiles pulled on update - a largefile corrupted on the server:
282 282 $ echo corruption > empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90
283 283 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
284 284 getting changed largefiles
285 285 f1: data corruption (expected 02a439e5c31c526465ab1a0ca1f431f76b827b90, got 6a7bb2556144babe3899b25e5428123735bb1e27)
286 286 0 largefiles updated, 0 removed
287 287 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
288 288 $ hg -R http-clone st
289 289 ! f1
290 290 $ [ ! -f http-clone/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
291 291 $ [ ! -f http-clone/f1 ]
292 292 $ [ ! -f http-clone-usercache ]
293 293 $ hg -R http-clone verify --large --lfc
294 294 checking changesets
295 295 checking manifests
296 296 crosschecking files in changesets and manifests
297 297 checking files
298 298 checked 1 changesets with 1 changes to 1 files
299 299 searching 1 changesets for largefiles
300 300 verified contents of 1 revisions of 1 largefiles
301 301 $ hg -R http-clone up -Cqr null
302 302
303 303 largefiles pulled on update - no server side problems:
304 304 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
305 305 $ hg -R http-clone --debug up --config largefiles.usercache=http-clone-usercache --config progress.debug=true
306 306 resolving manifests
307 307 branchmerge: False, force: False, partial: False
308 308 ancestor: 000000000000, local: 000000000000+, remote: cf03e5bb9936
309 309 .hglf/f1: remote created -> g
310 310 getting .hglf/f1
311 311 updating: .hglf/f1 1/1 files (100.00%)
312 312 getting changed largefiles
313 313 using http://localhost:$HGPORT2/
314 314 sending capabilities command
315 315 sending statlfile command
316 316 getting largefiles: 0/1 files (0.00%)
317 317 getting f1:02a439e5c31c526465ab1a0ca1f431f76b827b90
318 318 sending getlfile command
319 319 found 02a439e5c31c526465ab1a0ca1f431f76b827b90 in store
320 320 1 largefiles updated, 0 removed
321 321 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
322 322
323 323 $ ls http-clone-usercache/*
324 324 http-clone-usercache/02a439e5c31c526465ab1a0ca1f431f76b827b90
325 325
326 326 $ rm -rf empty http-clone*
327 327
328 328 used all HGPORTs, kill all daemons
329 329 $ killdaemons.py
330 330
331 331 largefiles should batch verify remote calls
332 332
333 333 $ hg init batchverifymain
334 334 $ cd batchverifymain
335 335 $ echo "aaa" >> a
336 336 $ hg add --large a
337 337 $ hg commit -m "a"
338 338 Invoking status precommit hook
339 339 A a
340 340 $ echo "bbb" >> b
341 341 $ hg add --large b
342 342 $ hg commit -m "b"
343 343 Invoking status precommit hook
344 344 A b
345 345 $ cd ..
346 346 $ hg serve -R batchverifymain -d -p $HGPORT --pid-file hg.pid \
347 347 > -A access.log
348 348 $ cat hg.pid >> $DAEMON_PIDS
349 349 $ hg clone --noupdate http://localhost:$HGPORT batchverifyclone
350 350 requesting all changes
351 351 adding changesets
352 352 adding manifests
353 353 adding file changes
354 354 added 2 changesets with 2 changes to 2 files
355 355 new changesets 567253b0f523:04d19c27a332 (2 drafts)
356 356 $ hg -R batchverifyclone verify --large --lfa
357 357 checking changesets
358 358 checking manifests
359 359 crosschecking files in changesets and manifests
360 360 checking files
361 361 checked 2 changesets with 2 changes to 2 files
362 362 searching 2 changesets for largefiles
363 363 verified existence of 2 revisions of 2 largefiles
364 364 $ tail -1 access.log
365 365 $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=statlfile+sha%3D972a1a11f19934401291cc99117ec614933374ce%3Bstatlfile+sha%3Dc801c9cfe94400963fcb683246217d5db77f9a9a x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
366 366 $ hg -R batchverifyclone update
367 367 getting changed largefiles
368 368 2 largefiles updated, 0 removed
369 369 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
370 370
371 371 Clear log file before next test
372 372
373 373 $ printf "" > access.log
374 374
375 375 Verify should check file on remote server only when file is not
376 376 available locally.
377 377
378 378 $ echo "ccc" >> batchverifymain/c
379 379 $ hg -R batchverifymain status
380 380 ? c
381 381 $ hg -R batchverifymain add --large batchverifymain/c
382 382 $ hg -R batchverifymain commit -m "c"
383 383 Invoking status precommit hook
384 384 A c
385 385 $ hg -R batchverifyclone pull
386 386 pulling from http://localhost:$HGPORT/
387 387 searching for changes
388 388 adding changesets
389 389 adding manifests
390 390 adding file changes
391 391 added 1 changesets with 1 changes to 1 files
392 392 new changesets 6bba8cb6935d (1 drafts)
393 393 (run 'hg update' to get a working copy)
394 394 $ hg -R batchverifyclone verify --lfa
395 395 checking changesets
396 396 checking manifests
397 397 crosschecking files in changesets and manifests
398 398 checking files
399 399 checked 3 changesets with 3 changes to 3 files
400 400 searching 3 changesets for largefiles
401 401 verified existence of 3 revisions of 3 largefiles
402 402 $ tail -1 access.log
403 403 $LOCALIP - - [$LOGDATE$] "GET /?cmd=statlfile HTTP/1.1" 200 - x-hgarg-1:sha=c8559c3c9cfb42131794b7d8009230403b9b454c x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
404 404
405 405 $ killdaemons.py
406 406
407 407 largefiles should not ask for password again after successful authorization
408 408
409 409 $ hg init credentialmain
410 410 $ cd credentialmain
411 411 $ echo "aaa" >> a
412 412 $ hg add --large a
413 413 $ hg commit -m "a"
414 414 Invoking status precommit hook
415 415 A a
416 416
417 417 Before running server clear the user cache to force clone to download
418 418 a large file from the server rather than to get it from the cache
419 419
420 420 $ rm "${USERCACHE}"/*
421 421
422 422 $ cd ..
423 423
424 424 $ hg serve --config extensions.x=$TESTDIR/httpserverauth.py -R credentialmain \
425 425 > -d -p $HGPORT --pid-file hg.pid -A access.log
426 426 $ cat hg.pid >> $DAEMON_PIDS
427 427 $ cat << EOF > get_pass.py
428 428 > import getpass
429 429 > def newgetpass(arg):
430 430 > return "pass"
431 431 > getpass.getpass = newgetpass
432 432 > EOF
433 433 $ hg clone --config ui.interactive=true --config extensions.getpass=get_pass.py \
434 434 > http://user@localhost:$HGPORT credentialclone
435 435 http authorization required for http://localhost:$HGPORT/
436 436 realm: mercurial
437 437 user: user
438 438 password: requesting all changes
439 439 adding changesets
440 440 adding manifests
441 441 adding file changes
442 442 added 1 changesets with 1 changes to 1 files
443 443 new changesets 567253b0f523 (1 drafts)
444 444 updating to branch default
445 445 getting changed largefiles
446 446 1 largefiles updated, 0 removed
447 447 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
448 448
449 449 $ killdaemons.py
450 450 $ rm hg.pid access.log
451 451
452 452 #endif
@@ -1,553 +1,553 b''
1 1 #require no-chg
2 2
3 3 #testcases bundle1 bundle2
4 4
5 5 #if bundle1
6 6 $ cat << EOF >> $HGRCPATH
7 7 > [devel]
8 8 > # This test is dedicated to interaction through old bundle
9 9 > legacy.exchange = bundle1
10 10 > EOF
11 11 #endif
12 12
13 13 $ hg init test
14 14 $ cd test
15 15 $ echo a > a
16 16 $ hg ci -Ama
17 17 adding a
18 18 $ cd ..
19 19 $ hg clone test test2
20 20 updating to branch default
21 21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 22 $ cd test2
23 23 $ echo a >> a
24 24 $ hg ci -mb
25 25 $ req() {
26 26 > hg $1 serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
27 27 > cat hg.pid >> $DAEMON_PIDS
28 28 > hg --cwd ../test2 push http://localhost:$HGPORT/
29 29 > exitstatus=$?
30 30 > killdaemons.py
31 31 > echo % serve errors
32 32 > cat errors.log
33 33 > return $exitstatus
34 34 > }
35 35 $ cd ../test
36 36
37 37 expect ssl error
38 38
39 39 $ req
40 40 pushing to http://localhost:$HGPORT/
41 41 searching for changes
42 42 abort: HTTP Error 403: ssl required
43 43 % serve errors
44 [255]
44 [100]
45 45
46 46 expect authorization error
47 47
48 48 $ echo '[web]' > .hg/hgrc
49 49 $ echo 'push_ssl = false' >> .hg/hgrc
50 50 $ req
51 51 pushing to http://localhost:$HGPORT/
52 52 searching for changes
53 53 abort: authorization failed
54 54 % serve errors
55 55 [255]
56 56
57 57 expect authorization error: must have authorized user
58 58
59 59 $ echo 'allow_push = unperson' >> .hg/hgrc
60 60 $ req
61 61 pushing to http://localhost:$HGPORT/
62 62 searching for changes
63 63 abort: authorization failed
64 64 % serve errors
65 65 [255]
66 66
67 67 expect success
68 68
69 69 $ cat > $TESTTMP/hook.sh <<'EOF'
70 70 > echo "phase-move: $HG_NODE: $HG_OLDPHASE -> $HG_PHASE"
71 71 > EOF
72 72
73 73 #if bundle1
74 74 $ cat >> .hg/hgrc <<EOF
75 75 > allow_push = *
76 76 > [hooks]
77 77 > changegroup = sh -c "printenv.py --line changegroup 0"
78 78 > pushkey = sh -c "printenv.py --line pushkey 0"
79 79 > txnclose-phase.test = sh $TESTTMP/hook.sh
80 80 > EOF
81 81 $ req "--debug --config extensions.blackbox="
82 82 listening at http://*:$HGPORT/ (bound to $LOCALIP:$HGPORT) (glob) (?)
83 83 pushing to http://localhost:$HGPORT/
84 84 searching for changes
85 85 remote: redirecting incoming bundle to */hg-unbundle-* (glob)
86 86 remote: adding changesets
87 87 remote: add changeset ba677d0156c1
88 88 remote: adding manifests
89 89 remote: adding file changes
90 90 remote: adding a revisions
91 91 remote: updating the branch cache
92 92 remote: added 1 changesets with 1 changes to 1 files
93 93 remote: running hook txnclose-phase.test: sh $TESTTMP/hook.sh
94 94 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
95 95 remote: running hook txnclose-phase.test: sh $TESTTMP/hook.sh
96 96 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
97 97 remote: running hook changegroup: sh -c "printenv.py --line changegroup 0"
98 98 remote: changegroup hook: HG_HOOKNAME=changegroup
99 99 remote: HG_HOOKTYPE=changegroup
100 100 remote: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872
101 101 remote: HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872
102 102 remote: HG_SOURCE=serve
103 103 remote: HG_TXNID=TXN:$ID$
104 104 remote: HG_TXNNAME=serve
105 105 remote: remote:http:$LOCALIP: (glob)
106 106 remote: HG_URL=remote:http:$LOCALIP: (glob)
107 107 remote:
108 108 % serve errors
109 109 $ hg rollback
110 110 repository tip rolled back to revision 0 (undo serve)
111 111 $ req "--debug --config server.streamunbundle=True --config extensions.blackbox="
112 112 listening at http://*:$HGPORT/ (bound to $LOCALIP:$HGPORT) (glob) (?)
113 113 pushing to http://localhost:$HGPORT/
114 114 searching for changes
115 115 remote: adding changesets
116 116 remote: add changeset ba677d0156c1
117 117 remote: adding manifests
118 118 remote: adding file changes
119 119 remote: adding a revisions
120 120 remote: updating the branch cache
121 121 remote: added 1 changesets with 1 changes to 1 files
122 122 remote: running hook txnclose-phase.test: sh $TESTTMP/hook.sh
123 123 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
124 124 remote: running hook txnclose-phase.test: sh $TESTTMP/hook.sh
125 125 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
126 126 remote: running hook changegroup: sh -c "printenv.py --line changegroup 0"
127 127 remote: changegroup hook: HG_HOOKNAME=changegroup
128 128 remote: HG_HOOKTYPE=changegroup
129 129 remote: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872
130 130 remote: HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872
131 131 remote: HG_SOURCE=serve
132 132 remote: HG_TXNID=TXN:$ID$
133 133 remote: HG_TXNNAME=serve
134 134 remote: remote:http:$LOCALIP: (glob)
135 135 remote: HG_URL=remote:http:$LOCALIP: (glob)
136 136 remote:
137 137 % serve errors
138 138 $ hg rollback
139 139 repository tip rolled back to revision 0 (undo serve)
140 140 #endif
141 141
142 142 #if bundle2
143 143 $ cat >> .hg/hgrc <<EOF
144 144 > allow_push = *
145 145 > [hooks]
146 146 > changegroup = sh -c "printenv.py --line changegroup 0"
147 147 > pushkey = sh -c "printenv.py --line pushkey 0"
148 148 > txnclose-phase.test = sh $TESTTMP/hook.sh
149 149 > EOF
150 150 $ req
151 151 pushing to http://localhost:$HGPORT/
152 152 searching for changes
153 153 remote: adding changesets
154 154 remote: adding manifests
155 155 remote: adding file changes
156 156 remote: added 1 changesets with 1 changes to 1 files
157 157 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
158 158 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
159 159 remote: changegroup hook: HG_BUNDLE2=1
160 160 remote: HG_HOOKNAME=changegroup
161 161 remote: HG_HOOKTYPE=changegroup
162 162 remote: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872
163 163 remote: HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872
164 164 remote: HG_SOURCE=serve
165 165 remote: HG_TXNID=TXN:$ID$
166 166 remote: HG_TXNNAME=serve
167 167 remote: HG_URL=remote:http:$LOCALIP: (glob)
168 168 remote:
169 169 % serve errors
170 170 $ hg rollback
171 171 repository tip rolled back to revision 0 (undo serve)
172 172 #endif
173 173
174 174 expect success, server lacks the httpheader capability
175 175
176 176 $ CAP=httpheader
177 177 $ . "$TESTDIR/notcapable"
178 178 $ req
179 179 pushing to http://localhost:$HGPORT/
180 180 searching for changes
181 181 remote: adding changesets
182 182 remote: adding manifests
183 183 remote: adding file changes
184 184 remote: added 1 changesets with 1 changes to 1 files
185 185 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
186 186 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
187 187 remote: changegroup hook: HG_HOOKNAME=changegroup (no-bundle2 !)
188 188 remote: changegroup hook: HG_BUNDLE2=1 (bundle2 !)
189 189 remote: HG_HOOKNAME=changegroup (bundle2 !)
190 190 remote: HG_HOOKTYPE=changegroup
191 191 remote: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872
192 192 remote: HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872
193 193 remote: HG_SOURCE=serve
194 194 remote: HG_TXNID=TXN:$ID$
195 195 remote: HG_TXNNAME=serve
196 196 remote: remote:http:$LOCALIP: (glob) (no-bundle2 !)
197 197 remote: HG_URL=remote:http:$LOCALIP: (glob)
198 198 remote:
199 199 % serve errors
200 200 $ hg rollback
201 201 repository tip rolled back to revision 0 (undo serve)
202 202
203 203 expect success, server lacks the unbundlehash capability
204 204
205 205 $ CAP=unbundlehash
206 206 $ . "$TESTDIR/notcapable"
207 207 $ req
208 208 pushing to http://localhost:$HGPORT/
209 209 searching for changes
210 210 remote: adding changesets
211 211 remote: adding manifests
212 212 remote: adding file changes
213 213 remote: added 1 changesets with 1 changes to 1 files
214 214 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
215 215 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
216 216 remote: changegroup hook: HG_HOOKNAME=changegroup (no-bundle2 !)
217 217 remote: changegroup hook: HG_BUNDLE2=1 (bundle2 !)
218 218 remote: HG_HOOKNAME=changegroup (bundle2 !)
219 219 remote: HG_HOOKTYPE=changegroup
220 220 remote: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872
221 221 remote: HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872
222 222 remote: HG_SOURCE=serve
223 223 remote: HG_TXNID=TXN:$ID$
224 224 remote: HG_TXNNAME=serve
225 225 remote: remote:http:$LOCALIP: (glob) (no-bundle2 !)
226 226 remote: HG_URL=remote:http:$LOCALIP: (glob)
227 227 remote:
228 228 % serve errors
229 229 $ hg rollback
230 230 repository tip rolled back to revision 0 (undo serve)
231 231
232 232 expect success, pre-d1b16a746db6 server supports the unbundle capability, but
233 233 has no parameter
234 234
235 235 $ cat <<EOF > notcapable-unbundleparam.py
236 236 > from mercurial import extensions, httppeer
237 237 > def capable(orig, self, name):
238 238 > if name == 'unbundle':
239 239 > return True
240 240 > return orig(self, name)
241 241 > def uisetup(ui):
242 242 > extensions.wrapfunction(httppeer.httppeer, 'capable', capable)
243 243 > EOF
244 244 $ cp $HGRCPATH $HGRCPATH.orig
245 245 $ cat <<EOF >> $HGRCPATH
246 246 > [extensions]
247 247 > notcapable-unbundleparam = `pwd`/notcapable-unbundleparam.py
248 248 > EOF
249 249 $ req
250 250 pushing to http://localhost:$HGPORT/
251 251 searching for changes
252 252 remote: adding changesets
253 253 remote: adding manifests
254 254 remote: adding file changes
255 255 remote: added 1 changesets with 1 changes to 1 files
256 256 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
257 257 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
258 258 remote: changegroup hook: * (glob)
259 259 remote: HG_HOOKNAME=changegroup (bundle2 !)
260 260 remote: HG_HOOKTYPE=changegroup
261 261 remote: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872
262 262 remote: HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872
263 263 remote: HG_SOURCE=serve
264 264 remote: HG_TXNID=TXN:$ID$
265 265 remote: HG_TXNNAME=serve
266 266 remote: remote:http:$LOCALIP: (glob) (no-bundle2 !)
267 267 remote: HG_URL=remote:http:$LOCALIP: (glob)
268 268 remote:
269 269 % serve errors
270 270 $ hg rollback
271 271 repository tip rolled back to revision 0 (undo serve)
272 272 $ mv $HGRCPATH.orig $HGRCPATH
273 273
274 274 Test pushing to a publishing repository with a failing prepushkey hook
275 275
276 276 $ cat > .hg/hgrc <<EOF
277 277 > [web]
278 278 > push_ssl = false
279 279 > allow_push = *
280 280 > [hooks]
281 281 > prepushkey = sh -c "printenv.py --line prepushkey 1"
282 282 > [devel]
283 283 > legacy.exchange=phases
284 284 > EOF
285 285
286 286 #if bundle1
287 287 Bundle1 works because a) phases are updated as part of changegroup application
288 288 and b) client checks phases after the "unbundle" command. Since it sees no
289 289 phase changes are necessary, it doesn't send the "pushkey" command and the
290 290 prepushkey hook never has to fire.
291 291
292 292 $ req
293 293 pushing to http://localhost:$HGPORT/
294 294 searching for changes
295 295 remote: adding changesets
296 296 remote: adding manifests
297 297 remote: adding file changes
298 298 remote: added 1 changesets with 1 changes to 1 files
299 299 % serve errors
300 300
301 301 #endif
302 302
303 303 #if bundle2
304 304 Bundle2 sends a "pushkey" bundle2 part. This runs as part of the transaction
305 305 and fails the entire push.
306 306 $ req
307 307 pushing to http://localhost:$HGPORT/
308 308 searching for changes
309 309 remote: adding changesets
310 310 remote: adding manifests
311 311 remote: adding file changes
312 312 remote: prepushkey hook: HG_BUNDLE2=1
313 313 remote: HG_HOOKNAME=prepushkey
314 314 remote: HG_HOOKTYPE=prepushkey
315 315 remote: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872
316 316 remote: HG_NAMESPACE=phases
317 317 remote: HG_NEW=0
318 318 remote: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872
319 319 remote: HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872
320 320 remote: HG_OLD=1
321 321 remote: HG_PENDING=$TESTTMP/test
322 322 remote: HG_PHASES_MOVED=1
323 323 remote: HG_SOURCE=serve
324 324 remote: HG_TXNID=TXN:$ID$
325 325 remote: HG_TXNNAME=serve
326 326 remote: HG_URL=remote:http:$LOCALIP: (glob)
327 327 remote:
328 328 remote: pushkey-abort: prepushkey hook exited with status 1
329 329 remote: transaction abort!
330 330 remote: rollback completed
331 331 abort: updating ba677d0156c1 to public failed
332 332 % serve errors
333 333 [255]
334 334
335 335 #endif
336 336
337 337 Now remove the failing prepushkey hook.
338 338
339 339 $ cat >> .hg/hgrc <<EOF
340 340 > [hooks]
341 341 > prepushkey = sh -c "printenv.py --line prepushkey 0"
342 342 > EOF
343 343
344 344 We don't need to test bundle1 because it succeeded above.
345 345
346 346 #if bundle2
347 347 $ req
348 348 pushing to http://localhost:$HGPORT/
349 349 searching for changes
350 350 remote: adding changesets
351 351 remote: adding manifests
352 352 remote: adding file changes
353 353 remote: prepushkey hook: HG_BUNDLE2=1
354 354 remote: HG_HOOKNAME=prepushkey
355 355 remote: HG_HOOKTYPE=prepushkey
356 356 remote: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872
357 357 remote: HG_NAMESPACE=phases
358 358 remote: HG_NEW=0
359 359 remote: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872
360 360 remote: HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872
361 361 remote: HG_OLD=1
362 362 remote: HG_PENDING=$TESTTMP/test
363 363 remote: HG_PHASES_MOVED=1
364 364 remote: HG_SOURCE=serve
365 365 remote: HG_TXNID=TXN:$ID$
366 366 remote: HG_TXNNAME=serve
367 367 remote: HG_URL=remote:http:$LOCALIP: (glob)
368 368 remote:
369 369 remote: added 1 changesets with 1 changes to 1 files
370 370 % serve errors
371 371 #endif
372 372
373 373 $ hg --config extensions.strip= strip -r 1:
374 374 saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg
375 375
376 376 Now do a variant of the above, except on a non-publishing repository
377 377
378 378 $ cat >> .hg/hgrc <<EOF
379 379 > [phases]
380 380 > publish = false
381 381 > [hooks]
382 382 > prepushkey = sh -c "printenv.py --line prepushkey 1"
383 383 > EOF
384 384
385 385 #if bundle1
386 386 $ req
387 387 pushing to http://localhost:$HGPORT/
388 388 searching for changes
389 389 remote: adding changesets
390 390 remote: adding manifests
391 391 remote: adding file changes
392 392 remote: added 1 changesets with 1 changes to 1 files
393 393 remote: prepushkey hook: HG_HOOKNAME=prepushkey
394 394 remote: HG_HOOKTYPE=prepushkey
395 395 remote: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872
396 396 remote: HG_NAMESPACE=phases
397 397 remote: HG_NEW=0
398 398 remote: HG_OLD=1
399 399 remote:
400 400 remote: pushkey-abort: prepushkey hook exited with status 1
401 401 updating ba677d0156c1 to public failed!
402 402 % serve errors
403 403 #endif
404 404
405 405 #if bundle2
406 406 $ req
407 407 pushing to http://localhost:$HGPORT/
408 408 searching for changes
409 409 remote: adding changesets
410 410 remote: adding manifests
411 411 remote: adding file changes
412 412 remote: prepushkey hook: HG_BUNDLE2=1
413 413 remote: HG_HOOKNAME=prepushkey
414 414 remote: HG_HOOKTYPE=prepushkey
415 415 remote: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872
416 416 remote: HG_NAMESPACE=phases
417 417 remote: HG_NEW=0
418 418 remote: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872
419 419 remote: HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872
420 420 remote: HG_OLD=1
421 421 remote: HG_PENDING=$TESTTMP/test
422 422 remote: HG_PHASES_MOVED=1
423 423 remote: HG_SOURCE=serve
424 424 remote: HG_TXNID=TXN:$ID$
425 425 remote: HG_TXNNAME=serve
426 426 remote: HG_URL=remote:http:$LOCALIP: (glob)
427 427 remote:
428 428 remote: pushkey-abort: prepushkey hook exited with status 1
429 429 remote: transaction abort!
430 430 remote: rollback completed
431 431 abort: updating ba677d0156c1 to public failed
432 432 % serve errors
433 433 [255]
434 434 #endif
435 435
436 436 Make phases updates work
437 437
438 438 $ cat >> .hg/hgrc <<EOF
439 439 > [hooks]
440 440 > prepushkey = sh -c "printenv.py --line prepushkey 0"
441 441 > EOF
442 442
443 443 #if bundle1
444 444 $ req
445 445 pushing to http://localhost:$HGPORT/
446 446 searching for changes
447 447 no changes found
448 448 remote: prepushkey hook: HG_HOOKNAME=prepushkey
449 449 remote: HG_HOOKTYPE=prepushkey
450 450 remote: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872
451 451 remote: HG_NAMESPACE=phases
452 452 remote: HG_NEW=0
453 453 remote: HG_OLD=1
454 454 remote:
455 455 % serve errors
456 456 [1]
457 457 #endif
458 458
459 459 #if bundle2
460 460 $ req
461 461 pushing to http://localhost:$HGPORT/
462 462 searching for changes
463 463 remote: adding changesets
464 464 remote: adding manifests
465 465 remote: adding file changes
466 466 remote: prepushkey hook: HG_BUNDLE2=1
467 467 remote: HG_HOOKNAME=prepushkey
468 468 remote: HG_HOOKTYPE=prepushkey
469 469 remote: HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872
470 470 remote: HG_NAMESPACE=phases
471 471 remote: HG_NEW=0
472 472 remote: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872
473 473 remote: HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872
474 474 remote: HG_OLD=1
475 475 remote: HG_PENDING=$TESTTMP/test
476 476 remote: HG_PHASES_MOVED=1
477 477 remote: HG_SOURCE=serve
478 478 remote: HG_TXNID=TXN:$ID$
479 479 remote: HG_TXNNAME=serve
480 480 remote: HG_URL=remote:http:$LOCALIP: (glob)
481 481 remote:
482 482 remote: added 1 changesets with 1 changes to 1 files
483 483 % serve errors
484 484 #endif
485 485
486 486 $ hg --config extensions.strip= strip -r 1:
487 487 saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg
488 488
489 489 #if bundle2
490 490
491 491 $ cat > .hg/hgrc <<EOF
492 492 > [web]
493 493 > push_ssl = false
494 494 > allow_push = *
495 495 > [experimental]
496 496 > httppostargs=true
497 497 > EOF
498 498 $ req
499 499 pushing to http://localhost:$HGPORT/
500 500 searching for changes
501 501 remote: adding changesets
502 502 remote: adding manifests
503 503 remote: adding file changes
504 504 remote: added 1 changesets with 1 changes to 1 files
505 505 % serve errors
506 506
507 507 #endif
508 508
509 509 $ cd ..
510 510
511 511 Pushing via hgwebdir works
512 512
513 513 $ hg init hgwebdir
514 514 $ cd hgwebdir
515 515 $ echo 0 > a
516 516 $ hg -q commit -A -m initial
517 517 $ cd ..
518 518
519 519 $ cat > web.conf << EOF
520 520 > [paths]
521 521 > / = *
522 522 > [web]
523 523 > push_ssl = false
524 524 > allow_push = *
525 525 > EOF
526 526
527 527 $ hg serve --web-conf web.conf -p $HGPORT -d --pid-file hg.pid
528 528 $ cat hg.pid >> $DAEMON_PIDS
529 529
530 530 $ hg clone http://localhost:$HGPORT/hgwebdir hgwebdir-local
531 531 requesting all 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
536 536 new changesets 98a3f8f02ba7
537 537 updating to branch default
538 538 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 539 $ cd hgwebdir-local
540 540 $ echo commit > a
541 541 $ hg commit -m 'local commit'
542 542
543 543 $ hg push
544 544 pushing to http://localhost:$HGPORT/hgwebdir
545 545 searching for changes
546 546 remote: adding changesets
547 547 remote: adding manifests
548 548 remote: adding file changes
549 549 remote: added 1 changesets with 1 changes to 1 files
550 550
551 551 $ killdaemons.py
552 552
553 553 $ cd ..
@@ -1,112 +1,112 b''
1 1 #require serve
2 2
3 3 $ hgserve()
4 4 > {
5 5 > hg serve -a localhost -d --pid-file=hg.pid -E errors.log -v $@ \
6 6 > | sed -e "s/:$HGPORT1\\([^0-9]\\)/:HGPORT1\1/g" \
7 7 > -e "s/:$HGPORT2\\([^0-9]\\)/:HGPORT2\1/g" \
8 8 > -e 's/http:\/\/[^/]*\//http:\/\/localhost\//'
9 9 > if [ -f hg.pid ]; then
10 10 > killdaemons.py hg.pid
11 11 > fi
12 12 > echo % errors
13 13 > cat errors.log
14 14 > }
15 15
16 16 $ hg init test
17 17 $ cd test
18 18 $ echo '[web]' > .hg/hgrc
19 19 $ echo 'accesslog = access.log' >> .hg/hgrc
20 20 $ echo "port = $HGPORT1" >> .hg/hgrc
21 21
22 22 Without -v
23 23
24 24 $ hg serve -a localhost -p $HGPORT -d --pid-file=hg.pid -E errors.log
25 25 $ cat hg.pid >> "$DAEMON_PIDS"
26 26 $ if [ -f access.log ]; then
27 27 > echo 'access log created - .hg/hgrc respected'
28 28 > fi
29 29 access log created - .hg/hgrc respected
30 30
31 31 errors
32 32
33 33 $ cat errors.log
34 34
35 35 With -v
36 36
37 37 $ hgserve
38 38 listening at http://localhost/ (bound to *$LOCALIP*:HGPORT1) (glob) (?)
39 39 % errors
40 40
41 41 With -v and -p HGPORT2
42 42
43 43 $ hgserve -p "$HGPORT2"
44 44 listening at http://localhost/ (bound to *$LOCALIP*:HGPORT2) (glob) (?)
45 45 % errors
46 46
47 47 With -v and -p daytime (should fail because low port)
48 48
49 49 #if no-root no-windows
50 50 $ KILLQUIETLY=Y
51 51 $ hgserve -p daytime
52 52 abort: cannot start server at 'localhost:13': Permission denied
53 53 abort: child process failed to start
54 54 % errors
55 55 $ KILLQUIETLY=N
56 56 #endif
57 57
58 58 With --prefix foo
59 59
60 60 $ hgserve --prefix foo
61 61 listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) (?)
62 62 % errors
63 63
64 64 With --prefix /foo
65 65
66 66 $ hgserve --prefix /foo
67 67 listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) (?)
68 68 % errors
69 69
70 70 With --prefix foo/
71 71
72 72 $ hgserve --prefix foo/
73 73 listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) (?)
74 74 % errors
75 75
76 76 With --prefix /foo/
77 77
78 78 $ hgserve --prefix /foo/
79 79 listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) (?)
80 80 % errors
81 81
82 82 $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
83 83
84 84 With out of bounds accesses
85 85
86 86 $ rm access.log
87 87 $ hg serve -a localhost -p $HGPORT -d --prefix some/dir \
88 88 > --pid-file=hg.pid -E errors.log
89 89 $ cat hg.pid >> "$DAEMON_PIDS"
90 90
91 91 $ hg id http://localhost:$HGPORT/some/dir7
92 92 abort: HTTP Error 404: Not Found
93 [255]
93 [100]
94 94 $ hg id http://localhost:$HGPORT/some
95 95 abort: HTTP Error 404: Not Found
96 [255]
96 [100]
97 97
98 98 $ cat access.log errors.log
99 99 $LOCALIP - - [$LOGDATE$] "GET /some/dir7?cmd=capabilities HTTP/1.1" 404 - (glob)
100 100 $LOCALIP - - [$LOGDATE$] "GET /some?cmd=capabilities HTTP/1.1" 404 - (glob)
101 101
102 102 $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
103 103
104 104 issue6362: Previously, this crashed on Python 3
105 105
106 106 $ hg serve -a 0.0.0.0 -d --pid-file=hg.pid
107 107 listening at http://*:$HGPORT1/ (bound to *:$HGPORT1) (glob) (?)
108 108
109 109 $ cat hg.pid > "$DAEMON_PIDS"
110 110 $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
111 111
112 112 $ cd ..
@@ -1,299 +1,299 b''
1 1 #require no-reposimplestore
2 2
3 3 $ hg clone http://localhost:$HGPORT/ copy
4 4 abort: * (glob)
5 [255]
5 [100]
6 6 $ test -d copy
7 7 [1]
8 8
9 9 This server doesn't do range requests so it's basically only good for
10 10 one pull
11 11
12 12 $ "$PYTHON" "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid \
13 13 > --logfile server.log
14 14 $ cat dumb.pid >> $DAEMON_PIDS
15 15 $ hg init remote
16 16 $ cd remote
17 17 $ echo foo > bar
18 18 $ echo c2 > '.dotfile with spaces'
19 19 $ hg add
20 20 adding .dotfile with spaces
21 21 adding bar
22 22 $ hg commit -m"test"
23 23 $ hg tip
24 24 changeset: 0:02770d679fb8
25 25 tag: tip
26 26 user: test
27 27 date: Thu Jan 01 00:00:00 1970 +0000
28 28 summary: test
29 29
30 30 $ cd ..
31 31 $ hg clone static-http://localhost:$HGPORT/remote local
32 32 requesting all changes
33 33 adding changesets
34 34 adding manifests
35 35 adding file changes
36 36 added 1 changesets with 2 changes to 2 files
37 37 new changesets 02770d679fb8
38 38 updating to branch default
39 39 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
40 40 $ cd local
41 41 $ hg verify
42 42 checking changesets
43 43 checking manifests
44 44 crosschecking files in changesets and manifests
45 45 checking files
46 46 checked 1 changesets with 2 changes to 2 files
47 47 $ cat bar
48 48 foo
49 49 $ cd ../remote
50 50 $ echo baz > quux
51 51 $ hg commit -A -mtest2
52 52 adding quux
53 53
54 54 check for HTTP opener failures when cachefile does not exist
55 55
56 56 $ rm .hg/cache/*
57 57 $ cd ../local
58 58 $ cat >> .hg/hgrc <<EOF
59 59 > [hooks]
60 60 > changegroup = sh -c "printenv.py --line changegroup"
61 61 > EOF
62 62 $ hg pull
63 63 pulling from static-http://localhost:$HGPORT/remote
64 64 searching for changes
65 65 adding changesets
66 66 adding manifests
67 67 adding file changes
68 68 added 1 changesets with 1 changes to 1 files
69 69 new changesets 4ac2e3648604
70 70 changegroup hook: HG_HOOKNAME=changegroup
71 71 HG_HOOKTYPE=changegroup
72 72 HG_NODE=4ac2e3648604439c580c69b09ec9d93a88d93432
73 73 HG_NODE_LAST=4ac2e3648604439c580c69b09ec9d93a88d93432
74 74 HG_SOURCE=pull
75 75 HG_TXNID=TXN:$ID$
76 76 HG_TXNNAME=pull
77 77 http://localhost:$HGPORT/remote
78 78 HG_URL=http://localhost:$HGPORT/remote
79 79
80 80 (run 'hg update' to get a working copy)
81 81
82 82 trying to push
83 83
84 84 $ hg update
85 85 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
86 86 $ echo more foo >> bar
87 87 $ hg commit -m"test"
88 88 $ hg push
89 89 pushing to static-http://localhost:$HGPORT/remote
90 90 abort: destination does not support push
91 91 [255]
92 92
93 93 trying clone -r
94 94
95 95 $ cd ..
96 96 $ hg clone -r doesnotexist static-http://localhost:$HGPORT/remote local0
97 97 abort: unknown revision 'doesnotexist'!
98 98 [255]
99 99 $ hg clone -r 0 static-http://localhost:$HGPORT/remote local0
100 100 adding changesets
101 101 adding manifests
102 102 adding file changes
103 103 added 1 changesets with 2 changes to 2 files
104 104 new changesets 02770d679fb8
105 105 updating to branch default
106 106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 107
108 108 test with "/" URI (issue747) and subrepo
109 109
110 110 $ hg init
111 111 $ hg init sub
112 112 $ touch sub/test
113 113 $ hg -R sub commit -A -m "test"
114 114 adding test
115 115 $ hg -R sub tag not-empty
116 116 $ echo sub=sub > .hgsub
117 117 $ echo a > a
118 118 $ hg add a .hgsub
119 119 $ hg -q ci -ma
120 120 $ hg clone static-http://localhost:$HGPORT/ local2
121 121 requesting all changes
122 122 adding changesets
123 123 adding manifests
124 124 adding file changes
125 125 added 1 changesets with 3 changes to 3 files
126 126 new changesets a9ebfbe8e587
127 127 updating to branch default
128 128 cloning subrepo sub from static-http://localhost:$HGPORT/sub
129 129 requesting all changes
130 130 adding changesets
131 131 adding manifests
132 132 adding file changes
133 133 added 2 changesets with 2 changes to 2 files
134 134 new changesets be090ea66256:322ea90975df
135 135 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
136 136 $ cd local2
137 137 $ hg verify
138 138 checking changesets
139 139 checking manifests
140 140 crosschecking files in changesets and manifests
141 141 checking files
142 142 checked 1 changesets with 3 changes to 3 files
143 143 checking subrepo links
144 144 $ cat a
145 145 a
146 146 $ hg paths
147 147 default = static-http://localhost:$HGPORT/
148 148
149 149 test with empty repo (issue965)
150 150
151 151 $ cd ..
152 152 $ hg init remotempty
153 153 $ hg clone static-http://localhost:$HGPORT/remotempty local3
154 154 no changes found
155 155 updating to branch default
156 156 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
157 157 $ cd local3
158 158 $ hg verify
159 159 checking changesets
160 160 checking manifests
161 161 crosschecking files in changesets and manifests
162 162 checking files
163 163 checked 0 changesets with 0 changes to 0 files
164 164 $ hg paths
165 165 default = static-http://localhost:$HGPORT/remotempty
166 166
167 167 test with non-repo
168 168
169 169 $ cd ..
170 170 $ mkdir notarepo
171 171 $ hg clone static-http://localhost:$HGPORT/notarepo local3
172 172 abort: 'http://localhost:$HGPORT/notarepo' does not appear to be an hg repository!
173 173 [255]
174 174
175 175 Clone with tags and branches works
176 176
177 177 $ hg init remote-with-names
178 178 $ cd remote-with-names
179 179 $ echo 0 > foo
180 180 $ hg -q commit -A -m initial
181 181 $ echo 1 > foo
182 182 $ hg commit -m 'commit 1'
183 183 $ hg -q up 0
184 184 $ hg branch mybranch
185 185 marked working directory as branch mybranch
186 186 (branches are permanent and global, did you want a bookmark?)
187 187 $ echo 2 > foo
188 188 $ hg commit -m 'commit 2 (mybranch)'
189 189 $ hg tag -r 1 'default-tag'
190 190 $ hg tag -r 2 'branch-tag'
191 191
192 192 $ cd ..
193 193
194 194 $ hg clone static-http://localhost:$HGPORT/remote-with-names local-with-names
195 195 requesting all changes
196 196 adding changesets
197 197 adding manifests
198 198 adding file changes
199 199 added 5 changesets with 5 changes to 2 files (+1 heads)
200 200 new changesets 68986213bd44:0c325bd2b5a7
201 201 updating to branch default
202 202 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
203 203
204 204 Clone a specific branch works
205 205
206 206 $ hg clone -r mybranch static-http://localhost:$HGPORT/remote-with-names local-with-names-branch
207 207 adding changesets
208 208 adding manifests
209 209 adding file changes
210 210 added 4 changesets with 4 changes to 2 files
211 211 new changesets 68986213bd44:0c325bd2b5a7
212 212 updating to branch mybranch
213 213 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
214 214
215 215 Clone a specific tag works
216 216
217 217 $ hg clone -r default-tag static-http://localhost:$HGPORT/remote-with-names local-with-names-tag
218 218 adding changesets
219 219 adding manifests
220 220 adding file changes
221 221 added 2 changesets with 2 changes to 1 files
222 222 new changesets 68986213bd44:4ee3fcef1c80
223 223 updating to branch default
224 224 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
225 225
226 226 $ killdaemons.py
227 227
228 228 List of files accessed over HTTP:
229 229
230 230 $ cat server.log | sed -n -e 's|.*GET \(/[^ ]*\).*|\1|p' | sort -u
231 231 /.hg/bookmarks
232 232 /.hg/bookmarks.current
233 233 /.hg/cache/hgtagsfnodes1
234 234 /.hg/cache/rbc-names-v1
235 235 /.hg/cache/rbc-revs-v1
236 236 /.hg/dirstate
237 237 /.hg/requires
238 238 /.hg/store/00changelog.i
239 239 /.hg/store/00manifest.i
240 240 /.hg/store/data/%7E2ehgsub.i (no-py37 !)
241 241 /.hg/store/data/%7E2ehgsubstate.i (no-py37 !)
242 242 /.hg/store/data/a.i
243 243 /.hg/store/data/~2ehgsub.i (py37 !)
244 244 /.hg/store/data/~2ehgsubstate.i (py37 !)
245 245 /notarepo/.hg/00changelog.i
246 246 /notarepo/.hg/requires
247 247 /remote-with-names/.hg/bookmarks
248 248 /remote-with-names/.hg/bookmarks.current
249 249 /remote-with-names/.hg/cache/branch2-served
250 250 /remote-with-names/.hg/cache/hgtagsfnodes1
251 251 /remote-with-names/.hg/cache/rbc-names-v1
252 252 /remote-with-names/.hg/cache/rbc-revs-v1
253 253 /remote-with-names/.hg/cache/tags2-served
254 254 /remote-with-names/.hg/dirstate
255 255 /remote-with-names/.hg/localtags
256 256 /remote-with-names/.hg/requires
257 257 /remote-with-names/.hg/store/00changelog.i
258 258 /remote-with-names/.hg/store/00manifest.i
259 259 /remote-with-names/.hg/store/data/%7E2ehgtags.i (no-py37 !)
260 260 /remote-with-names/.hg/store/data/foo.i
261 261 /remote-with-names/.hg/store/data/~2ehgtags.i (py37 !)
262 262 /remote/.hg/bookmarks
263 263 /remote/.hg/bookmarks.current
264 264 /remote/.hg/cache/branch2-base
265 265 /remote/.hg/cache/branch2-immutable
266 266 /remote/.hg/cache/branch2-served
267 267 /remote/.hg/cache/hgtagsfnodes1
268 268 /remote/.hg/cache/rbc-names-v1
269 269 /remote/.hg/cache/rbc-revs-v1
270 270 /remote/.hg/cache/tags2-served
271 271 /remote/.hg/dirstate
272 272 /remote/.hg/localtags
273 273 /remote/.hg/requires
274 274 /remote/.hg/store/00changelog.i
275 275 /remote/.hg/store/00manifest.i
276 276 /remote/.hg/store/data/%7E2edotfile%20with%20spaces.i (no-py37 !)
277 277 /remote/.hg/store/data/%7E2ehgtags.i (no-py37 !)
278 278 /remote/.hg/store/data/bar.i
279 279 /remote/.hg/store/data/quux.i
280 280 /remote/.hg/store/data/~2edotfile%20with%20spaces.i (py37 !)
281 281 /remote/.hg/store/data/~2ehgtags.i (py37 !)
282 282 /remotempty/.hg/bookmarks
283 283 /remotempty/.hg/bookmarks.current
284 284 /remotempty/.hg/dirstate
285 285 /remotempty/.hg/requires
286 286 /remotempty/.hg/store/00changelog.i
287 287 /remotempty/.hg/store/00manifest.i
288 288 /sub/.hg/bookmarks
289 289 /sub/.hg/bookmarks.current
290 290 /sub/.hg/cache/hgtagsfnodes1
291 291 /sub/.hg/cache/rbc-names-v1
292 292 /sub/.hg/cache/rbc-revs-v1
293 293 /sub/.hg/dirstate
294 294 /sub/.hg/requires
295 295 /sub/.hg/store/00changelog.i
296 296 /sub/.hg/store/00manifest.i
297 297 /sub/.hg/store/data/%7E2ehgtags.i (no-py37 !)
298 298 /sub/.hg/store/data/test.i
299 299 /sub/.hg/store/data/~2ehgtags.i (py37 !)
@@ -1,1182 +1,1182 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extdiff]
3 3 > # for portability:
4 4 > pdiff = sh "$RUNTESTDIR/pdiff"
5 5 > [progress]
6 6 > disable=False
7 7 > assume-tty = 1
8 8 > delay = 0
9 9 > # set changedelay really large so we don't see nested topics
10 10 > changedelay = 30000
11 11 > format = topic bar number
12 12 > refresh = 0
13 13 > width = 60
14 14 > EOF
15 15
16 16 Preparing the subrepository 'sub2'
17 17
18 18 $ hg init sub2
19 19 $ echo sub2 > sub2/sub2
20 20 $ hg add -R sub2
21 21 adding sub2/sub2
22 22 $ hg commit -R sub2 -m "sub2 import"
23 23
24 24 Preparing the 'sub1' repo which depends on the subrepo 'sub2'
25 25
26 26 $ hg init sub1
27 27 $ echo sub1 > sub1/sub1
28 28 $ echo "sub2 = ../sub2" > sub1/.hgsub
29 29 $ hg clone sub2 sub1/sub2
30 30 \r (no-eol) (esc)
31 31 linking [ <=> ] 1\r (no-eol) (esc)
32 32 linking [ <=> ] 2\r (no-eol) (esc)
33 33 linking [ <=> ] 3\r (no-eol) (esc)
34 34 linking [ <=> ] 4\r (no-eol) (esc)
35 35 linking [ <=> ] 5\r (no-eol) (esc)
36 36 linking [ <=> ] 6\r (no-eol) (esc)
37 37 \r (no-eol) (esc)
38 38 \r (no-eol) (esc)
39 39 updating [===========================================>] 1/1\r (no-eol) (esc)
40 40 \r (no-eol) (esc)
41 41 updating to branch default
42 42 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 43 $ hg add -R sub1
44 44 adding sub1/.hgsub
45 45 adding sub1/sub1
46 46 $ hg commit -R sub1 -m "sub1 import"
47 47
48 48 Preparing the 'main' repo which depends on the subrepo 'sub1'
49 49
50 50 $ hg init main
51 51 $ echo main > main/main
52 52 $ echo "sub1 = ../sub1" > main/.hgsub
53 53 $ hg clone sub1 main/sub1
54 54 \r (no-eol) (esc)
55 55 linking [ <=> ] 1\r (no-eol) (esc)
56 56 linking [ <=> ] 2\r (no-eol) (esc)
57 57 linking [ <=> ] 3\r (no-eol) (esc)
58 58 linking [ <=> ] 4\r (no-eol) (esc)
59 59 linking [ <=> ] 5\r (no-eol) (esc)
60 60 linking [ <=> ] 6\r (no-eol) (esc)
61 61 linking [ <=> ] 7\r (no-eol) (esc)
62 62 linking [ <=> ] 8\r (no-eol) (esc)
63 63 linking [ <=> ] 9\r (no-eol) (esc) (reposimplestore !)
64 64 linking [ <=> ] 10\r (no-eol) (esc) (reposimplestore !)
65 65 \r (no-eol) (esc)
66 66 \r (no-eol) (esc)
67 67 updating [===========================================>] 3/3\r (no-eol) (esc)
68 68 \r (no-eol) (esc)
69 69 \r (no-eol) (esc)
70 70 linking [ <=> ] 1\r (no-eol) (esc)
71 71 linking [ <=> ] 2\r (no-eol) (esc)
72 72 linking [ <=> ] 3\r (no-eol) (esc)
73 73 linking [ <=> ] 4\r (no-eol) (esc)
74 74 linking [ <=> ] 5\r (no-eol) (esc)
75 75 linking [ <=> ] 6\r (no-eol) (esc)
76 76 updating [===========================================>] 1/1\r (no-eol) (esc)
77 77 \r (no-eol) (esc)
78 78 updating to branch default
79 79 cloning subrepo sub2 from $TESTTMP/sub2
80 80 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
81 81 $ hg add -R main
82 82 adding main/.hgsub
83 83 adding main/main
84 84 $ hg commit -R main -m "main import"
85 85
86 86 #if serve
87 87
88 88 Unfortunately, subrepos not at their nominal location cannot be cloned. But
89 89 they are still served from their location within the local repository. The only
90 90 reason why 'main' can be cloned via the filesystem is because 'sub1' and 'sub2'
91 91 are also available as siblings of 'main'.
92 92
93 93 $ hg serve -R main --debug -S -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log
94 94 adding = $TESTTMP/main
95 95 adding sub1 = $TESTTMP/main/sub1
96 96 adding sub1/sub2 = $TESTTMP/main/sub1/sub2
97 97 listening at http://*:$HGPORT/ (bound to *:$HGPORT) (glob) (?)
98 98 adding = $TESTTMP/main (?)
99 99 adding sub1 = $TESTTMP/main/sub1 (?)
100 100 adding sub1/sub2 = $TESTTMP/main/sub1/sub2 (?)
101 101 $ cat hg1.pid >> $DAEMON_PIDS
102 102
103 103 $ hg clone http://localhost:$HGPORT httpclone --config progress.disable=True
104 104 requesting all changes
105 105 adding changesets
106 106 adding manifests
107 107 adding file changes
108 108 added 1 changesets with 3 changes to 3 files
109 109 new changesets 7f491f53a367
110 110 updating to branch default
111 111 cloning subrepo sub1 from http://localhost:$HGPORT/../sub1
112 112 abort: HTTP Error 404: Not Found
113 [255]
113 [100]
114 114
115 115 $ cat access.log
116 116 * "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
117 117 * "GET /?cmd=batch HTTP/1.1" 200 - * (glob)
118 118 * "GET /?cmd=getbundle HTTP/1.1" 200 - * (glob)
119 119 * "GET /../sub1?cmd=capabilities HTTP/1.1" 404 - (glob)
120 120 $ cat error.log
121 121
122 122 $ killdaemons.py
123 123 $ rm hg1.pid error.log access.log
124 124 #endif
125 125
126 126 Cleaning both repositories, just as a clone -U
127 127
128 128 $ hg up -C -R sub2 null
129 129 \r (no-eol) (esc)
130 130 updating [===========================================>] 1/1\r (no-eol) (esc)
131 131 \r (no-eol) (esc)
132 132 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
133 133 $ hg up -C -R sub1 null
134 134 \r (no-eol) (esc)
135 135 updating [===========================================>] 1/1\r (no-eol) (esc)
136 136 \r (no-eol) (esc)
137 137 \r (no-eol) (esc)
138 138 updating [===========================================>] 3/3\r (no-eol) (esc)
139 139 \r (no-eol) (esc)
140 140 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
141 141 $ hg up -C -R main null
142 142 \r (no-eol) (esc)
143 143 updating [===========================================>] 1/1\r (no-eol) (esc)
144 144 \r (no-eol) (esc)
145 145 \r (no-eol) (esc)
146 146 updating [===========================================>] 3/3\r (no-eol) (esc)
147 147 \r (no-eol) (esc)
148 148 \r (no-eol) (esc)
149 149 updating [===========================================>] 3/3\r (no-eol) (esc)
150 150 \r (no-eol) (esc)
151 151 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
152 152 $ rm -rf main/sub1
153 153 $ rm -rf sub1/sub2
154 154
155 155 Clone main
156 156
157 157 $ hg --config extensions.largefiles= clone main cloned
158 158 \r (no-eol) (esc)
159 159 linking [ <=> ] 1\r (no-eol) (esc)
160 160 linking [ <=> ] 2\r (no-eol) (esc)
161 161 linking [ <=> ] 3\r (no-eol) (esc)
162 162 linking [ <=> ] 4\r (no-eol) (esc)
163 163 linking [ <=> ] 5\r (no-eol) (esc)
164 164 linking [ <=> ] 6\r (no-eol) (esc)
165 165 linking [ <=> ] 7\r (no-eol) (esc)
166 166 linking [ <=> ] 8\r (no-eol) (esc)
167 167 linking [ <=> ] 9\r (no-eol) (esc) (reposimplestore !)
168 168 linking [ <=> ] 10\r (no-eol) (esc) (reposimplestore !)
169 169 \r (no-eol) (esc)
170 170 \r (no-eol) (esc)
171 171 updating [===========================================>] 3/3\r (no-eol) (esc)
172 172 \r (no-eol) (esc)
173 173 \r (no-eol) (esc)
174 174 linking [ <=> ] 1\r (no-eol) (esc)
175 175 linking [ <=> ] 2\r (no-eol) (esc)
176 176 linking [ <=> ] 3\r (no-eol) (esc)
177 177 linking [ <=> ] 4\r (no-eol) (esc)
178 178 linking [ <=> ] 5\r (no-eol) (esc)
179 179 linking [ <=> ] 6\r (no-eol) (esc)
180 180 linking [ <=> ] 7\r (no-eol) (esc)
181 181 linking [ <=> ] 8\r (no-eol) (esc)
182 182 linking [ <=> ] 9\r (no-eol) (esc) (reposimplestore !)
183 183 linking [ <=> ] 10\r (no-eol) (esc) (reposimplestore !)
184 184 updating [===========================================>] 3/3\r (no-eol) (esc)
185 185 \r (no-eol) (esc)
186 186 \r (no-eol) (esc)
187 187 linking [ <=> ] 1\r (no-eol) (esc) (reporevlogstore !)
188 188 linking [ <=> ] 2\r (no-eol) (esc) (reporevlogstore !)
189 189 linking [ <=> ] 3\r (no-eol) (esc) (reporevlogstore !)
190 190 linking [ <=> ] 4\r (no-eol) (esc) (reporevlogstore !)
191 191 linking [ <=> ] 5\r (no-eol) (esc) (reporevlogstore !)
192 192 linking [ <=> ] 6\r (no-eol) (esc) (reporevlogstore !)
193 193 linking [ <=> ] 1\r (no-eol) (esc) (reposimplestore !)
194 194 linking [ <=> ] 2\r (no-eol) (esc) (reposimplestore !)
195 195 linking [ <=> ] 3\r (no-eol) (esc) (reposimplestore !)
196 196 linking [ <=> ] 4\r (no-eol) (esc) (reposimplestore !)
197 197 linking [ <=> ] 5\r (no-eol) (esc) (reposimplestore !)
198 198 linking [ <=> ] 6\r (no-eol) (esc) (reposimplestore !)
199 199 updating [===========================================>] 1/1\r (no-eol) (esc)
200 200 \r (no-eol) (esc)
201 201 updating to branch default
202 202 cloning subrepo sub1 from $TESTTMP/sub1
203 203 cloning subrepo sub1/sub2 from $TESTTMP/sub2
204 204 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
205 205
206 206 Largefiles is NOT enabled in the clone if the source repo doesn't require it
207 207 $ grep largefiles cloned/.hg/hgrc
208 208 [1]
209 209
210 210 Checking cloned repo ids
211 211
212 212 $ printf "cloned " ; hg id -R cloned
213 213 cloned 7f491f53a367 tip
214 214 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
215 215 cloned/sub1 fc3b4ce2696f tip
216 216 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
217 217 cloned/sub1/sub2 c57a0840e3ba tip
218 218
219 219 debugsub output for main and sub1
220 220
221 221 $ hg debugsub -R cloned
222 222 path sub1
223 223 source ../sub1
224 224 revision fc3b4ce2696f7741438c79207583768f2ce6b0dd
225 225 $ hg debugsub -R cloned/sub1
226 226 path sub2
227 227 source ../sub2
228 228 revision c57a0840e3badd667ef3c3ef65471609acb2ba3c
229 229
230 230 Modifying deeply nested 'sub2'
231 231
232 232 $ echo modified > cloned/sub1/sub2/sub2
233 233 $ hg commit --subrepos -m "deep nested modif should trigger a commit" -R cloned
234 234 committing subrepository sub1
235 235 committing subrepository sub1/sub2
236 236
237 237 Checking modified node ids
238 238
239 239 $ printf "cloned " ; hg id -R cloned
240 240 cloned ffe6649062fe tip
241 241 $ printf "cloned/sub1 " ; hg id -R cloned/sub1
242 242 cloned/sub1 2ecb03bf44a9 tip
243 243 $ printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
244 244 cloned/sub1/sub2 53dd3430bcaf tip
245 245
246 246 debugsub output for main and sub1
247 247
248 248 $ hg debugsub -R cloned
249 249 path sub1
250 250 source ../sub1
251 251 revision 2ecb03bf44a94e749e8669481dd9069526ce7cb9
252 252 $ hg debugsub -R cloned/sub1
253 253 path sub2
254 254 source ../sub2
255 255 revision 53dd3430bcaf5ab4a7c48262bcad6d441f510487
256 256
257 257 Check that deep archiving works
258 258
259 259 $ cd cloned
260 260 $ echo 'test' > sub1/sub2/test.txt
261 261 $ hg --config extensions.largefiles=! add sub1/sub2/test.txt
262 262 $ mkdir sub1/sub2/folder
263 263 $ echo 'subfolder' > sub1/sub2/folder/test.txt
264 264 $ hg ci -ASm "add test.txt"
265 265 adding sub1/sub2/folder/test.txt
266 266 committing subrepository sub1
267 267 committing subrepository sub1/sub2
268 268
269 269 $ rm -r main
270 270 $ hg archive -S -qr 'wdir()' ../wdir
271 271 $ cat ../wdir/.hg_archival.txt
272 272 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
273 273 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
274 274 branch: default
275 275 latesttag: null
276 276 latesttagdistance: 4
277 277 changessincelatesttag: 4
278 278 $ hg update -Cq .
279 279
280 280 A deleted subrepo file is flagged as dirty, like the top level repo
281 281
282 282 $ rm -r ../wdir sub1/sub2/folder/test.txt
283 283 $ hg archive -S -qr 'wdir()' ../wdir
284 284 $ cat ../wdir/.hg_archival.txt
285 285 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
286 286 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
287 287 branch: default
288 288 latesttag: null
289 289 latesttagdistance: 4
290 290 changessincelatesttag: 4
291 291 $ hg update -Cq .
292 292 $ rm -r ../wdir
293 293
294 294 $ hg archive -S -qr 'wdir()' ../wdir \
295 295 > --config 'experimental.archivemetatemplate=archived {node|short}\n'
296 296 $ cat ../wdir/.hg_archival.txt
297 297 archived ffffffffffff
298 298 $ rm -r ../wdir
299 299
300 300 .. but first take a detour through some deep removal testing
301 301
302 302 $ hg remove -S -I 're:.*.txt' .
303 303 \r (no-eol) (esc)
304 304 searching [==========================================>] 1/1\r (no-eol) (esc)
305 305 searching [==========================================>] 1/1\r (no-eol) (esc)
306 306 \r (no-eol) (esc)
307 307 \r (no-eol) (esc)
308 308 deleting [=====================> ] 1/2\r (no-eol) (esc)
309 309 \r (no-eol) (esc)
310 310 \r (no-eol) (esc)
311 311 deleting [===========================================>] 2/2\r (no-eol) (esc)
312 312 \r (no-eol) (esc)
313 313 removing sub1/sub2/folder/test.txt
314 314 removing sub1/sub2/test.txt
315 315 $ hg status -S
316 316 R sub1/sub2/folder/test.txt
317 317 R sub1/sub2/test.txt
318 318 $ hg update -Cq
319 319 $ hg remove -I 're:.*.txt' sub1
320 320 \r (no-eol) (esc)
321 321 searching [==========================================>] 1/1\r (no-eol) (esc)
322 322 \r (no-eol) (esc)
323 323 \r (no-eol) (esc)
324 324 deleting [===========================================>] 1/1\r (no-eol) (esc)
325 325 \r (no-eol) (esc)
326 326 $ hg status -S
327 327 $ hg remove sub1/sub2/folder/test.txt
328 328 \r (no-eol) (esc)
329 329 searching [==========================================>] 1/1\r (no-eol) (esc)
330 330 searching [==========================================>] 1/1\r (no-eol) (esc)
331 331 \r (no-eol) (esc)
332 332 \r (no-eol) (esc)
333 333 deleting [===========================================>] 1/1\r (no-eol) (esc)
334 334 \r (no-eol) (esc)
335 335 \r (no-eol) (esc)
336 336 deleting [===========================================>] 1/1\r (no-eol) (esc)
337 337 \r (no-eol) (esc)
338 338 \r (no-eol) (esc)
339 339 deleting [===========================================>] 1/1\r (no-eol) (esc)
340 340 \r (no-eol) (esc)
341 341 $ hg remove sub1/.hgsubstate
342 342 \r (no-eol) (esc)
343 343 searching [==========================================>] 1/1\r (no-eol) (esc)
344 344 \r (no-eol) (esc)
345 345 \r (no-eol) (esc)
346 346 deleting [===========================================>] 1/1\r (no-eol) (esc)
347 347 \r (no-eol) (esc)
348 348 \r (no-eol) (esc)
349 349 deleting [===========================================>] 1/1\r (no-eol) (esc)
350 350 \r (no-eol) (esc)
351 351 $ mv sub1/.hgsub sub1/x.hgsub
352 352 $ hg status -S
353 353 warning: subrepo spec file 'sub1/.hgsub' not found
354 354 R sub1/.hgsubstate
355 355 R sub1/sub2/folder/test.txt
356 356 ! sub1/.hgsub
357 357 ? sub1/x.hgsub
358 358 $ hg status -R sub1
359 359 warning: subrepo spec file 'sub1/.hgsub' not found
360 360 R .hgsubstate
361 361 ! .hgsub
362 362 ? x.hgsub
363 363 $ mv sub1/x.hgsub sub1/.hgsub
364 364 $ hg update -Cq
365 365 $ touch sub1/foo
366 366 $ hg forget sub1/sub2/folder/test.txt
367 367 $ rm sub1/sub2/test.txt
368 368
369 369 Test relative path printing + subrepos
370 370 $ mkdir -p foo/bar
371 371 $ cd foo
372 372 $ touch bar/abc
373 373 $ hg addremove -S ..
374 374 \r (no-eol) (esc)
375 375 searching for exact renames [========================>] 1/1\r (no-eol) (esc)
376 376 \r (no-eol) (esc)
377 377 adding ../sub1/sub2/folder/test.txt
378 378 removing ../sub1/sub2/test.txt
379 379 adding ../sub1/foo
380 380 adding bar/abc
381 381 $ cd ..
382 382 $ hg status -S
383 383 A foo/bar/abc
384 384 A sub1/foo
385 385 R sub1/sub2/test.txt
386 386
387 387 Archive wdir() with subrepos
388 388 $ hg rm main
389 389 \r (no-eol) (esc)
390 390 deleting [===========================================>] 1/1\r (no-eol) (esc)
391 391 \r (no-eol) (esc)
392 392 $ hg archive -S -r 'wdir()' ../wdir
393 393 \r (no-eol) (esc)
394 394 archiving [ ] 0/3\r (no-eol) (esc)
395 395 archiving [=============> ] 1/3\r (no-eol) (esc)
396 396 archiving [===========================> ] 2/3\r (no-eol) (esc)
397 397 archiving [==========================================>] 3/3\r (no-eol) (esc)
398 398 \r (no-eol) (esc)
399 399 \r (no-eol) (esc)
400 400 archiving (sub1) [ ] 0/4\r (no-eol) (esc)
401 401 archiving (sub1) [========> ] 1/4\r (no-eol) (esc)
402 402 archiving (sub1) [=================> ] 2/4\r (no-eol) (esc)
403 403 archiving (sub1) [==========================> ] 3/4\r (no-eol) (esc)
404 404 archiving (sub1) [===================================>] 4/4\r (no-eol) (esc)
405 405 \r (no-eol) (esc)
406 406 \r (no-eol) (esc)
407 407 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (esc)
408 408 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (esc)
409 409 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (esc)
410 410 \r (no-eol) (esc)
411 411 $ diff -r . ../wdir | egrep -v '\.hg$|^Common subdirectories:'
412 412 Only in ../wdir: .hg_archival.txt
413 413
414 414 $ find ../wdir -type f | sort
415 415 ../wdir/.hg_archival.txt
416 416 ../wdir/.hgsub
417 417 ../wdir/.hgsubstate
418 418 ../wdir/foo/bar/abc
419 419 ../wdir/sub1/.hgsub
420 420 ../wdir/sub1/.hgsubstate
421 421 ../wdir/sub1/foo
422 422 ../wdir/sub1/sub1
423 423 ../wdir/sub1/sub2/folder/test.txt
424 424 ../wdir/sub1/sub2/sub2
425 425
426 426 $ cat ../wdir/.hg_archival.txt
427 427 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
428 428 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd+
429 429 branch: default
430 430 latesttag: null
431 431 latesttagdistance: 4
432 432 changessincelatesttag: 4
433 433
434 434 Attempting to archive 'wdir()' with a missing file is handled gracefully
435 435 $ rm sub1/sub1
436 436 $ rm -r ../wdir
437 437 $ hg archive -v -S -r 'wdir()' ../wdir
438 438 \r (no-eol) (esc)
439 439 archiving [ ] 0/3\r (no-eol) (esc)
440 440 archiving [=============> ] 1/3\r (no-eol) (esc)
441 441 archiving [===========================> ] 2/3\r (no-eol) (esc)
442 442 archiving [==========================================>] 3/3\r (no-eol) (esc)
443 443 \r (no-eol) (esc)
444 444 \r (no-eol) (esc)
445 445 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
446 446 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
447 447 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
448 448 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
449 449 \r (no-eol) (esc)
450 450 \r (no-eol) (esc)
451 451 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (esc)
452 452 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (esc)
453 453 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (esc)
454 454 \r (no-eol) (esc)
455 455 $ find ../wdir -type f | sort
456 456 ../wdir/.hg_archival.txt
457 457 ../wdir/.hgsub
458 458 ../wdir/.hgsubstate
459 459 ../wdir/foo/bar/abc
460 460 ../wdir/sub1/.hgsub
461 461 ../wdir/sub1/.hgsubstate
462 462 ../wdir/sub1/foo
463 463 ../wdir/sub1/sub2/folder/test.txt
464 464 ../wdir/sub1/sub2/sub2
465 465
466 466 Continue relative path printing + subrepos
467 467 $ hg update -Cq
468 468 $ rm -r ../wdir
469 469 $ hg archive -S -r 'wdir()' ../wdir
470 470 \r (no-eol) (esc)
471 471 archiving [ ] 0/3\r (no-eol) (esc)
472 472 archiving [=============> ] 1/3\r (no-eol) (esc)
473 473 archiving [===========================> ] 2/3\r (no-eol) (esc)
474 474 archiving [==========================================>] 3/3\r (no-eol) (esc)
475 475 \r (no-eol) (esc)
476 476 \r (no-eol) (esc)
477 477 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
478 478 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
479 479 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
480 480 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
481 481 \r (no-eol) (esc)
482 482 \r (no-eol) (esc)
483 483 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (esc)
484 484 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (esc)
485 485 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (esc)
486 486 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (esc)
487 487 \r (no-eol) (esc)
488 488 $ cat ../wdir/.hg_archival.txt
489 489 repo: 7f491f53a367861f47ee64a80eb997d1f341b77a
490 490 node: 9bb10eebee29dc0f1201dcf5977b811a540255fd
491 491 branch: default
492 492 latesttag: null
493 493 latesttagdistance: 4
494 494 changessincelatesttag: 4
495 495
496 496 $ touch sub1/sub2/folder/bar
497 497 $ hg addremove sub1/sub2
498 498 adding sub1/sub2/folder/bar
499 499 $ hg status -S
500 500 A sub1/sub2/folder/bar
501 501 ? foo/bar/abc
502 502 ? sub1/foo
503 503 $ hg update -Cq
504 504 $ hg addremove sub1
505 505 adding sub1/sub2/folder/bar
506 506 adding sub1/foo
507 507 $ hg update -Cq
508 508 $ rm sub1/sub2/folder/test.txt
509 509 $ rm sub1/sub2/test.txt
510 510 $ hg ci -ASm "remove test.txt"
511 511 adding sub1/sub2/folder/bar
512 512 removing sub1/sub2/folder/test.txt
513 513 removing sub1/sub2/test.txt
514 514 adding sub1/foo
515 515 adding foo/bar/abc
516 516 committing subrepository sub1
517 517 committing subrepository sub1/sub2
518 518
519 519 $ hg forget sub1/sub2/sub2
520 520 $ echo x > sub1/sub2/x.txt
521 521 $ hg add sub1/sub2/x.txt
522 522
523 523 Files sees uncommitted adds and removes in subrepos
524 524 $ hg files -S
525 525 .hgsub
526 526 .hgsubstate
527 527 foo/bar/abc
528 528 main
529 529 sub1/.hgsub
530 530 sub1/.hgsubstate
531 531 sub1/foo
532 532 sub1/sub1
533 533 sub1/sub2/folder/bar
534 534 sub1/sub2/x.txt
535 535
536 536 $ hg files -S "set:eol('dos') or eol('unix') or size('<= 0')"
537 537 .hgsub
538 538 .hgsubstate
539 539 foo/bar/abc
540 540 main
541 541 sub1/.hgsub
542 542 sub1/.hgsubstate
543 543 sub1/foo
544 544 sub1/sub1
545 545 sub1/sub2/folder/bar
546 546 sub1/sub2/x.txt
547 547
548 548 $ hg files -r '.^' -S "set:eol('dos') or eol('unix')"
549 549 .hgsub
550 550 .hgsubstate
551 551 main
552 552 sub1/.hgsub
553 553 sub1/.hgsubstate
554 554 sub1/sub1
555 555 sub1/sub2/folder/test.txt
556 556 sub1/sub2/sub2
557 557 sub1/sub2/test.txt
558 558
559 559 $ hg files sub1
560 560 sub1/.hgsub
561 561 sub1/.hgsubstate
562 562 sub1/foo
563 563 sub1/sub1
564 564 sub1/sub2/folder/bar
565 565 sub1/sub2/x.txt
566 566
567 567 $ hg files sub1/sub2
568 568 sub1/sub2/folder/bar
569 569 sub1/sub2/x.txt
570 570
571 571 $ hg files
572 572 .hgsub
573 573 .hgsubstate
574 574 foo/bar/abc
575 575 main
576 576
577 577 $ hg files -S -r '.^' sub1/sub2/folder
578 578 sub1/sub2/folder/test.txt
579 579
580 580 $ hg files -S -r '.^' sub1/sub2/missing
581 581 sub1/sub2/missing: no such file in rev 78026e779ea6
582 582 [1]
583 583
584 584 $ hg files -r '.^' sub1/
585 585 sub1/.hgsub
586 586 sub1/.hgsubstate
587 587 sub1/sub1
588 588 sub1/sub2/folder/test.txt
589 589 sub1/sub2/sub2
590 590 sub1/sub2/test.txt
591 591
592 592 $ hg files -r '.^' sub1/sub2
593 593 sub1/sub2/folder/test.txt
594 594 sub1/sub2/sub2
595 595 sub1/sub2/test.txt
596 596
597 597 $ hg rollback -q
598 598 $ hg up -Cq
599 599
600 600 $ hg --config extensions.largefiles=! archive -S ../archive_all
601 601 \r (no-eol) (esc)
602 602 archiving [ ] 0/3\r (no-eol) (esc)
603 603 archiving [=============> ] 1/3\r (no-eol) (esc)
604 604 archiving [===========================> ] 2/3\r (no-eol) (esc)
605 605 archiving [==========================================>] 3/3\r (no-eol) (esc)
606 606 \r (no-eol) (esc)
607 607 \r (no-eol) (esc)
608 608 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
609 609 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
610 610 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
611 611 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
612 612 \r (no-eol) (esc)
613 613 \r (no-eol) (esc)
614 614 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (esc)
615 615 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (esc)
616 616 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (esc)
617 617 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (esc)
618 618 \r (no-eol) (esc)
619 619 $ find ../archive_all | sort
620 620 ../archive_all
621 621 ../archive_all/.hg_archival.txt
622 622 ../archive_all/.hgsub
623 623 ../archive_all/.hgsubstate
624 624 ../archive_all/main
625 625 ../archive_all/sub1
626 626 ../archive_all/sub1/.hgsub
627 627 ../archive_all/sub1/.hgsubstate
628 628 ../archive_all/sub1/sub1
629 629 ../archive_all/sub1/sub2
630 630 ../archive_all/sub1/sub2/folder
631 631 ../archive_all/sub1/sub2/folder/test.txt
632 632 ../archive_all/sub1/sub2/sub2
633 633 ../archive_all/sub1/sub2/test.txt
634 634
635 635 Check that archive -X works in deep subrepos
636 636
637 637 $ hg --config extensions.largefiles=! archive -S -X '**test*' ../archive_exclude
638 638 \r (no-eol) (esc)
639 639 archiving [ ] 0/3\r (no-eol) (esc)
640 640 archiving [=============> ] 1/3\r (no-eol) (esc)
641 641 archiving [===========================> ] 2/3\r (no-eol) (esc)
642 642 archiving [==========================================>] 3/3\r (no-eol) (esc)
643 643 \r (no-eol) (esc)
644 644 \r (no-eol) (esc)
645 645 archiving (sub1) [ ] 0/3\r (no-eol) (esc)
646 646 archiving (sub1) [===========> ] 1/3\r (no-eol) (esc)
647 647 archiving (sub1) [=======================> ] 2/3\r (no-eol) (esc)
648 648 archiving (sub1) [===================================>] 3/3\r (no-eol) (esc)
649 649 \r (no-eol) (esc)
650 650 \r (no-eol) (esc)
651 651 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (esc)
652 652 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (esc)
653 653 \r (no-eol) (esc)
654 654 $ find ../archive_exclude | sort
655 655 ../archive_exclude
656 656 ../archive_exclude/.hg_archival.txt
657 657 ../archive_exclude/.hgsub
658 658 ../archive_exclude/.hgsubstate
659 659 ../archive_exclude/main
660 660 ../archive_exclude/sub1
661 661 ../archive_exclude/sub1/.hgsub
662 662 ../archive_exclude/sub1/.hgsubstate
663 663 ../archive_exclude/sub1/sub1
664 664 ../archive_exclude/sub1/sub2
665 665 ../archive_exclude/sub1/sub2/sub2
666 666
667 667 $ hg --config extensions.largefiles=! archive -S -I '**test*' ../archive_include
668 668 \r (no-eol) (esc)
669 669 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
670 670 \r (no-eol) (esc)
671 671 \r (no-eol) (esc)
672 672 archiving (sub1/sub2) [ ] 0/2\r (no-eol) (esc)
673 673 archiving (sub1/sub2) [==============> ] 1/2\r (no-eol) (esc)
674 674 archiving (sub1/sub2) [==============================>] 2/2\r (no-eol) (esc)
675 675 \r (no-eol) (esc)
676 676 $ find ../archive_include | sort
677 677 ../archive_include
678 678 ../archive_include/sub1
679 679 ../archive_include/sub1/sub2
680 680 ../archive_include/sub1/sub2/folder
681 681 ../archive_include/sub1/sub2/folder/test.txt
682 682 ../archive_include/sub1/sub2/test.txt
683 683
684 684 Check that deep archive works with largefiles (which overrides hgsubrepo impl)
685 685 This also tests the repo.ui regression in 43fb170a23bd, and that lf subrepo
686 686 subrepos are archived properly.
687 687 Note that add --large through a subrepo currently adds the file as a normal file
688 688
689 689 $ echo "large" > sub1/sub2/large.bin
690 690 $ hg --config extensions.largefiles= add --large -R sub1/sub2 sub1/sub2/large.bin
691 691 $ echo "large" > large.bin
692 692 $ hg --config extensions.largefiles= add --large large.bin
693 693 $ hg --config extensions.largefiles= ci -S -m "add large files"
694 694 committing subrepository sub1
695 695 committing subrepository sub1/sub2
696 696
697 697 $ hg --config extensions.largefiles= archive -S ../archive_lf
698 698 $ find ../archive_lf | sort
699 699 ../archive_lf
700 700 ../archive_lf/.hg_archival.txt
701 701 ../archive_lf/.hgsub
702 702 ../archive_lf/.hgsubstate
703 703 ../archive_lf/large.bin
704 704 ../archive_lf/main
705 705 ../archive_lf/sub1
706 706 ../archive_lf/sub1/.hgsub
707 707 ../archive_lf/sub1/.hgsubstate
708 708 ../archive_lf/sub1/sub1
709 709 ../archive_lf/sub1/sub2
710 710 ../archive_lf/sub1/sub2/folder
711 711 ../archive_lf/sub1/sub2/folder/test.txt
712 712 ../archive_lf/sub1/sub2/large.bin
713 713 ../archive_lf/sub1/sub2/sub2
714 714 ../archive_lf/sub1/sub2/test.txt
715 715 $ rm -rf ../archive_lf
716 716
717 717 Exclude large files from main and sub-sub repo
718 718
719 719 $ hg --config extensions.largefiles= archive -S -X '**.bin' ../archive_lf
720 720 $ find ../archive_lf | sort
721 721 ../archive_lf
722 722 ../archive_lf/.hg_archival.txt
723 723 ../archive_lf/.hgsub
724 724 ../archive_lf/.hgsubstate
725 725 ../archive_lf/main
726 726 ../archive_lf/sub1
727 727 ../archive_lf/sub1/.hgsub
728 728 ../archive_lf/sub1/.hgsubstate
729 729 ../archive_lf/sub1/sub1
730 730 ../archive_lf/sub1/sub2
731 731 ../archive_lf/sub1/sub2/folder
732 732 ../archive_lf/sub1/sub2/folder/test.txt
733 733 ../archive_lf/sub1/sub2/sub2
734 734 ../archive_lf/sub1/sub2/test.txt
735 735 $ rm -rf ../archive_lf
736 736
737 737 Exclude normal files from main and sub-sub repo
738 738
739 739 $ hg --config extensions.largefiles= archive -S -X '**.txt' -p '.' ../archive_lf.tgz
740 740 $ tar -tzf ../archive_lf.tgz | sort
741 741 .hgsub
742 742 .hgsubstate
743 743 large.bin
744 744 main
745 745 sub1/.hgsub
746 746 sub1/.hgsubstate
747 747 sub1/sub1
748 748 sub1/sub2/large.bin
749 749 sub1/sub2/sub2
750 750
751 751 Include normal files from within a largefiles subrepo
752 752
753 753 $ hg --config extensions.largefiles= archive -S -I '**.txt' ../archive_lf
754 754 $ find ../archive_lf | sort
755 755 ../archive_lf
756 756 ../archive_lf/.hg_archival.txt
757 757 ../archive_lf/sub1
758 758 ../archive_lf/sub1/sub2
759 759 ../archive_lf/sub1/sub2/folder
760 760 ../archive_lf/sub1/sub2/folder/test.txt
761 761 ../archive_lf/sub1/sub2/test.txt
762 762 $ rm -rf ../archive_lf
763 763
764 764 Include large files from within a largefiles subrepo
765 765
766 766 $ hg --config extensions.largefiles= archive -S -I '**.bin' ../archive_lf
767 767 $ find ../archive_lf | sort
768 768 ../archive_lf
769 769 ../archive_lf/large.bin
770 770 ../archive_lf/sub1
771 771 ../archive_lf/sub1/sub2
772 772 ../archive_lf/sub1/sub2/large.bin
773 773 $ rm -rf ../archive_lf
774 774
775 775 Find an exact largefile match in a largefiles subrepo
776 776
777 777 $ hg --config extensions.largefiles= archive -S -I 'sub1/sub2/large.bin' ../archive_lf
778 778 $ find ../archive_lf | sort
779 779 ../archive_lf
780 780 ../archive_lf/sub1
781 781 ../archive_lf/sub1/sub2
782 782 ../archive_lf/sub1/sub2/large.bin
783 783 $ rm -rf ../archive_lf
784 784
785 785 The local repo enables largefiles if a largefiles repo is cloned
786 786
787 787 $ hg showconfig extensions
788 788 extensions.largefiles=
789 789
790 790 $ hg --config extensions.largefiles= clone -qU . ../lfclone
791 791 $ grep largefiles ../lfclone/.hg/requires
792 792 largefiles
793 793
794 794 Find an exact match to a standin (should archive nothing)
795 795 $ hg --config extensions.largefiles= archive -S -I 'sub/sub2/.hglf/large.bin' ../archive_lf
796 796 $ find ../archive_lf 2> /dev/null | sort
797 797
798 798 $ cat >> $HGRCPATH <<EOF
799 799 > [extensions]
800 800 > largefiles=
801 801 > [largefiles]
802 802 > patterns=glob:**.dat
803 803 > EOF
804 804
805 805 Test forget through a deep subrepo with the largefiles extension, both a
806 806 largefile and a normal file. Then a largefile that hasn't been committed yet.
807 807 $ touch sub1/sub2/untracked.txt
808 808 $ touch sub1/sub2/large.dat
809 809 $ hg forget sub1/sub2/large.bin sub1/sub2/test.txt sub1/sub2/untracked.txt
810 810 not removing sub1/sub2/untracked.txt: file is already untracked
811 811 [1]
812 812 $ hg add --large --dry-run -v sub1/sub2/untracked.txt
813 813 adding sub1/sub2/untracked.txt as a largefile
814 814 $ hg add --large -v sub1/sub2/untracked.txt
815 815 adding sub1/sub2/untracked.txt as a largefile
816 816 $ hg add --normal -v sub1/sub2/large.dat
817 817 adding sub1/sub2/large.dat
818 818 $ hg forget -v sub1/sub2/untracked.txt
819 819 removing sub1/sub2/untracked.txt
820 820 $ hg status -S
821 821 A sub1/sub2/large.dat
822 822 R sub1/sub2/large.bin
823 823 R sub1/sub2/test.txt
824 824 ? foo/bar/abc
825 825 ? sub1/sub2/untracked.txt
826 826 ? sub1/sub2/x.txt
827 827 $ hg add sub1/sub2
828 828
829 829 $ hg archive -S -r 'wdir()' ../wdir2
830 830 $ diff -r . ../wdir2 | egrep -v '\.hg$|^Common subdirectories:'
831 831 Only in ../wdir2: .hg_archival.txt
832 832 Only in .: .hglf
833 833 Only in .: foo
834 834 Only in ./sub1/sub2: large.bin
835 835 Only in ./sub1/sub2: test.txt
836 836 Only in ./sub1/sub2: untracked.txt
837 837 Only in ./sub1/sub2: x.txt
838 838 $ find ../wdir2 -type f | sort
839 839 ../wdir2/.hg_archival.txt
840 840 ../wdir2/.hgsub
841 841 ../wdir2/.hgsubstate
842 842 ../wdir2/large.bin
843 843 ../wdir2/main
844 844 ../wdir2/sub1/.hgsub
845 845 ../wdir2/sub1/.hgsubstate
846 846 ../wdir2/sub1/sub1
847 847 ../wdir2/sub1/sub2/folder/test.txt
848 848 ../wdir2/sub1/sub2/large.dat
849 849 ../wdir2/sub1/sub2/sub2
850 850 $ hg status -S -mac -n | sort
851 851 .hgsub
852 852 .hgsubstate
853 853 large.bin
854 854 main
855 855 sub1/.hgsub
856 856 sub1/.hgsubstate
857 857 sub1/sub1
858 858 sub1/sub2/folder/test.txt
859 859 sub1/sub2/large.dat
860 860 sub1/sub2/sub2
861 861
862 862 $ hg ci -Sqm 'forget testing'
863 863
864 864 Test 'wdir()' modified file archiving with largefiles
865 865 $ echo 'mod' > main
866 866 $ echo 'mod' > large.bin
867 867 $ echo 'mod' > sub1/sub2/large.dat
868 868 $ hg archive -S -r 'wdir()' ../wdir3
869 869 $ diff -r . ../wdir3 | egrep -v '\.hg$|^Common subdirectories'
870 870 Only in ../wdir3: .hg_archival.txt
871 871 Only in .: .hglf
872 872 Only in .: foo
873 873 Only in ./sub1/sub2: large.bin
874 874 Only in ./sub1/sub2: test.txt
875 875 Only in ./sub1/sub2: untracked.txt
876 876 Only in ./sub1/sub2: x.txt
877 877 $ find ../wdir3 -type f | sort
878 878 ../wdir3/.hg_archival.txt
879 879 ../wdir3/.hgsub
880 880 ../wdir3/.hgsubstate
881 881 ../wdir3/large.bin
882 882 ../wdir3/main
883 883 ../wdir3/sub1/.hgsub
884 884 ../wdir3/sub1/.hgsubstate
885 885 ../wdir3/sub1/sub1
886 886 ../wdir3/sub1/sub2/folder/test.txt
887 887 ../wdir3/sub1/sub2/large.dat
888 888 ../wdir3/sub1/sub2/sub2
889 889 $ hg up -Cq
890 890
891 891 Test issue4330: commit a directory where only normal files have changed
892 892 $ touch foo/bar/large.dat
893 893 $ hg add --large foo/bar/large.dat
894 894 $ hg ci -m 'add foo/bar/large.dat'
895 895 $ touch a.txt
896 896 $ touch a.dat
897 897 $ hg add -v foo/bar/abc a.txt a.dat
898 898 adding a.dat as a largefile
899 899 adding a.txt
900 900 adding foo/bar/abc
901 901 $ hg ci -m 'dir commit with only normal file deltas' foo/bar
902 902 $ hg status
903 903 A a.dat
904 904 A a.txt
905 905
906 906 Test a directory commit with a changed largefile and a changed normal file
907 907 $ echo changed > foo/bar/large.dat
908 908 $ echo changed > foo/bar/abc
909 909 $ hg ci -m 'dir commit with normal and lf file deltas' foo
910 910 $ hg status
911 911 A a.dat
912 912 A a.txt
913 913
914 914 $ hg ci -m "add a.*"
915 915 $ hg mv a.dat b.dat
916 916 $ hg mv foo/bar/abc foo/bar/def
917 917 $ hg status -C
918 918 A b.dat
919 919 a.dat
920 920 A foo/bar/def
921 921 foo/bar/abc
922 922 R a.dat
923 923 R foo/bar/abc
924 924
925 925 $ hg ci -m "move large and normal"
926 926 $ hg status -C --rev '.^' --rev .
927 927 A b.dat
928 928 a.dat
929 929 A foo/bar/def
930 930 foo/bar/abc
931 931 R a.dat
932 932 R foo/bar/abc
933 933
934 934
935 935 $ echo foo > main
936 936 $ hg ci -m "mod parent only"
937 937 $ hg init sub3
938 938 $ echo "sub3 = sub3" >> .hgsub
939 939 $ echo xyz > sub3/a.txt
940 940 $ hg add sub3/a.txt
941 941 $ hg ci -Sm "add sub3"
942 942 committing subrepository sub3
943 943 $ cat .hgsub | grep -v sub3 > .hgsub1
944 944 $ mv .hgsub1 .hgsub
945 945 $ hg ci -m "remove sub3"
946 946
947 947 $ hg log -r "subrepo()" --style compact
948 948 0 7f491f53a367 1970-01-01 00:00 +0000 test
949 949 main import
950 950
951 951 1 ffe6649062fe 1970-01-01 00:00 +0000 test
952 952 deep nested modif should trigger a commit
953 953
954 954 2 9bb10eebee29 1970-01-01 00:00 +0000 test
955 955 add test.txt
956 956
957 957 3 7c64f035294f 1970-01-01 00:00 +0000 test
958 958 add large files
959 959
960 960 4 f734a59e2e35 1970-01-01 00:00 +0000 test
961 961 forget testing
962 962
963 963 11 9685a22af5db 1970-01-01 00:00 +0000 test
964 964 add sub3
965 965
966 966 12[tip] 2e0485b475b9 1970-01-01 00:00 +0000 test
967 967 remove sub3
968 968
969 969 $ hg log -r "subrepo('sub3')" --style compact
970 970 11 9685a22af5db 1970-01-01 00:00 +0000 test
971 971 add sub3
972 972
973 973 12[tip] 2e0485b475b9 1970-01-01 00:00 +0000 test
974 974 remove sub3
975 975
976 976 $ hg log -r "subrepo('bogus')" --style compact
977 977
978 978
979 979 Test .hgsubstate in the R state
980 980
981 981 $ hg rm .hgsub .hgsubstate
982 982 \r (no-eol) (esc)
983 983 deleting [=====================> ] 1/2\r (no-eol) (esc)
984 984 deleting [===========================================>] 2/2\r (no-eol) (esc)
985 985 \r (no-eol) (esc)
986 986 $ hg ci -m 'trash subrepo tracking'
987 987
988 988 $ hg log -r "subrepo('re:sub\d+')" --style compact
989 989 0 7f491f53a367 1970-01-01 00:00 +0000 test
990 990 main import
991 991
992 992 1 ffe6649062fe 1970-01-01 00:00 +0000 test
993 993 deep nested modif should trigger a commit
994 994
995 995 2 9bb10eebee29 1970-01-01 00:00 +0000 test
996 996 add test.txt
997 997
998 998 3 7c64f035294f 1970-01-01 00:00 +0000 test
999 999 add large files
1000 1000
1001 1001 4 f734a59e2e35 1970-01-01 00:00 +0000 test
1002 1002 forget testing
1003 1003
1004 1004 11 9685a22af5db 1970-01-01 00:00 +0000 test
1005 1005 add sub3
1006 1006
1007 1007 12 2e0485b475b9 1970-01-01 00:00 +0000 test
1008 1008 remove sub3
1009 1009
1010 1010 13[tip] a68b2c361653 1970-01-01 00:00 +0000 test
1011 1011 trash subrepo tracking
1012 1012
1013 1013
1014 1014 Restore the trashed subrepo tracking
1015 1015
1016 1016 $ hg rollback -q
1017 1017 $ hg update -Cq .
1018 1018
1019 1019 Interaction with extdiff, largefiles and subrepos
1020 1020
1021 1021 $ hg --config extensions.extdiff= pdiff -S
1022 1022
1023 1023 $ hg --config extensions.extdiff= pdiff -r '.^' -S
1024 1024 \r (no-eol) (esc)
1025 1025 archiving [ ] 0/2\r (no-eol) (esc)
1026 1026 archiving [====================> ] 1/2\r (no-eol) (esc)
1027 1027 archiving [==========================================>] 2/2\r (no-eol) (esc)
1028 1028 \r (no-eol) (esc)
1029 1029 \r (no-eol) (esc)
1030 1030 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1031 1031 \r (no-eol) (esc)
1032 1032 \r (no-eol) (esc)
1033 1033 archiving (sub1/sub2) [ <=> ] 0\r (no-eol) (esc)
1034 1034 \r (no-eol) (esc)
1035 1035 \r (no-eol) (esc)
1036 1036 archiving (sub3) [ <=> ] 0\r (no-eol) (esc)
1037 1037 \r (no-eol) (esc)
1038 1038 \r (no-eol) (esc)
1039 1039 archiving [ ] 0/2\r (no-eol) (esc)
1040 1040 archiving [====================> ] 1/2\r (no-eol) (esc)
1041 1041 archiving [==========================================>] 2/2\r (no-eol) (esc)
1042 1042 \r (no-eol) (esc)
1043 1043 \r (no-eol) (esc)
1044 1044 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1045 1045 \r (no-eol) (esc)
1046 1046 \r (no-eol) (esc)
1047 1047 archiving (sub1/sub2) [ <=> ] 0\r (no-eol) (esc)
1048 1048 \r (no-eol) (esc)
1049 1049 diff -Nru cloned.*/.hgsub cloned/.hgsub (glob)
1050 1050 --- cloned.*/.hgsub * (glob)
1051 1051 +++ cloned/.hgsub * (glob)
1052 1052 @@ -1,2 +1* @@ (glob)
1053 1053 sub1 = ../sub1
1054 1054 -sub3 = sub3
1055 1055 diff -Nru cloned.*/.hgsubstate cloned/.hgsubstate (glob)
1056 1056 --- cloned.*/.hgsubstate * (glob)
1057 1057 +++ cloned/.hgsubstate * (glob)
1058 1058 @@ -1,2 +1* @@ (glob)
1059 1059 7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
1060 1060 -b1a26de6f2a045a9f079323693614ee322f1ff7e sub3
1061 1061 [1]
1062 1062
1063 1063 $ hg --config extensions.extdiff= pdiff -r 0 -r '.^' -S
1064 1064 \r (no-eol) (esc)
1065 1065 archiving [ ] 0/3\r (no-eol) (esc)
1066 1066 archiving [=============> ] 1/3\r (no-eol) (esc)
1067 1067 archiving [===========================> ] 2/3\r (no-eol) (esc)
1068 1068 archiving [==========================================>] 3/3\r (no-eol) (esc)
1069 1069 \r (no-eol) (esc)
1070 1070 \r (no-eol) (esc)
1071 1071 archiving (sub1) [ ] 0/1\r (no-eol) (esc)
1072 1072 archiving (sub1) [===================================>] 1/1\r (no-eol) (esc)
1073 1073 \r (no-eol) (esc)
1074 1074 \r (no-eol) (esc)
1075 1075 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (esc)
1076 1076 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (esc)
1077 1077 \r (no-eol) (esc)
1078 1078 \r (no-eol) (esc)
1079 1079 archiving [ ] 0/8\r (no-eol) (esc)
1080 1080 archiving [====> ] 1/8\r (no-eol) (esc)
1081 1081 archiving [=========> ] 2/8\r (no-eol) (esc)
1082 1082 archiving [===============> ] 3/8\r (no-eol) (esc)
1083 1083 archiving [====================> ] 4/8\r (no-eol) (esc)
1084 1084 archiving [=========================> ] 5/8\r (no-eol) (esc)
1085 1085 archiving [===============================> ] 6/8\r (no-eol) (esc)
1086 1086 archiving [====================================> ] 7/8\r (no-eol) (esc)
1087 1087 archiving [==========================================>] 8/8\r (no-eol) (esc)
1088 1088 \r (no-eol) (esc)
1089 1089 \r (no-eol) (esc)
1090 1090 archiving (sub1) [ ] 0/1\r (no-eol) (esc)
1091 1091 archiving (sub1) [===================================>] 1/1\r (no-eol) (esc)
1092 1092 \r (no-eol) (esc)
1093 1093 \r (no-eol) (esc)
1094 1094 archiving (sub1/sub2) [ ] 0/3\r (no-eol) (esc)
1095 1095 archiving (sub1/sub2) [=========> ] 1/3\r (no-eol) (esc)
1096 1096 archiving (sub1/sub2) [===================> ] 2/3\r (no-eol) (esc)
1097 1097 archiving (sub1/sub2) [==============================>] 3/3\r (no-eol) (esc)
1098 1098 \r (no-eol) (esc)
1099 1099 \r (no-eol) (esc)
1100 1100 archiving (sub3) [ ] 0/1\r (no-eol) (esc)
1101 1101 archiving (sub3) [===================================>] 1/1\r (no-eol) (esc)
1102 1102 \r (no-eol) (esc)
1103 1103 diff -Nru cloned.*/.hglf/b.dat cloned.*/.hglf/b.dat (glob)
1104 1104 --- cloned.*/.hglf/b.dat * (glob)
1105 1105 +++ cloned.*/.hglf/b.dat * (glob)
1106 1106 @@ -*,0 +1* @@ (glob)
1107 1107 +da39a3ee5e6b4b0d3255bfef95601890afd80709
1108 1108 diff -Nru cloned.*/.hglf/foo/bar/large.dat cloned.*/.hglf/foo/bar/large.dat (glob)
1109 1109 --- cloned.*/.hglf/foo/bar/large.dat * (glob)
1110 1110 +++ cloned.*/.hglf/foo/bar/large.dat * (glob)
1111 1111 @@ -*,0 +1* @@ (glob)
1112 1112 +2f6933b5ee0f5fdd823d9717d8729f3c2523811b
1113 1113 diff -Nru cloned.*/.hglf/large.bin cloned.*/.hglf/large.bin (glob)
1114 1114 --- cloned.*/.hglf/large.bin * (glob)
1115 1115 +++ cloned.*/.hglf/large.bin * (glob)
1116 1116 @@ -*,0 +1* @@ (glob)
1117 1117 +7f7097b041ccf68cc5561e9600da4655d21c6d18
1118 1118 diff -Nru cloned.*/.hgsub cloned.*/.hgsub (glob)
1119 1119 --- cloned.*/.hgsub * (glob)
1120 1120 +++ cloned.*/.hgsub * (glob)
1121 1121 @@ -1* +1,2 @@ (glob)
1122 1122 sub1 = ../sub1
1123 1123 +sub3 = sub3
1124 1124 diff -Nru cloned.*/.hgsubstate cloned.*/.hgsubstate (glob)
1125 1125 --- cloned.*/.hgsubstate * (glob)
1126 1126 +++ cloned.*/.hgsubstate * (glob)
1127 1127 @@ -1* +1,2 @@ (glob)
1128 1128 -fc3b4ce2696f7741438c79207583768f2ce6b0dd sub1
1129 1129 +7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
1130 1130 +b1a26de6f2a045a9f079323693614ee322f1ff7e sub3
1131 1131 diff -Nru cloned.*/foo/bar/def cloned.*/foo/bar/def (glob)
1132 1132 --- cloned.*/foo/bar/def * (glob)
1133 1133 +++ cloned.*/foo/bar/def * (glob)
1134 1134 @@ -*,0 +1* @@ (glob)
1135 1135 +changed
1136 1136 diff -Nru cloned.*/main cloned.*/main (glob)
1137 1137 --- cloned.*/main * (glob)
1138 1138 +++ cloned.*/main * (glob)
1139 1139 @@ -1* +1* @@ (glob)
1140 1140 -main
1141 1141 +foo
1142 1142 diff -Nru cloned.*/sub1/.hgsubstate cloned.*/sub1/.hgsubstate (glob)
1143 1143 --- cloned.*/sub1/.hgsubstate * (glob)
1144 1144 +++ cloned.*/sub1/.hgsubstate * (glob)
1145 1145 @@ -1* +1* @@ (glob)
1146 1146 -c57a0840e3badd667ef3c3ef65471609acb2ba3c sub2
1147 1147 +c77908c81ccea3794a896c79e98b0e004aee2e9e sub2
1148 1148 diff -Nru cloned.*/sub1/sub2/folder/test.txt cloned.*/sub1/sub2/folder/test.txt (glob)
1149 1149 --- cloned.*/sub1/sub2/folder/test.txt * (glob)
1150 1150 +++ cloned.*/sub1/sub2/folder/test.txt * (glob)
1151 1151 @@ -*,0 +1* @@ (glob)
1152 1152 +subfolder
1153 1153 diff -Nru cloned.*/sub1/sub2/sub2 cloned.*/sub1/sub2/sub2 (glob)
1154 1154 --- cloned.*/sub1/sub2/sub2 * (glob)
1155 1155 +++ cloned.*/sub1/sub2/sub2 * (glob)
1156 1156 @@ -1* +1* @@ (glob)
1157 1157 -sub2
1158 1158 +modified
1159 1159 diff -Nru cloned.*/sub3/a.txt cloned.*/sub3/a.txt (glob)
1160 1160 --- cloned.*/sub3/a.txt * (glob)
1161 1161 +++ cloned.*/sub3/a.txt * (glob)
1162 1162 @@ -*,0 +1* @@ (glob)
1163 1163 +xyz
1164 1164 [1]
1165 1165
1166 1166 $ echo mod > sub1/sub2/sub2
1167 1167 $ hg --config extensions.extdiff= pdiff -S
1168 1168 \r (no-eol) (esc)
1169 1169 archiving (sub1) [ <=> ] 0\r (no-eol) (esc)
1170 1170 \r (no-eol) (esc)
1171 1171 \r (no-eol) (esc)
1172 1172 archiving (sub1/sub2) [ ] 0/1\r (no-eol) (esc)
1173 1173 archiving (sub1/sub2) [==============================>] 1/1\r (no-eol) (esc)
1174 1174 \r (no-eol) (esc)
1175 1175 --- */cloned.*/sub1/sub2/sub2 * (glob)
1176 1176 +++ */cloned/sub1/sub2/sub2 * (glob)
1177 1177 @@ -1* +1* @@ (glob)
1178 1178 -modified
1179 1179 +mod
1180 1180 [1]
1181 1181
1182 1182 $ cd ..
@@ -1,219 +1,219 b''
1 1 Preparing the subrepository 'sub'
2 2
3 3 $ hg init sub
4 4 $ echo sub > sub/sub
5 5 $ hg add -R sub
6 6 adding sub/sub
7 7 $ hg commit -R sub -m "sub import"
8 8
9 9 Preparing the 'main' repo which depends on the subrepo 'sub'
10 10
11 11 $ hg init main
12 12 $ echo main > main/main
13 13 $ echo "sub = ../sub" > main/.hgsub
14 14 $ hg clone sub main/sub
15 15 updating to branch default
16 16 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
17 17 $ hg add -R main
18 18 adding main/.hgsub
19 19 adding main/main
20 20 $ hg commit -R main -m "main import"
21 21
22 22 Cleaning both repositories, just as a clone -U
23 23
24 24 $ hg up -C -R sub null
25 25 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
26 26 $ hg up -C -R main null
27 27 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
28 28 $ rm -rf main/sub
29 29
30 30 hide outer repo
31 31 $ hg init
32 32
33 33 Serving them both using hgweb
34 34
35 35 $ printf '[paths]\n/main = main\nsub = sub\n' > webdir.conf
36 36 $ hg serve --webdir-conf webdir.conf -a localhost -p $HGPORT \
37 37 > -A /dev/null -E /dev/null --pid-file hg.pid -d
38 38 $ cat hg.pid >> $DAEMON_PIDS
39 39
40 40 Clone main from hgweb
41 41
42 42 $ hg clone "http://user:pass@localhost:$HGPORT/main" cloned
43 43 requesting all changes
44 44 adding changesets
45 45 adding manifests
46 46 adding file changes
47 47 added 1 changesets with 3 changes to 3 files
48 48 new changesets fdfeeb3e979e
49 49 updating to branch default
50 50 cloning subrepo sub from http://user@localhost:$HGPORT/sub
51 51 requesting all changes
52 52 adding changesets
53 53 adding manifests
54 54 adding file changes
55 55 added 1 changesets with 1 changes to 1 files
56 56 new changesets 863c1745b441
57 57 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 58
59 59 Ensure that subrepos pay attention to default:pushurl
60 60
61 61 $ cat > cloned/.hg/hgrc << EOF
62 62 > [paths]
63 63 > default:pushurl = http://user:pass@localhost:$HGPORT/main
64 64 > EOF
65 65
66 66 $ hg -R cloned out -S --config paths.default=bogus://invalid
67 67 comparing with http://user:***@localhost:$HGPORT/main
68 68 searching for changes
69 69 no changes found
70 70 comparing with http://user:***@localhost:$HGPORT/sub
71 71 searching for changes
72 72 no changes found
73 73 [1]
74 74
75 75 TODO: Figure out why, if the password is left out of the default:pushurl URL,
76 76 this says "no changes made to subrepo sub since last push". It looks like from
77 77 the original clone command above, the password is getting stripped off, not
78 78 just masked out, and that would make the hashed URL different.
79 79
80 80 $ hg -R cloned push --config paths.default=bogus://invalid
81 81 pushing to http://user:***@localhost:$HGPORT/main
82 82 pushing subrepo sub to http://user:***@localhost:$HGPORT/sub
83 83 searching for changes
84 84 no changes found
85 85 searching for changes
86 86 no changes found
87 87 abort: HTTP Error 403: ssl required
88 [255]
88 [100]
89 89
90 90 Checking cloned repo ids
91 91
92 92 $ hg id -R cloned
93 93 fdfeeb3e979e tip
94 94 $ hg id -R cloned/sub
95 95 863c1745b441 tip
96 96
97 97 subrepo debug for 'main' clone
98 98
99 99 $ hg debugsub -R cloned
100 100 path sub
101 101 source ../sub
102 102 revision 863c1745b441bd97a8c4a096e87793073f4fb215
103 103
104 104 Test sharing with a remote URL reference
105 105
106 106 $ hg init absolute_subrepo
107 107 $ cd absolute_subrepo
108 108 $ echo foo > foo.txt
109 109 $ hg ci -Am 'initial commit'
110 110 adding foo.txt
111 111 $ echo "sub = http://localhost:$HGPORT/sub" > .hgsub
112 112 $ hg ci -Am 'add absolute subrepo'
113 113 adding .hgsub
114 114 $ cd ..
115 115
116 116 Clone pooling works for local clones with a remote subrepo reference. The
117 117 subrepo is cloned to the pool and shared from there, so that all clones will
118 118 share the same subrepo.
119 119
120 120 $ hg --config extensions.share= --config share.pool=$TESTTMP/pool \
121 121 > clone absolute_subrepo cloned_from_abs
122 122 (sharing from new pooled repository 8d6a2f1e993b34b6557de0042cfe825ae12a8dae)
123 123 requesting all changes
124 124 adding changesets
125 125 adding manifests
126 126 adding file changes
127 127 added 2 changesets with 3 changes to 3 files
128 128 new changesets 8d6a2f1e993b:* (glob)
129 129 searching for changes
130 130 no changes found
131 131 updating working directory
132 132 cloning subrepo sub from http://localhost:$HGPORT/sub
133 133 (sharing from new pooled repository 863c1745b441bd97a8c4a096e87793073f4fb215)
134 134 requesting all changes
135 135 adding changesets
136 136 adding manifests
137 137 adding file changes
138 138 added 1 changesets with 1 changes to 1 files
139 139 new changesets 863c1745b441
140 140 searching for changes
141 141 no changes found
142 142 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 143
144 144 Vanilla sharing with a subrepo remote path reference will clone the subrepo.
145 145 Each share of these top level repos will end up with independent subrepo copies
146 146 (potentially leaving the shared parent with dangling cset references).
147 147
148 148 $ hg --config extensions.share= share absolute_subrepo shared_from_abs
149 149 updating working directory
150 150 cloning subrepo sub from http://localhost:$HGPORT/sub
151 151 requesting all changes
152 152 adding changesets
153 153 adding manifests
154 154 adding file changes
155 155 added 1 changesets with 1 changes to 1 files
156 156 new changesets 863c1745b441
157 157 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 158
159 159 $ hg --config extensions.share= share -U absolute_subrepo shared_from_abs2
160 160 $ hg -R shared_from_abs2 update -r tip
161 161 cloning subrepo sub from http://localhost:$HGPORT/sub
162 162 requesting all changes
163 163 adding changesets
164 164 adding manifests
165 165 adding file changes
166 166 added 1 changesets with 1 changes to 1 files
167 167 new changesets 863c1745b441
168 168 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
169 169
170 170 A parent repo without its subrepo available locally can be shared if the
171 171 subrepo is referenced by absolute path.
172 172
173 173 $ hg clone -U absolute_subrepo cloned_null_from_abs
174 174 $ hg --config extensions.share= share cloned_null_from_abs shared_from_null_abs
175 175 updating working directory
176 176 cloning subrepo sub from http://localhost:$HGPORT/sub
177 177 requesting all changes
178 178 adding changesets
179 179 adding manifests
180 180 adding file changes
181 181 added 1 changesets with 1 changes to 1 files
182 182 new changesets 863c1745b441
183 183 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
184 184
185 185 $ killdaemons.py
186 186
187 187 subrepo paths with ssh urls
188 188
189 189 $ hg clone -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/cloned sshclone
190 190 requesting all changes
191 191 adding changesets
192 192 adding manifests
193 193 adding file changes
194 194 added 1 changesets with 3 changes to 3 files
195 195 new changesets fdfeeb3e979e
196 196 updating to branch default
197 197 cloning subrepo sub from ssh://user@dummy/sub
198 198 requesting all changes
199 199 adding changesets
200 200 adding manifests
201 201 adding file changes
202 202 added 1 changesets with 1 changes to 1 files
203 203 new changesets 863c1745b441
204 204 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
205 205
206 206 $ hg -R sshclone push -e "\"$PYTHON\" \"$TESTDIR/dummyssh\"" ssh://user@dummy/`pwd`/cloned
207 207 pushing to ssh://user@dummy/$TESTTMP/cloned
208 208 pushing subrepo sub to ssh://user@dummy/$TESTTMP/sub
209 209 searching for changes
210 210 no changes found
211 211 searching for changes
212 212 no changes found
213 213 [1]
214 214
215 215 $ cat dummylog
216 216 Got arguments 1:user@dummy 2:hg -R cloned serve --stdio
217 217 Got arguments 1:user@dummy 2:hg -R sub serve --stdio
218 218 Got arguments 1:user@dummy 2:hg -R $TESTTMP/cloned serve --stdio
219 219 Got arguments 1:user@dummy 2:hg -R $TESTTMP/sub serve --stdio
General Comments 0
You need to be logged in to leave comments. Login now