← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/git-recipe-browser-listing into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/git-recipe-browser-listing into lp:launchpad with lp:~cjwatson/launchpad/recipe-name-policy as a prerequisite.

Commit message:
Add views to list existing Git recipes.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1453022 in Launchpad itself: "Please support daily builds via git"
  https://bugs.launchpad.net/launchpad/+bug/1453022

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/git-recipe-browser-listing/+merge/282321

Add views to list existing Git recipes.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/git-recipe-browser-listing into lp:launchpad.
=== modified file 'lib/lp/code/browser/configure.zcml'
--- lib/lp/code/browser/configure.zcml	2015-11-23 11:34:15 +0000
+++ lib/lp/code/browser/configure.zcml	2016-01-12 15:24:34 +0000
@@ -1,4 +1,4 @@
-<!-- Copyright 2009-2015 Canonical Ltd.  This software is licensed under the
+<!-- Copyright 2009-2016 Canonical Ltd.  This software is licensed under the
      GNU Affero General Public License version 3 (see the file LICENSE).
 -->
 
@@ -800,6 +800,9 @@
         <browser:page
             name="++repository-management"
             template="../templates/gitrepository-management.pt"/>
+        <browser:page
+            name="++repository-recipes"
+            template="../templates/gitrepository-recipes.pt"/>
     </browser:pages>
     <browser:page
         for="lp.code.interfaces.gitrepository.IGitRepository"
@@ -884,11 +887,14 @@
             name="++ref-commits"
             template="../templates/gitref-commits.pt"/>
         <browser:page
+            name="++ref-management"
+            template="../templates/gitref-management.pt"/>
+        <browser:page
             name="++ref-pending-merges"
             template="../templates/gitref-pending-merges.pt"/>
         <browser:page
-            name="++ref-management"
-            template="../templates/gitref-management.pt"/>
+            name="++ref-recipes"
+            template="../templates/gitref-recipes.pt"/>
     </browser:pages>
     <browser:page
         for="lp.code.interfaces.gitref.IGitRef"
@@ -1232,6 +1238,18 @@
             name="+recipes"
             template="../templates/sourcepackagerecipe-listing.pt"/>
         <browser:page
+            for="lp.code.interfaces.gitrepository.IGitRepository"
+            class="lp.code.browser.sourcepackagerecipelisting.BranchRecipeListingView"
+            permission="zope.Public"
+            name="+recipes"
+            template="../templates/sourcepackagerecipe-listing.pt"/>
+        <browser:page
+            for="lp.code.interfaces.gitref.IGitRef"
+            class="lp.code.browser.sourcepackagerecipelisting.BranchRecipeListingView"
+            permission="zope.Public"
+            name="+recipes"
+            template="../templates/sourcepackagerecipe-listing.pt"/>
+        <browser:page
             for="lp.registry.interfaces.product.IProduct"
             class="lp.code.browser.sourcepackagerecipelisting.ProductRecipeListingView"
             permission="zope.Public"

=== modified file 'lib/lp/code/browser/gitref.py'
--- lib/lp/code/browser/gitref.py	2015-11-30 03:03:14 +0000
+++ lib/lp/code/browser/gitref.py	2016-01-12 15:24:34 +0000
@@ -1,4 +1,4 @@
-# Copyright 2015 Canonical Ltd.  This software is licensed under the
+# Copyright 2015-2016 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Git reference views."""
@@ -35,6 +35,7 @@
 from lp.code.browser.branchmergeproposal import (
     latest_proposals_for_each_branch,
     )
+from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin
 from lp.code.errors import InvalidBranchMergeProposal
 from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal
 from lp.code.interfaces.codereviewvote import ICodeReviewVoteReference
@@ -49,18 +50,19 @@
     Link,
     )
 from lp.services.webapp.authorization import check_permission
+from lp.services.webapp.escaping import structured
 from lp.snappy.browser.hassnaps import (
     HasSnapsMenuMixin,
     HasSnapsViewMixin,
     )
 
 
