launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #18700
Re: [Merge] lp:~wgrant/launchpad/gitlisting into lp:launchpad
Review: Approve
Looks fine, just a few inline suggestions.
Diff comments:
> === 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)
Any reason not to preemptively handle IPersonDistributionSourcePackage here too?
> +
> + @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)
You could just use IGitCollection(self.context).visibleByUser(self.user) here, which is shorter and works for both IPersonProduct and IPersonDistributionSourcePackage.
>
> === 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">
Perhaps show repository/description here too, like lib/lp/code/templates/gitrepository-index.pt.
> + <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">
Is it worth removing the "Bazaar branches" heading and the surrounding portlet that I added here when I put the temporary hack in place? It might look a bit odd now that the page will only show Bazaar branches again.
>
--
https://code.launchpad.net/~wgrant/launchpad/gitlisting/+merge/261066
Your team Launchpad code reviewers is subscribed to branch lp:launchpad.
References