launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #21801
[Merge] lp:~cjwatson/launchpad/snap-set-git-path into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/snap-set-git-path into lp:launchpad.
Commit message:
Allow setting Snap.git_path directly on the webservice.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/snap-set-git-path/+merge/329360
This allows the backfill requested in https://github.com/canonical-websites/build.snapcraft.io/issues/917.
I thought about adding similar setters for the other components of the snap's source, but it got rather complex and less broadly-applicable, whereas changing the branch should be lightweight and easy.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/snap-set-git-path into lp:launchpad.
=== modified file 'lib/lp/code/model/gitref.py'
--- lib/lp/code/model/gitref.py 2017-05-22 11:27:17 +0000
+++ lib/lp/code/model/gitref.py 2017-08-22 12:01:09 +0000
@@ -592,7 +592,8 @@
"""See `GitRefDatabaseBackedMixin`."""
path = self.repository.default_branch
if path is None:
- raise NotFoundError("Repository '%s' has no default branch")
+ raise NotFoundError(
+ "Repository '%s' has no default branch" % self.repository)
ref = IStore(GitRef).get(GitRef, (self.repository_id, path))
if ref is None:
raise NotFoundError(
=== modified file 'lib/lp/snappy/interfaces/snap.py'
--- lib/lp/snappy/interfaces/snap.py 2017-04-24 13:38:04 +0000
+++ lib/lp/snappy/interfaces/snap.py 2017-08-22 12:01:09 +0000
@@ -7,6 +7,7 @@
__all__ = [
'BadSnapSearchContext',
+ 'BadSnapSource',
'CannotAuthorizeStoreUploads',
'CannotModifySnapProcessor',
'CannotRequestAutoBuilds',
@@ -185,6 +186,11 @@
@error_status(httplib.BAD_REQUEST)
+class BadSnapSource(Exception):
+ """The elements of the source for a snap package are inconsistent."""
+
+
+@error_status(httplib.BAD_REQUEST)
class SnapPrivacyMismatch(Exception):
"""Snap package privacy does not match its content."""
@@ -461,11 +467,19 @@
allow_fragment=False,
trailing_slash=False))
- git_path = exported(TextLine(
- title=_("Git branch path"), required=False, readonly=True,
+ git_path = TextLine(
+ title=_("Git branch path"), required=False, readonly=False,
description=_(
"The path of the Git branch containing a snap/snapcraft.yaml, "
- "snapcraft.yaml, or .snapcraft.yaml recipe at the top level.")))
+ "snapcraft.yaml, or .snapcraft.yaml recipe at the top level."))
+ _api_git_path = exported(
+ TextLine(
+ title=_("Git branch path"), required=False, readonly=False,
+ description=_(
+ "The path of the Git branch containing a snap/snapcraft.yaml, "
+ "snapcraft.yaml, or .snapcraft.yaml recipe at the top "
+ "level.")),
+ exported_as="git_path")
git_ref = exported(Reference(
IGitRef, title=_("Git branch"), required=False, readonly=False,
=== modified file 'lib/lp/snappy/model/snap.py'
--- lib/lp/snappy/model/snap.py 2017-06-29 12:02:11 +0000
+++ lib/lp/snappy/model/snap.py 2017-08-22 12:01:09 +0000
@@ -107,6 +107,7 @@
from lp.services.webhooks.model import WebhookTargetMixin
from lp.snappy.interfaces.snap import (
BadSnapSearchContext,
+ BadSnapSource,
CannotAuthorizeStoreUploads,
CannotModifySnapProcessor,
CannotRequestAutoBuilds,
@@ -241,6 +242,19 @@
return ["snap:build:0.1"]
@property
+ def _api_git_path(self):
+ return self.git_path
+
+ @_api_git_path.setter
+ def _api_git_path(self, value):
+ if self.git_repository is None and self.git_repository_url is None:
+ raise BadSnapSource(
+ "git_path may only be set on a Git-based snap.")
+ if value is None:
+ raise BadSnapSource("git_path may not be set to None.")
+ self.git_path = value
+
+ @property
def git_ref(self):
"""See `ISnap`."""
if self.git_repository is not None:
=== modified file 'lib/lp/snappy/tests/test_snap.py'
--- lib/lp/snappy/tests/test_snap.py 2017-04-24 13:38:04 +0000
+++ lib/lp/snappy/tests/test_snap.py 2017-08-22 12:01:09 +0000
@@ -22,6 +22,7 @@
from storm.exceptions import LostObjectError
from storm.locals import Store
from testtools.matchers import (
+ ContainsDict,
Equals,
MatchesSetwise,
MatchesStructure,
@@ -1361,6 +1362,53 @@
self.assertEqual(
"Test Person is not a member of Other Team.", response.body)
+ def test_cannot_set_git_path_for_bzr(self):
+ # Setting git_path on a Bazaar-based Snap fails.
+ snap = self.makeSnap(branch=self.factory.makeAnyBranch())
+ response = self.webservice.patch(
+ snap["self_link"], "application/json",
+ json.dumps({"git_path": "HEAD"}))
+ self.assertEqual(400, response.status)
+
+ def test_cannot_set_git_path_to_None(self):
+ # Setting git_path to None fails.
+ snap = self.makeSnap(git_ref=self.factory.makeGitRefs()[0])
+ response = self.webservice.patch(
+ snap["self_link"], "application/json",
+ json.dumps({"git_path": None}))
+ self.assertEqual(400, response.status)
+
+ def test_set_git_path(self):
+ # Setting git_path on a Git-based Snap works.
+ ref_master, ref_next = self.factory.makeGitRefs(
+ paths=[u"refs/heads/master", u"refs/heads/next"])
+ snap = self.makeSnap(git_ref=ref_master)
+ response = self.webservice.patch(
+ snap["self_link"], "application/json",
+ json.dumps({"git_path": ref_next.path}))
+ self.assertEqual(209, response.status)
+ self.assertThat(response.jsonBody(), ContainsDict({
+ "git_repository_link": Equals(snap["git_repository_link"]),
+ "git_path": Equals(ref_next.path),
+ }))
+
+ def test_set_git_path_external(self):
+ # Setting git_path on a Snap backed by an external Git repository
+ # works.
+ ref = self.factory.makeGitRefRemote()
+ repository_url = ref.repository_url
+ snap = self.factory.makeSnap(
+ registrant=self.person, owner=self.person, git_ref=ref)
+ snap_url = api_url(snap)
+ logout()
+ response = self.webservice.patch(
+ snap_url, "application/json", json.dumps({"git_path": "HEAD"}))
+ self.assertEqual(209, response.status)
+ self.assertThat(response.jsonBody(), ContainsDict({
+ "git_repository_url": Equals(repository_url),
+ "git_path": Equals("HEAD"),
+ }))
+
def test_getByName(self):
# lp.snaps.getByName returns a matching Snap.
snap = self.makeSnap()
Follow ups