-class GitRefContextMenu(ContextMenu, HasSnapsMenuMixin):
+class GitRefContextMenu(ContextMenu, HasRecipesMenuMixin, HasSnapsMenuMixin):
     """Context menu for Git references."""
 
     usedfor = IGitRef
     facet = 'branches'
-    links = ['create_snap', 'register_merge', 'source']
+    links = ['create_snap', 'register_merge', 'source', 'view_recipes']
 
     def source(self):
         """Return a link to the branch's browsing interface."""
@@ -144,6 +146,24 @@
     def dependent_landing_count_text(self):
         return self._getBranchCountText(len(self.dependent_landings))
 
+    @property
+    def recipes_link(self):
+        """A link to recipes for this reference."""
+        count = self.context.recipes.count()
+        if count == 0:
+            # Nothing to link to.
+            return 'No recipes using this branch.'
+        elif count == 1:
+            # Link to the single recipe.
+            return structured(
+                '<a href="%s">1 recipe</a> using this branch.',
+                canonical_url(self.context.recipes.one())).escapedtext
+        else:
+            # Link to a recipe listing.
+            return structured(
+                '<a href="+recipes">%s recipes</a> using this branch.',
+                count).escapedtext
+
 
 class GitRefRegisterMergeProposalSchema(Interface):
     """The schema to define the form for registering a new merge proposal."""

=== modified file 'lib/lp/code/browser/gitrepository.py'
--- lib/lp/code/browser/gitrepository.py	2015-10-07 16:14:42 +0000
+++ lib/lp/code/browser/gitrepository.py	2016-01-12 15:24:34 +0000
@@ -1,4 +1,4 @@
-# Copyright 2015 Canonical Ltd.  This software is licensed under the
+# Copyright 2015-2016 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Git repository views."""
@@ -52,6 +52,7 @@
 from lp.app.vocabularies import InformationTypeVocabulary
 from lp.app.widgets.itemswidgets import LaunchpadRadioWidgetWithDescription
 from lp.code.browser.branch import CodeEditOwnerMixin
