Switch to smart HTTP mode.

Gerrit actually only speaks smart http, but we were assuming
dumb HTTP (which is provided in OpenStack's configuration).

Change-Id: Id299f53a6be6fc1670edf1da4b3353115bf1e31e
Reviewed-on: https://review.openstack.org/13146
Reviewed-by: Clark Boylan <clark.boylan@gmail.com>
Reviewed-by: Monty Taylor <mordred@inaugust.com>
Approved: James E. Blair <corvus@inaugust.com>
Tested-by: Jenkins
diff --git a/tests/test_scheduler.py b/tests/test_scheduler.py
index cacf4a9..41848f6 100644
--- a/tests/test_scheduler.py
+++ b/tests/test_scheduler.py
@@ -580,11 +580,16 @@
         res = urlparse.urlparse(self.url)
         path = res.path
         project = '/'.join(path.split('/')[2:-2])
-        ret = ''
+        ret = '001e# service=git-upload-pack\n'
+        ret += ('000000a31270149696713ba7e06f1beb760f20d359c4abed HEAD\x00'
+                'multi_ack thin-pack side-band side-band-64k ofs-delta '
+                'shallow no-progress include-tag multi_ack_detailed no-done\n')
         path = os.path.join(UPSTREAM_ROOT, project)
         repo = git.Repo(path)
         for ref in repo.refs:
-            ret += ref.object.hexsha + '\t' + ref.path + '\n'
+            r = ref.object.hexsha + ' ' + ref.path + '\n'
+            ret += '%04x%s' % (len(r) + 4, r)
+        ret += '0000'
         return ret
 
 
diff --git a/zuul/trigger/gerrit.py b/zuul/trigger/gerrit.py
index 1c4b74c..5f0064e 100644
--- a/zuul/trigger/gerrit.py
+++ b/zuul/trigger/gerrit.py
@@ -117,12 +117,41 @@
                                   message, action)
 
     def _getInfoRefs(self, project):
-        url = "https://%s/p/%s/info/refs" % (self.server, project)
+        url = "https://%s/p/%s/info/refs?service=git-upload-pack" % (
+            self.server, project)
         data = urllib2.urlopen(url).read()
         ret = {}
-        for line in data.split('\n'):
-            if not line:
+        read_headers = False
+        read_advertisement = False
+        if data[4] != '#':
+            raise Exception("Gerrit repository does not support "
+                            "git-upload-pack")
+        i = 0
+        while i < len(data):
+            if len(data) - i < 4:
+                raise Exception("Invalid length in info/refs")
+            plen = int(data[i:i + 4], 16)
+            i += 4
+            # It's the length of the packet, including the 4 bytes of the
+            # length itself, unless it's null, in which case the length is
+            # not included.
+            if plen > 0:
+                plen -= 4
+            if len(data) - i < plen:
+                raise Exception("Invalid data in info/refs")
+            line = data[i:i + plen]
+            i += plen
+            if not read_headers:
+                if plen == 0:
+                    read_headers = True
                 continue
+            if not read_advertisement:
+                read_advertisement = True
+                continue
+            if plen == 0:
+                # The terminating null
+                continue
+            line = line.strip()
             revision, ref = line.split()
             ret[ref] = revision
         return ret