launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #28248
[Merge] ~cjwatson/turnip:dynamic-git-capability-advertisement into turnip:master
Colin Watson has proposed merging ~cjwatson/turnip:dynamic-git-capability-advertisement into turnip:master.
Commit message:
Dynamically generate git v2 capability advertisement
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/turnip/+git/turnip/+merge/417597
`turnip.pack.helpers.get_capabilities_advertisement` hardcoded our protocol 2 capability advertisement quite tightly, which caused tests to fail when upgrading to a newer version of git. Generate this dynamically instead based on git's own advertisement.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/turnip:dynamic-git-capability-advertisement into turnip:master.
diff --git a/turnip/pack/helpers.py b/turnip/pack/helpers.py
index 9cfcfcf..7ab61e4 100644
--- a/turnip/pack/helpers.py
+++ b/turnip/pack/helpers.py
@@ -1,4 +1,4 @@
-# Copyright 2015 Canonical Ltd. This software is licensed under the
+# Copyright 2015-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
from __future__ import (
@@ -9,13 +9,16 @@ from __future__ import (
from collections import OrderedDict
import enum
+from functools import lru_cache
import hashlib
import os.path
import re
+import shutil
import stat
import subprocess
import sys
from tempfile import (
+ mkdtemp,
mktemp,
NamedTemporaryFile,
)
@@ -248,6 +251,28 @@ def translate_xmlrpc_fault(code):
return result
+@lru_cache(maxsize=1)
+def _get_git_v2_capabilities_advertisement():
+ """Returns git's own v2 capability advertisement, parsed into packets."""
+ git_dir = mkdtemp(prefix="git-advertisement-")
+ try:
+ subprocess.check_call(
+ ["git", "init", git_dir], stdout=subprocess.DEVNULL)
+ env = dict(os.environ)
+ env["GIT_PROTOCOL"] = "version=2"
+ advertisement = subprocess.check_output(
+ ["git", "upload-pack", git_dir], input=b"", env=env)
+ finally:
+ shutil.rmtree(git_dir, ignore_errors=True)
+ packets = []
+ while advertisement:
+ packet, advertisement = decode_packet(advertisement)
+ if packet is None:
+ break
+ packets.append(packet)
+ return packets
+
+
def get_capabilities_advertisement(version=b'1'):
"""Returns the capability advertisement binary string to be sent to
clients for a given protocol version requested.
@@ -257,11 +282,10 @@ def get_capabilities_advertisement(version=b'1'):
if version != b'2':
return b""
turnip_version = six.ensure_binary(version_info.get("revision_id", '-1'))
- return (
- encode_packet(b"version 2\n") +
- encode_packet(b"agent=git/2.25.1@turnip/%s\n" % turnip_version) +
- encode_packet(b"ls-refs\n") +
- encode_packet(b"fetch=shallow\n") +
- encode_packet(b"server-option\n") +
- b'0000'
- )
+ advertisement = bytearray()
+ for packet in _get_git_v2_capabilities_advertisement():
+ if packet.startswith(b"agent="):
+ packet = b"%s@turnip/%s\n" % (packet.rstrip(b"\n"), turnip_version)
+ advertisement += encode_packet(packet)
+ advertisement += b"0000"
+ return bytes(advertisement)
diff --git a/turnip/pack/tests/test_helpers.py b/turnip/pack/tests/test_helpers.py
index 815497f..d652bf8 100644
--- a/turnip/pack/tests/test_helpers.py
+++ b/turnip/pack/tests/test_helpers.py
@@ -1,4 +1,4 @@
-# Copyright 2015 Canonical Ltd. This software is licensed under the
+# Copyright 2015-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
from __future__ import (
@@ -347,7 +347,8 @@ class TestCapabilityAdvertisement(TestCase):
turnip_capabilities = get_capabilities_advertisement(version=b'2')
version = six.ensure_binary(version_info["revision_id"])
- turnip_agent = encode_packet(b"agent=git/2.25.1@turnip/%s\n" % version)
+ turnip_agent = encode_packet(
+ b"agent=git/%s@turnip/%s\n" % (git_version_num, version))
self.assertEqual(
turnip_capabilities,
diff --git a/turnip/pack/tests/test_http.py b/turnip/pack/tests/test_http.py
index b1158d1..2b01f62 100644
--- a/turnip/pack/tests/test_http.py
+++ b/turnip/pack/tests/test_http.py
@@ -1,4 +1,4 @@
-# Copyright 2015 Canonical Ltd. This software is licensed under the
+# Copyright 2015-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
from __future__ import (
@@ -15,7 +15,6 @@ from unittest import mock
from fixtures import TempDir
from openid.consumer import consumer
from paste.auth.cookie import encode as encode_cookie
-import six
from testtools import TestCase
from testtools.deferredruntest import AsynchronousDeferredRunTest
from twisted.internet import (
@@ -34,13 +33,12 @@ from turnip.pack import (
helpers,
http,
)
-from turnip.pack.helpers import encode_packet
+from turnip.pack.helpers import get_capabilities_advertisement
from turnip.pack.http import (
get_protocol_version_from_request,
HTTPAuthLoginResource,
)
from turnip.pack.tests.fake_servers import FakeVirtInfoService
-from turnip.version_info import version_info
class LessDummyRequest(requesthelper.DummyRequest):
@@ -261,15 +259,9 @@ class TestSmartHTTPRefsResource(ErrorTestMixin, TestCase):
b'turnip-request-id': mock.ANY,
b'turnip-stateless-rpc': b'yes'})
- ver = six.ensure_binary(version_info["revision_id"])
- capabilities = (
- encode_packet(b'version 2\n') +
- encode_packet(b'agent=git/2.25.1@turnip/%s\n' % ver) +
- encode_packet(b'ls-refs\n') +
- encode_packet(b'fetch=shallow\n') +
- encode_packet(b'server-option\n') +
- b'0000'
- )
+ # Details tested separately; see
+ # turnip.pack.tests.test_helpers.TestCapabilityAdvertisement.
+ capabilities = get_capabilities_advertisement(version=b"2")
self.assertEqual(
capabilities +
b'001e# service=git-upload-pack\n'