+from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin
 from lp.code.browser.widgets.gitrepositorytarget import (
     GitRepositoryTargetDisplayWidget,
     GitRepositoryTargetWidget,
@@ -203,12 +204,14 @@
         return Link("+delete", text, icon="trash-icon")
 
 
-class GitRepositoryContextMenu(ContextMenu):
+class GitRepositoryContextMenu(ContextMenu, HasRecipesMenuMixin):
     """Context menu for `IGitRepository`."""
 
     usedfor = IGitRepository
     facet = "branches"
-    links = ["add_subscriber", "source", "subscription", "visibility"]
+    links = [
+        "add_subscriber", "source", "subscription",
+        "view_recipes", "visibility"]
 
     @enabled_with_permission("launchpad.AnyPerson")
     def subscription(self):
@@ -291,6 +294,24 @@
         """All branches in this repository, sorted for display."""
         return GitRefBatchNavigator(self, self.context)
 
+    @property
+    def recipes_link(self):
+        """A link to recipes for this repository."""
+        count = self.context.recipes.count()
+        if count == 0:
+            # Nothing to link to.
+            return 'No recipes using this repository.'
+        elif count == 1:
+            # Link to the single recipe.
+            return structured(
+                '<a href="%s">1 recipe</a> using this repository.',
+                canonical_url(self.context.recipes.one())).escapedtext
+        else:
+            # Link to a recipe listing.
+            return structured(
+                '<a href="+recipes">%s recipes</a> using this repository.',
+                count).escapedtext
+
 
 class GitRepositoryEditFormView(LaunchpadEditFormView):
     """Base class for forms that edit a Git repository."""

=== modified file 'lib/lp/code/browser/sourcepackagerecipelisting.py'
--- lib/lp/code/browser/sourcepackagerecipelisting.py	2015-10-05 13:36:06 +0000
+++ lib/lp/code/browser/sourcepackagerecipelisting.py	2016-01-12 15:24:34 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2015 Canonical Ltd.  This software is licensed under the
+# Copyright 2010-2016 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Base class view for sourcepackagerecipe listings."""
@@ -14,6 +14,7 @@
 
 
 from lp.code.browser.decorations import DecoratedBranch
+from lp.code.interfaces.branch import IBranch
 from lp.services.feeds.browser import FeedsMixin
 from lp.services.webapp import (
     LaunchpadView,
@@ -42,8 +43,8 @@
 
     @property
     def page_title(self):
-        return 'Source Package Recipes for %(displayname)s' % {
-            'displayname': self.context.displayname}
+        return 'Source Package Recipes for %(display_name)s' % {
+            'display_name': self.context.display_name}
 
 
 class BranchRecipeListingView(RecipeListingView):
@@ -54,7 +55,8 @@
         super(BranchRecipeListingView, self).initialize()
         # Replace our context with a decorated branch, if it is not already
         # decorated.
-        if not isinstance(self.context, DecoratedBranch):
+        if (IBranch.providedBy(self.context) and
+                not isinstance(self.context, DecoratedBranch)):
             self.context = DecoratedBranch(self.context)
 
 

=== modified file 'lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt'
--- lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt	2011-06-29 16:49:05 +0000
+++ lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt	2016-01-12 15:24:34 +0000
@@ -52,18 +52,84 @@
     >>> print nopriv_browser.url
     http://code.launchpad.dev/%7Eperson-name.../product-name.../branch.../+recipes
 
-The "Base branch" column should not be shown.
-
-    >>> print_recipe_listing_head(nopriv_browser)
-    Name
-    Owner
-    Registered
-
-The branch page should have a list of all the recipes the branch is a
-base_branch for.
-
-    >>> print_recipe_listing_contents(nopriv_browser)
-    spr-name... Person-name...
+The "Base Source" column should not be shown.
+
+    >>> print_recipe_listing_head(nopriv_browser)
+    Name
+    Owner
+    Registered
+
+The recipe listing page should have a list of all the recipes the branch is
+a base for.
+
+    >>> print_recipe_listing_contents(nopriv_browser)
+    spr-name... Person-name...
+    spr-name... Person-name...
+    spr-name... Person-name...
+
+
+Git Recipe Listings
+===================
+
+Create a new sample repository, some branches in it, and some source package
+recipes to go along with them.
+
+    >>> login('foo.bar@xxxxxxxxxxxxx')
+    >>> repository = factory.makeGitRepository()
+    >>> ref1, ref2, ref3 = factory.makeGitRefs(
+    ...     repository=repository,
+    ...     paths=[u"refs/heads/a", u"refs/heads/b", u"refs/heads/c"])
+    >>> recipe1a = factory.makeSourcePackageRecipe(branches=[ref1])
+    >>> recipe1b = factory.makeSourcePackageRecipe(branches=[ref1])
+    >>> recipe2 = factory.makeSourcePackageRecipe(branches=[ref2])
+    >>> recipe3 = factory.makeSourcePackageRecipe(branches=[ref3])
+
+Keep these urls, including the target url.  We'll use these later.
+
+    >>> repository_url = canonical_url(repository)
+    >>> ref1_url = canonical_url(ref1)
+    >>> target_url = canonical_url(repository.target)
+
+    >>> logout()
+
+Since there are 4 recipes associated with this repository now, the link
+should now read "4 recipes."  Let's click through.
+
+    >>> nopriv_browser.open(repository_url)
+    >>> nopriv_browser.getLink('4 recipes').click()
+    >>> print nopriv_browser.url
+    http://code.launchpad.dev/%7Eperson-name.../product-name.../+git/gitrepository.../+recipes
+
+The "Base Source" column should not be shown.
+
+    >>> print_recipe_listing_head(nopriv_browser)
+    Name
+    Owner
+    Registered
+
+The recipe listing page should have a list of all the recipes the repository
+is a base for.
+
+    >>> print_recipe_listing_contents(nopriv_browser)
+    spr-name... Person-name...
+    spr-name... Person-name...
+    spr-name... Person-name...
+    spr-name... Person-name...
+
+If we start from one of the branches instead, then only two recipes are
+listed.
+
+    >>> nopriv_browser.open(ref1_url)
+    >>> nopriv_browser.getLink('2 recipes').click()
+    >>> print nopriv_browser.url
+    http://code.launchpad.dev/%7Eperson-name.../product-name.../+git/gitrepository.../+ref/a/+recipes
+
+    >>> print_recipe_listing_head(nopriv_browser)
+    Name
+    Owner
+    Registered
+
+    >>> print_recipe_listing_contents(nopriv_browser)
     spr-name... Person-name...
     spr-name... Person-name...
 
@@ -81,7 +147,7 @@
     >>> print_recipe_listing_head(nopriv_browser)
     Name
     Owner
-    Base Branch
+    Base Source
     Registered
 
 The listings should now show all recipes whose base branch is a branch from
@@ -92,6 +158,25 @@
     spr-name... Person-name... lp://dev/... ...
     spr-name... Person-name... lp://dev/... ...
 
+The same thing works for the target of the former Git repository test.
+
+    >>> nopriv_browser.open(target_url)
+    >>> nopriv_browser.getLink('View source package recipes').click()
+    >>> print nopriv_browser.url
+    http://code.launchpad.dev/product-name.../+recipes
+
+    >>> print_recipe_listing_head(nopriv_browser)
+    Name
+    Owner
+    Base Source
+    Registered
+
+    >>> print_recipe_listing_contents(nopriv_browser)
+    spr-name... Person-name... lp:~.../+git/... ...
+    spr-name... Person-name... lp:~.../+git/... ...
+    spr-name... Person-name... lp:~.../+git/... ...
+    spr-name... Person-name... lp:~.../+git/... ...
+
 
 Person Recipe Listings
 ======================
@@ -115,7 +200,7 @@
 
     >>> print_recipe_listing_head(nopriv_browser)
     Name
-    Base Branch
+    Base Source
     Registered
 
 The listings should now show all recipes whose base branch is a branch from

=== modified file 'lib/lp/code/templates/branch-recipes.pt'
--- lib/lp/code/templates/branch-recipes.pt	2015-10-05 13:36:06 +0000
+++ lib/lp/code/templates/branch-recipes.pt	2016-01-12 15:24:34 +0000
@@ -3,7 +3,7 @@
   xmlns:metal="http://xml.zope.org/namespaces/metal";
   xmlns:i18n="http://xml.zope.org/namespaces/i18n";
   tal:define="context_menu view/context/menu:context"
-  id="related-bugs-and-blueprints">
+  id="related-recipes">
 
   <h3>Related source package recipes</h3>
 

=== modified file 'lib/lp/code/templates/gitref-index.pt'
--- lib/lp/code/templates/gitref-index.pt	2015-09-18 15:41:08 +0000
+++ lib/lp/code/templates/gitref-index.pt	2016-01-12 15:24:34 +0000
@@ -7,6 +7,15 @@
   i18n:domain="launchpad"
 >
 
+<metal:block fill-slot="head_epilogue">
+  <style type="text/css">
+    #merge-summary, #recipe-summary {
+      margin-top: .5em;
+      margin-bottom: .1em;
+    }
+  </style>
+</metal:block>
+
 <body>
 
 <tal:registering metal:fill-slot="registering">
@@ -24,10 +33,10 @@
   </div>
 
   <div class="yui-g">
-    <div id="ref-relations" class="portlet"
-         tal:condition="python: view.show_merge_links or view.show_snap_information">
+    <div id="ref-relations" class="portlet">
       <tal:ref-pending-merges
            replace="structure context/@@++ref-pending-merges" />
+      <tal:ref-recipes replace="structure context/@@++ref-recipes" />
       <div metal:use-macro="context/@@+snap-macros/related-snaps" />
     </div>
   </div>

=== added file 'lib/lp/code/templates/gitref-recipes.pt'
--- lib/lp/code/templates/gitref-recipes.pt	1970-01-01 00:00:00 +0000
+++ lib/lp/code/templates/gitref-recipes.pt	2016-01-12 15:24:34 +0000
@@ -0,0 +1,19 @@
+<div
+  xmlns:tal="http://xml.zope.org/namespaces/tal";
+  xmlns:metal="http://xml.zope.org/namespaces/metal";
+  xmlns:i18n="http://xml.zope.org/namespaces/i18n";
+  id="related-recipes">
+
+  <h3>Related source package recipes</h3>
+
+  <div id="recipe-links" class="actions">
+    <div id="recipe-summary">
+      <img src="/@@/source-package-recipe" />
+      <tal:recipes replace="structure view/recipes_link" />
+
+      <a href="/+help-code/related-recipes.html" target="help"
+         class="sprite maybe action-icon">(?)</a>
+    </div>
+  </div>
+
+</div>

=== modified file 'lib/lp/code/templates/gitrepository-index.pt'
--- lib/lp/code/templates/gitrepository-index.pt	2015-12-04 15:48:39 +0000
+++ lib/lp/code/templates/gitrepository-index.pt	2016-01-12 15:24:34 +0000
@@ -9,6 +9,10 @@
 
 <metal:block fill-slot="head_epilogue">
   <style type="text/css">
+    #merge-summary, #recipe-summary {
+      margin-top: .5em;
+      margin-bottom: .1em;
+    }
     #clone-url dt {
       font-weight: strong;
     }
