changeset 5978:7939c71f3132

sshrepo: be more careful while reading data This should avoid some tracebacks when the server sends some garbage.
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Sun, 03 Feb 2008 21:03:46 -0200
parents e82dd2dd6276
children b4858eb4b58f
files mercurial/sshrepo.py tests/test-ssh tests/test-ssh.out
diffstat 3 files changed, 56 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/sshrepo.py	Sun Feb 03 21:03:46 2008 -0200
+++ b/mercurial/sshrepo.py	Sun Feb 03 21:03:46 2008 -0200
@@ -115,14 +115,25 @@
         return self.pipei
 
     def call(self, cmd, **args):
-        r = self.do_cmd(cmd, **args)
-        l = r.readline()
+        self.do_cmd(cmd, **args)
+        return self._recv()
+
+    def _recv(self):
+        l = self.pipei.readline()
         self.readerr()
         try:
             l = int(l)
         except:
             self.raise_(util.UnexpectedOutput(_("unexpected response:"), l))
-        return r.read(l)
+        return self.pipei.read(l)
+
+    def _send(self, data, flush=False):
+        self.pipeo.write("%d\n" % len(data))
+        if data:
+            self.pipeo.write(data)
+        if flush:
+            self.pipeo.flush()
+        self.readerr()
 
     def lock(self):
         self.call("lock")
@@ -183,25 +194,22 @@
 
         while 1:
             d = cg.read(4096)
-            if not d: break
-            self.pipeo.write(str(len(d)) + '\n')
-            self.pipeo.write(d)
-            self.readerr()
+            if not d:
+                break
+            self._send(d)
 
-        self.pipeo.write('0\n')
-        self.pipeo.flush()
+        self._send("", flush=True)
 
-        self.readerr()
-        l = int(self.pipei.readline())
-        r = self.pipei.read(l)
+        r = self._recv()
         if r:
             # remote may send "unsynced changes"
             self.raise_(hg.RepoError(_("push failed: %s") % r))
 
-        self.readerr()
-        l = int(self.pipei.readline())
-        r = self.pipei.read(l)
-        return int(r)
+        r = self._recv()
+        try:
+            return int(r)
+        except:
+            self.raise_(util.UnexpectedOutput(_("unexpected response:"), r))
 
     def addchangegroup(self, cg, source, url):
         d = self.call("addchangegroup")
@@ -209,18 +217,21 @@
             self.raise_(repo.RepoError(_("push refused: %s") % d))
         while 1:
             d = cg.read(4096)
-            if not d: break
+            if not d:
+                break
             self.pipeo.write(d)
             self.readerr()
 
         self.pipeo.flush()
 
         self.readerr()
-        l = int(self.pipei.readline())
-        r = self.pipei.read(l)
+        r = self._recv()
         if not r:
             return 1
-        return int(r)
+        try:
+            return int(r)
+        except:
+            self.raise_(util.UnexpectedOutput(_("unexpected response:"), r))
 
     def stream_out(self):
         return self.do_cmd('stream_out')
--- a/tests/test-ssh	Sun Feb 03 21:03:46 2008 -0200
+++ b/tests/test-ssh	Sun Feb 03 21:03:46 2008 -0200
@@ -27,6 +27,11 @@
 sys.exit(bool(r))
 EOF
 
+cat <<EOF > badhook
+import sys
+sys.stdout.write("KABOOM")
+EOF
+
 echo "# creating 'remote'"
 hg init remote
 cd remote
@@ -91,13 +96,16 @@
 
 echo z > z
 hg ci -A -m z -d '1000001 0' z
+# a bad, evil hook that prints to stdout
+echo 'changegroup.stdout = python ../badhook' >> .hg/hgrc
 
 cd ../local
 echo r > r
 hg ci -A -m z -d '1000002 0' r
 
-echo "# push should succeed"
+echo "# push should succeed even though it has an unexpected response"
 hg push
+hg -R ../remote heads
 
 cd ..
 cat dummylog
--- a/tests/test-ssh.out	Sun Feb 03 21:03:46 2008 -0200
+++ b/tests/test-ssh.out	Sun Feb 03 21:03:46 2008 -0200
@@ -70,7 +70,7 @@
 checking files
 2 files, 2 changesets, 3 total revisions
 bleah
-# push should succeed
+# push should succeed even though it has an unexpected response
 pushing to ssh://user@dummy/remote
 searching for changes
 note: unsynced remote changes!
@@ -78,6 +78,21 @@
 remote: adding manifests
 remote: adding file changes
 remote: added 1 changesets with 1 changes to 1 files
+abort: unexpected response:
+'KABOOM1\n'
+changeset:   3:ac7448082955
+tag:         tip
+parent:      1:572896fe480d
+user:        test
+date:        Mon Jan 12 13:46:42 1970 +0000
+summary:     z
+
+changeset:   2:187c6caa0d1e
+parent:      0:e34318c26897
+user:        test
+date:        Mon Jan 12 13:46:41 1970 +0000
+summary:     z
+
 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
 Got arguments 1:user@dummy 2:hg -R remote serve --stdio