launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #18696
[Merge] lp:~wgrant/launchpad/gitlisting into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/gitlisting into lp:launchpad.
Commit message:
Add Product:+git and PersonProduct:+git, and remove the temporary Git bits from Product:+branches.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/gitlisting/+merge/261066
Add Product:+git and PersonProduct:+git, displaying the details of the default repo and a list of any others. Product:+branches' temporary default Git rendering is gone.
The next branch includes link between the VCS pages if there are artifacts for the other one. A later branch will introduce a +code view which shows the default VCS at https://code.launchpad.net/PROJECT.
I'll also be reworking GitRepository:+index and experimenting with how best to integrate all of the the default repo's +index bits into the target's +git, but it's good enough for now.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/gitlisting into lp:launchpad.
=== modified file 'lib/lp/code/browser/branchlisting.py'
--- lib/lp/code/browser/branchlisting.py 2015-06-02 10:53:52 +0000
+++ lib/lp/code/browser/branchlisting.py 2015-06-04 09:15:20 +0000
@@ -68,7 +68,6 @@
from lp.bugs.interfaces.bugbranch import IBugBranchSet
from lp.code.browser.branch import BranchMirrorMixin
from lp.code.browser.branchmergeproposallisting import ActiveReviewsView
-from lp.code.browser.gitrepository import GitRefBatchNavigator
from lp.code.browser.summary import BranchCountSummaryView
from lp.code.enums import (
BranchLifecycleStatus,
@@ -85,7 +84,6 @@
from lp.code.interfaces.branchcollection import IAllBranches
from lp.code.interfaces.branchnamespace import IBranchNamespacePolicy
from lp.code.interfaces.branchtarget import IBranchTarget
-from lp.code.interfaces.gitrepository import IGitRepositorySet
from lp.code.interfaces.revision import IRevisionSet
from lp.code.interfaces.revisioncache import IRevisionCache
from lp.code.interfaces.seriessourcepackagebranch import (
@@ -526,7 +524,6 @@
field_names = ['lifecycle', 'sort_by']
development_focus_branch = None
show_set_development_focus = False
- default_git_repository = None
custom_widget('lifecycle', LaunchpadDropdownWidget)
custom_widget('sort_by', LaunchpadDropdownWidget)
# Showing the series links is only really useful on product listing
@@ -1098,26 +1095,6 @@
else:
return None
- @cachedproperty
- def default_git_repository(self):
- repository = getUtility(IGitRepositorySet).getDefaultRepository(
- self.context)
- if repository is None:
- return None
- elif check_permission('launchpad.View', repository):
- return repository
- else:
- return None
-
- def default_git_repository_branches(self):
- """All branches in the default Git repository, sorted for display."""
- return GitRefBatchNavigator(self, self.default_git_repository)
-
- @property
- def has_default_git_repository(self):
- """Is there a default Git repository?"""
- return self.default_git_repository is not None
-
@property
def no_branch_message(self):
if (self.selected_lifecycle_status is not None
=== modified file 'lib/lp/code/browser/configure.zcml'
--- lib/lp/code/browser/configure.zcml 2015-06-02 08:57:02 +0000
+++ lib/lp/code/browser/configure.zcml 2015-06-04 09:15:20 +0000
@@ -875,6 +875,24 @@
attribute_to_parent="repository"
rootsite="code"/>
+ <browser:page
+ for="lp.registry.interfaces.product.IProduct"
+ class="lp.code.browser.gitlisting.TargetGitListingView"
+ permission="zope.Public"
+ name="+git"
+ template="../templates/gitlisting.pt"/>
+ <browser:page
+ for="lp.registry.interfaces.personproduct.IPersonProduct"
+ class="lp.code.browser.gitlisting.PersonTargetGitListingView"
+ permission="zope.Public"
+ name="+git"
+ template="../templates/gitlisting.pt"/>
+ <browser:page
+ for="lp.code.browser.gitlisting.IGitRepositoryBatchNavigator"
+ name="+gitrepository-listing"
+ template="../templates/gitrepository-listing.pt"
+ permission="zope.Public"/>
+
<browser:menus
classes="ProductBranchesMenu"
module="lp.code.browser.branchlisting"/>
=== added file 'lib/lp/code/browser/gitlisting.py'
--- lib/lp/code/browser/gitlisting.py 1970-01-01 00:00:00 +0000
+++ lib/lp/code/browser/gitlisting.py 2015-06-04 09:15:20 +0000
@@ -0,0 +1,154 @@
+# Copyright 2015 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""View classes for Git repository listings."""
+
+__metaclass__ = type
+
+__all__ = [
+ 'PersonTargetGitListingView',
+ 'TargetGitListingView',
+ ]
+
+from storm.expr import Desc
+from zope.component import getUtility
+from zope.interface import (
+ implements,
+ Interface,
+ )
+
+from lp.app.enums import PRIVATE_INFORMATION_TYPES
+from lp.code.browser.gitrepository import GitRefBatchNavigator
+from lp.code.interfaces.gitcollection import IGitCollection
+from lp.code.interfaces.gitnamespace import (
+ get_git_namespace,
+ IGitNamespacePolicy,
+ )
+from lp.code.interfaces.gitrepository import IGitRepositorySet
+from lp.code.model.gitrepository import GitRepository
+from lp.registry.interfaces.personproduct import IPersonProduct
+from lp.services.config import config
+from lp.services.propertycache import cachedproperty
+from lp.services.webapp.batching import TableBatchNavigator
+from lp.services.webapp.publisher import LaunchpadView
+from lp.services.webapp.authorization import check_permission
+
+
+class IGitRepositoryBatchNavigator(Interface):
+ pass
+
+
+class GitRepositoryBatchNavigator(TableBatchNavigator):
+ """Batch up Git repository listings."""
+ implements(IGitRepositoryBatchNavigator)
+
+ variable_name_prefix = 'repo'
+
+ def __init__(self, view, repo_collection):
+ super(GitRepositoryBatchNavigator, self).__init__(
+ repo_collection.getRepositories().order_by(
+ Desc(GitRepository.date_last_modified)),
+ view.request, size=config.launchpad.branchlisting_batch_size)
+ self.view = view
+ self.column_count = 2
+
+
+class BaseGitListingView(LaunchpadView):
+
+ @property
+ def target(self):
+ raise NotImplementedError()
+
+ @cachedproperty
+ def default_git_repository(self):
+ raise NotImplementedError()
+
+ @property
+ def repo_collection(self):
+ raise NotImplementedError()
+
+ def default_git_repository_branches(self):
+ """All branches in the default Git repository, sorted for display."""
+ return GitRefBatchNavigator(self, self.default_git_repository)
+
+ @cachedproperty
+ def default_information_type(self):
+ """The default information type for new repos."""
+ if self.user is None:
+ return None
+ namespace = get_git_namespace(self.target, self.user)
+ policy = IGitNamespacePolicy(namespace)
+ return policy.getDefaultInformationType(self.user)
+
+ @property
+ def default_information_type_title(self):
+ """The title of the default information type for new branches."""
+ information_type = self.default_information_type
+ if information_type is None:
+ return None
+ return information_type.title
+
+ @property
+ def default_information_type_is_private(self):
+ """The title of the default information type for new branches."""
+ return self.default_information_type in PRIVATE_INFORMATION_TYPES
+
+ @property
+ def repos(self):
+ return GitRepositoryBatchNavigator(self, self.repo_collection)
+
+
+class TargetGitListingView(BaseGitListingView):
+
+ page_title = 'Git'
+
+ @property
+ def target(self):
+ return self.context
+
+ @cachedproperty
+ def default_git_repository(self):
+ repo = getUtility(IGitRepositorySet).getDefaultRepository(
+ self.context)
+ if repo is None:
+ return None
+ elif check_permission('launchpad.View', repo):
+ return repo
+ else:
+ return None
+
+ @property
+ def repo_collection(self):
+ return IGitCollection(self.target).visibleByUser(self.user)
+
+
+class PersonTargetGitListingView(BaseGitListingView):
+
+ page_title = 'Git'
+
+ @property
+ def label(self):
+ return 'Git repositories for %s' % self.target.displayname
+
+ @property
+ def target(self):
+ if IPersonProduct.providedBy(self.context):
+ return self.context.product
+ else:
+ raise Exception("Unknown context: %r" % self.context)
+
+ @cachedproperty
+ def default_git_repository(self):
+ repo = getUtility(IGitRepositorySet).getDefaultRepositoryForOwner(
+ self.context.person, self.target)
+ if repo is None:
+ return None
+ elif check_permission('launchpad.View', repo):
+ return repo
+ else:
+ return None
+
+ @property
+ def repo_collection(self):
+ return IGitCollection(self.target).ownedBy(
+ self.context.person).visibleByUser(self.user)
=== added file 'lib/lp/code/browser/tests/test_gitlisting.py'
--- lib/lp/code/browser/tests/test_gitlisting.py 1970-01-01 00:00:00 +0000
+++ lib/lp/code/browser/tests/test_gitlisting.py 2015-06-04 09:15:20 +0000
@@ -0,0 +1,271 @@
+# Copyright 2015 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Unit tests for Git listing views."""
+
+__metaclass__ = type
+
+from BeautifulSoup import BeautifulSoup
+from zope.component import getUtility
+
+from lp.app.enums import InformationType
+from lp.code.interfaces.gitrepository import IGitRepositorySet
+from lp.registry.model.personproduct import PersonProduct
+from lp.testing import (
+ admin_logged_in,
+ anonymous_logged_in,
+ person_logged_in,
+ TestCaseWithFactory,
+ )
+from lp.testing.layers import DatabaseFunctionalLayer
+from lp.testing.views import create_initialized_view
+
+
+class TestTargetGitListingView(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def test_rendering(self):
+ owner = self.factory.makePerson(name=u"foowner")
+ product = self.factory.makeProduct(name=u"foo", owner=owner)
+ main_repo = self.factory.makeGitRepository(
+ owner=owner, target=product, name=u"foo")
+ self.factory.makeGitRefs(
+ main_repo,
+ paths=[u"refs/heads/master", u"refs/heads/1.0", u"refs/tags/1.1"])
+
+ other_repo = self.factory.makeGitRepository(
+ owner=self.factory.makePerson(name=u"contributor"),
+ target=product, name=u"foo")
+ self.factory.makeGitRefs(other_repo, paths=[u"refs/heads/bug-1234"])
+ self.factory.makeGitRepository(
+ owner=self.factory.makePerson(name=u"random"),
+ target=product, name=u"bar")
+
+ with admin_logged_in():
+ getUtility(IGitRepositorySet).setDefaultRepository(
+ target=product, repository=main_repo)
+ getUtility(IGitRepositorySet).setDefaultRepositoryForOwner(
+ owner=other_repo.owner, target=product, repository=other_repo,
+ user=other_repo.owner)
+
+ view = create_initialized_view(product, '+git')
+ self.assertEqual(main_repo, view.default_git_repository)
+
+ content = view()
+ soup = BeautifulSoup(content)
+
+ # Clone instructions for the default repo are present.
+ self.assertEqual(
+ 'git://git.launchpad.dev/foo',
+ soup.find(attrs={'class': 'anon-url'}).find(text=True))
+ self.assertEqual(
+ 'https://git.launchpad.dev/~foowner/foo/+git/foo',
+ soup.find(text='Browse the code').parent['href'])
+
+ # The default repo's branches are shown, but not its tags.
+ table = soup.find(
+ 'div', id='default-repository-branches').find('table')
+ self.assertContentEqual(
+ ['1.0', 'master'],
+ [link.find(text=True) for link in table.findAll('a')])
+ self.assertEndsWith(
+ table.find(text="1.0").parent['href'],
+ u"/~foowner/foo/+git/foo/+ref/1.0")
+
+ # Other repos are listed.
+ table = soup.find(
+ 'div', id='gitrepositories-table-listing').find('table')
+ self.assertContentEqual(
+ ['lp:foo', 'lp:~random/foo/+git/bar', 'lp:~contributor/foo'],
+ [link.find(text=True) for link in table.findAll('a')])
+ self.assertEndsWith(
+ table.find(text="lp:~contributor/foo").parent['href'],
+ u"/~contributor/foo/+git/foo")
+
+ # But not their branches.
+ self.assertNotIn('bug-1234', content)
+
+ def test_copes_with_no_default(self):
+ owner = self.factory.makePerson(name=u"foowner")
+ product = self.factory.makeProduct(name=u"foo", owner=owner)
+
+ self.factory.makeGitRepository(
+ owner=self.factory.makePerson(name=u"contributor"),
+ target=product, name=u"foo")
+
+ view = create_initialized_view(product, '+git')
+ self.assertIs(None, view.default_git_repository)
+
+ content = view()
+ soup = BeautifulSoup(content)
+
+ # No details about the non-existent default repo are shown.
+ # XXX: This should show instructions to create one.
+ self.assertNotIn('Branches', content)
+ self.assertNotIn('Browse the code', content)
+ self.assertNotIn('git clone', content)
+
+ # Other repos are listed.
+ table = soup.find(
+ 'div', id='gitrepositories-table-listing').find('table')
+ self.assertContentEqual(
+ ['lp:~contributor/foo/+git/foo'],
+ [link.find(text=True) for link in table.findAll('a')])
+
+ def test_copes_with_private_repos(self):
+ product = self.factory.makeProduct()
+ invisible_repo = self.factory.makeGitRepository(
+ target=product, information_type=InformationType.PRIVATESECURITY)
+ other_repo = self.factory.makeGitRepository(
+ target=product, information_type=InformationType.PUBLIC)
+ with admin_logged_in():
+ getUtility(IGitRepositorySet).setDefaultRepository(
+ target=product, repository=invisible_repo)
+
+ # An anonymous user can't see the default.
+ with anonymous_logged_in():
+ anon_view = create_initialized_view(product, '+git')
+ self.assertIs(None, anon_view.default_git_repository)
+ self.assertContentEqual(
+ [other_repo], anon_view.repo_collection.getRepositories())
+
+ # Neither can a random unprivileged user.
+ with person_logged_in(self.factory.makePerson()):
+ anon_view = create_initialized_view(product, '+git')
+ self.assertIs(None, anon_view.default_git_repository)
+ self.assertContentEqual(
+ [other_repo], anon_view.repo_collection.getRepositories())
+
+ # But someone who can see the repo gets the normal view.
+ with person_logged_in(product.owner):
+ owner_view = create_initialized_view(
+ product, '+git', user=product.owner)
+ self.assertEqual(invisible_repo, owner_view.default_git_repository)
+ self.assertContentEqual(
+ [invisible_repo, other_repo],
+ owner_view.repo_collection.getRepositories())
+
+
+class TestPersonTargetGitListingView(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def test_rendering(self):
+ owner = self.factory.makePerson(name=u"dev")
+ product = self.factory.makeProduct(name=u"foo")
+ default_repo = self.factory.makeGitRepository(
+ owner=owner, target=product, name=u"foo")
+ self.factory.makeGitRefs(
+ default_repo,
+ paths=[u"refs/heads/master", u"refs/heads/bug-1234"])
+
+ other_repo = self.factory.makeGitRepository(
+ owner=owner, target=product, name=u"bar")
+ self.factory.makeGitRefs(other_repo, paths=[u"refs/heads/bug-2468"])
+
+ with admin_logged_in():
+ getUtility(IGitRepositorySet).setDefaultRepositoryForOwner(
+ owner=owner, target=product, repository=default_repo,
+ user=owner)
+
+ view = create_initialized_view(PersonProduct(owner, product), '+git')
+ self.assertEqual(default_repo, view.default_git_repository)
+
+ content = view()
+ soup = BeautifulSoup(content)
+
+ # Clone instructions for the default repo are present.
+ self.assertEqual(
+ 'git://git.launchpad.dev/~dev/foo',
+ soup.find(attrs={'class': 'anon-url'}).find(text=True))
+ self.assertEqual(
+ 'https://git.launchpad.dev/~dev/foo/+git/foo',
+ soup.find(text='Browse the code').parent['href'])
+
+ # The default repo's branches are shown.
+ table = soup.find(
+ 'div', id='default-repository-branches').find('table')
+ self.assertContentEqual(
+ ['master', 'bug-1234'],
+ [link.find(text=True) for link in table.findAll('a')])
+ self.assertEndsWith(
+ table.find(text="bug-1234").parent['href'],
+ u"/~dev/foo/+git/foo/+ref/bug-1234")
+
+ # Other repos are listed.
+ table = soup.find(
+ 'div', id='gitrepositories-table-listing').find('table')
+ self.assertContentEqual(
+ ['lp:~dev/foo', 'lp:~dev/foo/+git/bar'],
+ [link.find(text=True) for link in table.findAll('a')])
+ self.assertEndsWith(
+ table.find(text="lp:~dev/foo/+git/bar").parent['href'],
+ u"/~dev/foo/+git/bar")
+
+ # But not their branches.
+ self.assertNotIn('bug-2468', content)
+
+ def test_copes_with_no_default(self):
+ owner = self.factory.makePerson(name=u"dev")
+ product = self.factory.makeProduct(name=u"foo", owner=owner)
+
+ self.factory.makeGitRepository(
+ owner=owner, target=product, name=u"foo")
+
+ view = create_initialized_view(PersonProduct(owner, product), '+git')
+ self.assertIs(None, view.default_git_repository)
+
+ content = view()
+ soup = BeautifulSoup(content)
+
+ # No details about the non-existent default repo are shown.
+ # XXX: This should show instructions to create one.
+ self.assertNotIn('Branches', content)
+ self.assertNotIn('Browse the code', content)
+ self.assertNotIn('git clone', content)
+
+ # Other repos are listed.
+ table = soup.find(
+ 'div', id='gitrepositories-table-listing').find('table')
+ self.assertContentEqual(
+ ['lp:~dev/foo/+git/foo'],
+ [link.find(text=True) for link in table.findAll('a')])
+
+ def test_copes_with_private_repos(self):
+ owner = self.factory.makePerson(name=u"dev")
+ product = self.factory.makeProduct()
+ invisible_repo = self.factory.makeGitRepository(
+ owner=owner, target=product,
+ information_type=InformationType.PRIVATESECURITY)
+ other_repo = self.factory.makeGitRepository(
+ owner=owner, target=product,
+ information_type=InformationType.PUBLIC)
+ with admin_logged_in():
+ getUtility(IGitRepositorySet).setDefaultRepositoryForOwner(
+ owner=owner, target=product, repository=invisible_repo,
+ user=owner)
+
+ pp = PersonProduct(owner, product)
+
+ # An anonymous user can't see the default.
+ with anonymous_logged_in():
+ anon_view = create_initialized_view(pp, '+git')
+ self.assertIs(None, anon_view.default_git_repository)
+ self.assertContentEqual(
+ [other_repo], anon_view.repo_collection.getRepositories())
+
+ # Neither can a random unprivileged user.
+ with person_logged_in(self.factory.makePerson()):
+ anon_view = create_initialized_view(pp, '+git')
+ self.assertIs(None, anon_view.default_git_repository)
+ self.assertContentEqual(
+ [other_repo], anon_view.repo_collection.getRepositories())
+
+ # But someone who can see the repo gets the normal view.
+ with person_logged_in(owner):
+ owner_view = create_initialized_view(pp, '+git', user=owner)
+ self.assertEqual(invisible_repo, owner_view.default_git_repository)
+ self.assertContentEqual(
+ [invisible_repo, other_repo],
+ owner_view.repo_collection.getRepositories())
=== modified file 'lib/lp/code/browser/tests/test_product.py'
--- lib/lp/code/browser/tests/test_product.py 2015-06-02 06:35:38 +0000
+++ lib/lp/code/browser/tests/test_product.py 2015-06-04 09:15:20 +0000
@@ -19,7 +19,6 @@
ServiceUsage,
)
from lp.code.enums import BranchType
-from lp.code.interfaces.gitrepository import IGitRepositorySet
from lp.code.interfaces.revision import IRevisionSet
from lp.registry.enums import BranchSharingPolicy
from lp.services.webapp import canonical_url
@@ -146,38 +145,6 @@
expected = 'There are no branches for %s' % product.displayname
self.assertIn(expected, html)
- def test_no_default_git_repository(self):
- # If there is no default Git repository, Product:+branches does not
- # try to render one.
- product = self.factory.makeProduct()
- view = create_initialized_view(
- product, '+branches', rootsite='code', principal=product.owner)
- self.assertIsNone(view.default_git_repository)
- self.assertFalse(view.has_default_git_repository)
- content = view()
- self.assertNotIn('git clone', content)
-
- def test_default_git_repository(self):
- # If there is a default Git repository, Product:+branches shows a
- # summary of its branches.
- product = self.factory.makeProduct()
- repository = self.factory.makeGitRepository(target=product)
- self.factory.makeGitRefs(
- repository=repository,
- paths=[u"refs/heads/master", u"refs/heads/another-branch"])
- with person_logged_in(product.owner):
- getUtility(IGitRepositorySet).setDefaultRepository(
- product, repository)
- view = create_initialized_view(
- product, '+branches', rootsite='code', principal=product.owner)
- self.assertEqual(repository, view.default_git_repository)
- self.assertTrue(view.has_default_git_repository)
- content = view()
- self.assertIn('git clone', content)
- # XXX cjwatson 2015-04-30: These tests are not very precise.
- self.assertIn('master', content)
- self.assertIn('another-branch', content)
-
class TestProductBranchesServiceUsages(ProductTestBase, BrowserTestCase):
"""Tests for the product code page, especially the usage messasges."""
=== added file 'lib/lp/code/templates/gitlisting.pt'
--- lib/lp/code/templates/gitlisting.pt 1970-01-01 00:00:00 +0000
+++ lib/lp/code/templates/gitlisting.pt 2015-06-04 09:15:20 +0000
@@ -0,0 +1,72 @@
+<html
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+ metal:use-macro="view/macro:page/main_side"
+ i18n:domain="launchpad"
+>
+<head>
+ <tal:head-epilogue metal:fill-slot="head_epilogue">
+ <meta tal:condition="view/target/codehosting_usage/enumvalue:UNKNOWN"
+ name="robots" content="noindex,nofollow" />
+ </tal:head-epilogue>
+</head>
+
+<body>
+ <metal:side fill-slot="side" tal:define="context_menu context/menu:context">
+ <div id="branch-portlet"
+ tal:condition="not: view/target/codehosting_usage/enumvalue:UNKNOWN">
+ <div id="privacy"
+ tal:define="private_class python: 'private' if view.default_information_type_is_private else 'public'"
+ tal:attributes="class string:first portlet ${private_class}">
+ <span tal:condition="not: view/default_information_type"
+ id="privacy-text">
+ You can't create new repositories for
+ <tal:name replace="context/displayname"/>.
+ <tal:sharing-link condition="context/required:launchpad.Edit">
+ <br/>This can be fixed by changing the branch sharing policy on the
+ <a tal:attributes="href string:${view/target/fmt:url:mainsite}/+sharing">sharing page</a>.
+ </tal:sharing-link>
+ </span>
+
+ <span tal:condition="view/default_information_type"
+ tal:attributes="class string:sprite ${private_class}"
+ id="privacy-text">
+ New repositories for <tal:name replace="view/target/displayname"/> are
+ <strong tal:content="view/default_information_type_title" />.
+ </span>
+ </div>
+ </div>
+ </metal:side>
+ <metal:main fill-slot="main">
+ <tal:default-repository
+ condition="view/default_git_repository"
+ define="repository view/default_git_repository">
+ <div class="yui-g first">
+ <div id="default-repository-management" class="top-portlet">
+ <tal:repository-management
+ replace="structure repository/@@++repository-management" />
+ </div>
+ </div>
+
+ <div class="yui-g">
+ <div id="default-repository-branches" class="portlet"
+ tal:define="branches view/default_git_repository_branches">
+ <h2>Branches</h2>
+ <tal:default-repository-branches
+ replace="structure branches/@@+ref-listing" />
+ </div>
+ </div>
+ </tal:default-repository>
+
+ <div class="yui-g">
+ <div id="other-repositories" class="portlet">
+ <h2>Other repositories</h2>
+ <tal:other-repos
+ content="structure view/repos/@@+gitrepository-listing" />
+ </div>
+ </div>
+ </metal:main>
+</body>
+</html>
=== added file 'lib/lp/code/templates/gitrepository-listing.pt'
--- lib/lp/code/templates/gitrepository-listing.pt 1970-01-01 00:00:00 +0000
+++ lib/lp/code/templates/gitrepository-listing.pt 2015-06-04 09:15:20 +0000
@@ -0,0 +1,30 @@
+<div id="gitrepositories-table-listing"
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ >
+ <tal:needs-batch condition="context/has_multiple_pages">
+ <div id="branch-batch-links">
+ <tal:navigation replace="structure context/@@+navigation-links-upper" />
+ </div>
+ </tal:needs-batch>
+ <table class="listing">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Last Modified</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr tal:repeat="repo context/currentBatch">
+ <td>
+ <a tal:content="repo/display_name"
+ tal:attributes="href repo/fmt:url">lp:foo</a>
+ </td>
+ <td tal:content="repo/date_last_modified/fmt:approximatedate">
+ 2 hours ago
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <tal:navigation replace="structure context/@@+navigation-links-lower" />
+</div>
=== modified file 'lib/lp/code/templates/product-branch-summary.pt'
--- lib/lp/code/templates/product-branch-summary.pt 2015-05-01 13:20:09 +0000
+++ lib/lp/code/templates/product-branch-summary.pt 2015-06-04 09:15:20 +0000
@@ -57,7 +57,7 @@
</div>
<tal:no-branches
- condition="python: not view.branch_count and not view.has_default_git_repository">
+ condition="not: view/branch_count">
There are no branches for <tal:project-name replace="context/displayname"/>
in Launchpad.
<tal:can-configure condition="view/can_configure_branches">
@@ -79,23 +79,6 @@
</tal:can-configure>
</tal:no-branches>
- <div tal:condition="view/has_default_git_repository"
- style="margin: 1em 0"
- tal:define="repository view/default_git_repository">
- You can
- <a tal:attributes="href repository/getCodebrowseUrl">browse the
- source code</a>
- for the default Git repository or get a copy of the repository using
- the command:<br/>
- <tt class="command">git clone
- <tal:logged-in condition="view/user">
- <tal:git-ssh-url replace="repository/ssh_url"/>
- </tal:logged-in>
- <tal:not-logged-in condition="not: view/user">
- <tal:git-anon-url replace="repository/anon_url"/>
- </tal:not-logged-in></tt>
- </div>
-
<tal:has-branches condition="view/branch_count">
<div tal:condition="view/has_development_focus_branch"
style="margin: 1em 0"
=== modified file 'lib/lp/code/templates/product-branches.pt'
--- lib/lp/code/templates/product-branches.pt 2015-06-01 08:43:09 +0000
+++ lib/lp/code/templates/product-branches.pt 2015-06-04 09:15:20 +0000
@@ -60,16 +60,6 @@
condition="not: view/context/codehosting_usage/enumvalue:UNKNOWN"
replace="structure context/@@+portlet-product-branchstatistics" />
- <tal:has-default-git-repository condition="view/has_default_git_repository">
- <div id="default-repository-branches" class="portlet"
- tal:define="repository view/default_git_repository;
- branches view/default_git_repository_branches">
- <h2>Git branches</h2>
- <tal:default-repository-branches
- replace="structure branches/@@+ref-listing" />
- </div>
- </tal:has-default-git-repository>
-
<tal:has-branches condition="view/branch_count"
define="branches view/branches">
<div class="portlet">
Follow ups