diff --git a/mercurial/worker.py b/mercurial/worker.py --- a/mercurial/worker.py +++ b/mercurial/worker.py @@ -71,8 +71,12 @@ def __init__(self, wrapped): self._wrapped = wrapped - def __getattr__(self, attr): - return getattr(self._wrapped, attr) + # Do NOT implement readinto() by making it delegate to + # _wrapped.readline(), since that is unbuffered. The unpickler is fine + # with just read() and readline(), so we don't need to implement it. + + def readline(self): + return self._wrapped.readline() # issue multiple reads until size is fulfilled def read(self, size=-1): @@ -91,7 +95,7 @@ del view del buf[pos:] - return buf + return bytes(buf) else: diff --git a/tests/test-fix-pickle.t b/tests/test-fix-pickle.t new file mode 100644 --- /dev/null +++ b/tests/test-fix-pickle.t @@ -0,0 +1,45 @@ +A script that implements uppercasing all letters in a file. + + $ UPPERCASEPY="$TESTTMP/uppercase.py" + $ cat > $UPPERCASEPY < import sys + > from mercurial.utils.procutil import setbinary + > setbinary(sys.stdin) + > setbinary(sys.stdout) + > sys.stdout.write(sys.stdin.read().upper()) + > EOF + $ TESTLINES="foo\nbar\nbaz\n" + $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY + FOO + BAR + BAZ + +This file attempts to test our workarounds for pickle's lack of +support for short reads. + + $ cat >> $HGRCPATH < [extensions] + > fix = + > [fix] + > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY + > uppercase-whole-file:pattern=set:** + > EOF + + $ hg init repo + $ cd repo + +# Create a file that's large enough that it seems to not fit in +# pickle's buffer, making it use the code path that expects our +# _blockingreader's read() method to return bytes. + $ echo "some stuff" > file + $ for i in $($TESTDIR/seq.py 13); do + > cat file file > tmp + > mv -f tmp file + > done + $ hg commit -Am "add large file" + adding file + +Check that we don't get a crash + + $ hg fix -r . + saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-fix.hg (glob)