Merge lp:~cjwatson/launchpad/git-ref-remote-lp-non-production into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18814
Proposed branch: lp:~cjwatson/launchpad/git-ref-remote-lp-non-production
Merge into: lp:launchpad
Diff against target: 121 lines (+82/-6)
2 files modified
lib/lp/code/model/gitref.py (+37/-6)
lib/lp/code/model/tests/test_gitref.py (+45/-0)
To merge this branch: bzr merge lp:~cjwatson/launchpad/git-ref-remote-lp-non-production
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+357827@code.launchpad.net

Commit message

Allow fetching blobs from repositories hosted on git.launchpad.net from non-production Launchpad instances.

Description of the change

This makes life easier when doing e.g. snap build QA on dogfood.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/code/model/gitref.py'
--- lib/lp/code/model/gitref.py 2018-10-22 12:43:55 +0000
+++ lib/lp/code/model/gitref.py 2018-10-25 15:18:55 +0000
@@ -702,6 +702,25 @@
702 return response.content702 return response.content
703703
704704
705def _fetch_blob_from_launchpad(repository_url, ref_path, filename):
706 repo_path = urlsplit(repository_url).path.strip("/")
707 try:
708 response = urlfetch(
709 "https://git.launchpad.net/%s/plain/%s" % (
710 repo_path, quote(filename)),
711 params={"h": ref_path})
712 except requests.RequestException as e:
713 if (e.response is not None and
714 e.response.status_code == requests.codes.NOT_FOUND):
715 raise GitRepositoryBlobNotFound(
716 repository_url, filename, rev=ref_path)
717 else:
718 raise GitRepositoryScanFault(
719 "Failed to get file from Git repository at %s: %s" %
720 (repository_url, str(e)))
721 return response.content
722
723
705@implementer(IGitRef)724@implementer(IGitRef)
706@provider(IGitRefRemoteSet)725@provider(IGitRefRemoteSet)
707class GitRefRemote(GitRefMixin):726class GitRefRemote(GitRefMixin):
@@ -800,17 +819,29 @@
800 # dispatch a build job or a code import or something like that to do819 # dispatch a build job or a code import or something like that to do
801 # so. For now, we just special-case some providers where we know820 # so. For now, we just special-case some providers where we know
802 # how to fetch a blob on its own.821 # how to fetch a blob on its own.
803 repository = getUtility(IGitLookup).getByUrl(self.repository_url)
804 if repository is not None:
805 # This is one of our own repositories. Doing this by URL seems
806 # gratuitously complex, but apparently we already have some
807 # examples of this on production.
808 return repository.getBlob(filename, rev=self.path)
809 url = urlsplit(self.repository_url)822 url = urlsplit(self.repository_url)
810 if (url.hostname == "github.com" and823 if (url.hostname == "github.com" and
811 len(url.path.strip("/").split("/")) == 2):824 len(url.path.strip("/").split("/")) == 2):
812 return _fetch_blob_from_github(825 return _fetch_blob_from_github(
813 self.repository_url, self.path, filename)826 self.repository_url, self.path, filename)
827 if (url.hostname == "git.launchpad.net" and
828 config.vhost.mainsite.hostname != "launchpad.net"):
829 # Even if this isn't launchpad.net, we can still retrieve files
830 # from git.launchpad.net by URL, as a QA convenience. (We check
831 # config.vhost.mainsite.hostname rather than
832 # config.codehosting.git_*_root because the dogfood instance
833 # points git_*_root to git.launchpad.net but doesn't share the
834 # production database.)
835 return _fetch_blob_from_launchpad(
836 self.repository_url, self.path, filename)
837 codehosting_host = urlsplit(config.codehosting.git_anon_root).hostname
838 if url.hostname == codehosting_host:
839 repository = getUtility(IGitLookup).getByUrl(self.repository_url)
840 if repository is not None:
841 # This is one of our own repositories. Doing this by URL
842 # seems gratuitously complex, but apparently we already have
843 # some examples of this on production.
844 return repository.getBlob(filename, rev=self.path)
814 raise GitRepositoryBlobUnsupportedRemote(self.repository_url)845 raise GitRepositoryBlobUnsupportedRemote(self.repository_url)
815846
816 @property847 @property
817848
=== modified file 'lib/lp/code/model/tests/test_gitref.py'
--- lib/lp/code/model/tests/test_gitref.py 2018-10-16 15:29:37 +0000
+++ lib/lp/code/model/tests/test_gitref.py 2018-10-25 15:18:55 +0000
@@ -344,6 +344,51 @@
344 self.assertEqual(expected_calls, hosting_fixture.getBlob.calls)344 self.assertEqual(expected_calls, hosting_fixture.getBlob.calls)
345345
346 @responses.activate346 @responses.activate
347 def test_remote_launchpad_production_branch(self):
348 ref = self.factory.makeGitRefRemote(
349 repository_url="https://git.launchpad.net/~owner/+git/name",
350 path="refs/heads/path")
351 responses.add(
352 "GET",
353 "https://git.launchpad.net/~owner/+git/name/plain/dir/file"
354 "?h=refs%2Fheads%2Fpath",
355 body=b"foo")
356 self.assertEqual(b"foo", ref.getBlob("dir/file"))
357
358 @responses.activate
359 def test_remote_launchpad_production_HEAD(self):
360 ref = self.factory.makeGitRefRemote(
361 repository_url="https://git.launchpad.net/~owner/+git/name",
362 path="HEAD")
363 responses.add(
364 "GET",
365 "https://git.launchpad.net/~owner/+git/name/plain/dir/file?h=HEAD",
366 body=b"foo")
367 self.assertEqual(b"foo", ref.getBlob("dir/file"))
368
369 @responses.activate
370 def test_remote_launchpad_production_404(self):
371 ref = self.factory.makeGitRefRemote(
372 repository_url="https://git.launchpad.net/~owner/+git/name",
373 path="HEAD")
374 responses.add(
375 "GET",
376 "https://git.launchpad.net/~owner/+git/name/plain/dir/file?h=HEAD",
377 status=404)
378 self.assertRaises(GitRepositoryBlobNotFound, ref.getBlob, "dir/file")
379
380 @responses.activate
381 def test_remote_launchpad_production_error(self):
382 ref = self.factory.makeGitRefRemote(
383 repository_url="https://git.launchpad.net/~owner/+git/name",
384 path="HEAD")
385 responses.add(
386 "GET",
387 "https://git.launchpad.net/~owner/+git/name/plain/dir/file?h=HEAD",
388 status=500)
389 self.assertRaises(GitRepositoryScanFault, ref.getBlob, "dir/file")
390
391 @responses.activate
347 def test_remote_github_branch(self):392 def test_remote_github_branch(self):
348 ref = self.factory.makeGitRefRemote(393 ref = self.factory.makeGitRefRemote(
349 repository_url="https://github.com/owner/name",394 repository_url="https://github.com/owner/name",