@@ -41,8 +45,9 @@
   </div>
 
   <div class="yui-g">
-    <div id="repository-relations" class="portlet"
-         tal:condition="view/show_snap_information">
+    <div id="repository-relations" class="portlet">
+      <tal:repository-recipes
+           replace="structure context/@@++repository-recipes" />
       <div metal:use-macro="context/@@+snap-macros/related-snaps">
         <metal:context-type fill-slot="context_type">repository</metal:context-type>
       </div>

=== added file 'lib/lp/code/templates/gitrepository-recipes.pt'
--- lib/lp/code/templates/gitrepository-recipes.pt	1970-01-01 00:00:00 +0000
+++ lib/lp/code/templates/gitrepository-recipes.pt	2016-01-12 15:24:34 +0000
@@ -0,0 +1,19 @@
+<div
+  xmlns:tal="http://xml.zope.org/namespaces/tal";
+  xmlns:metal="http://xml.zope.org/namespaces/metal";
+  xmlns:i18n="http://xml.zope.org/namespaces/i18n";
+  id="related-recipes">
+
+  <h3>Related source package recipes</h3>
+
+  <div id="recipe-links" class="actions">
+    <div id="recipe-summary">
+      <img src="/@@/source-package-recipe" />
+      <tal:recipes replace="structure view/recipes_link" />
+
+      <a href="/+help-code/related-recipes.html" target="help"
+         class="sprite maybe action-icon">(?)</a>
+    </div>
+  </div>
+
+</div>

=== modified file 'lib/lp/code/templates/sourcepackagerecipe-listing.pt'
--- lib/lp/code/templates/sourcepackagerecipe-listing.pt	2011-02-23 01:24:09 +0000
+++ lib/lp/code/templates/sourcepackagerecipe-listing.pt	2016-01-12 15:24:34 +0000
@@ -15,7 +15,7 @@
         <tr>
           <th colspan="2">Name</th>
           <th tal:condition="view/owner_enabled">Owner</th>
-          <th tal:condition="view/branch_enabled">Base Branch</th>
+          <th tal:condition="view/branch_enabled">Base Source</th>
           <th>Registered</th>
         </tr>
       </thead>
@@ -32,8 +32,8 @@
               </a>
             </td>
             <td tal:condition="view/branch_enabled">
-              <a tal:replace="structure recipe/base_branch/fmt:link">
-                Branch
+              <a tal:replace="structure recipe/base/fmt:link">
+                Source
               </a>
             </td>
             <td tal:content="recipe/date_created/fmt:datetime" />


Follow ups