← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~jml/launchpad/branch-sample-data-doctests into lp:launchpad/devel

 

Jonathan Lange has proposed merging lp:~jml/launchpad/branch-sample-data-doctests into lp:launchpad/devel.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)


As part of an eventually-ending quest to get rid of sampledata, this branch fixes doc/branch.txt to not need any.

Specifically, it takes a bunch of crap from doc/branch.txt and moves it to unit tests. It also tweaks some of the existing doctest to use sampledata.

In one case, I removed a small piece of crappy functionality: the count of the number of branches with linked bugs that is displayed on the code.launchpad.net homepage.

The branch also fixes a minor bug where merge_control_status was in the public interface but did not have view access granted.

-- 
https://code.launchpad.net/~jml/launchpad/branch-sample-data-doctests/+merge/30426
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jml/launchpad/branch-sample-data-doctests into lp:launchpad/devel.
=== modified file 'lib/lp/code/browser/bazaar.py'
--- lib/lp/code/browser/bazaar.py	2010-05-11 09:36:14 +0000
+++ lib/lp/code/browser/bazaar.py	2010-07-20 15:27:56 +0000
@@ -41,10 +41,6 @@
         return getUtility(IProductSet).getProductsWithBranches().count()
 
     @property
-    def branches_with_bugs_count(self):
-        return getUtility(IBranchSet).countBranchesWithAssociatedBugs()
-
-    @property
     def import_count(self):
         return getUtility(ICodeImportSet).search(
             review_status=CodeImportReviewStatus.REVIEWED).count()

=== modified file 'lib/lp/code/configure.zcml'
--- lib/lp/code/configure.zcml	2010-06-16 18:18:32 +0000
+++ lib/lp/code/configure.zcml	2010-07-20 15:27:56 +0000
@@ -460,6 +460,7 @@
                     last_mirrored_id
                     last_mirror_attempt
                     mirror_failures
+                    merge_control_status
                     pull_disabled
                     next_mirror_time
                     last_scanned

=== modified file 'lib/lp/code/doc/branch.txt'
--- lib/lp/code/doc/branch.txt	2010-05-27 02:09:13 +0000
+++ lib/lp/code/doc/branch.txt	2010-07-20 15:27:56 +0000
@@ -27,16 +27,9 @@
 
     >>> from canonical.launchpad.webapp.testing import verifyObject
     >>> from lp.code.enums import BranchType
-    >>> from lp.code.interfaces.branch import IBranch, IBranchSet
+    >>> from lp.code.interfaces.branch import IBranchSet
     >>> from lp.code.interfaces.branchsubscription import IBranchSubscription
-    >>> from lp.code.model.branch import Branch, BranchSet
-    >>> from lp.code.model.branchsubscription import BranchSubscription
-    >>> verifyObject(IBranchSet, BranchSet())
-    True
-    >>> verifyObject(IBranch, Branch.get(1))
-    True
-    >>> verifyObject(IBranchSubscription, BranchSubscription.get(1))
-    True
+    >>> from lp.code.model.branch import Branch
 
 
 == Branch types ==
@@ -73,7 +66,6 @@
 registered as an utility.
 
     >>> from zope.component import getUtility
-    >>> from lp.code.interfaces.branch import IBranchSet
     >>> from lp.code.interfaces.branchlookup import IBranchLookup
     >>> branchset = getUtility(IBranchSet)
     >>> branch_lookup = getUtility(IBranchLookup)
@@ -96,7 +88,6 @@
 details like the type of the branch -- whether it is mirrored, hosted,
 imported or remote, name, and so on.
 
-    >>> from lp.registry.interfaces.person import IPersonSet
     >>> registrant = factory.makePerson(name='registrant')
     >>> from lp.code.interfaces.branchnamespace import (
     ...     get_branch_namespace)
@@ -145,17 +136,6 @@
     LaunchpadValidationError: Invalid branch name 'invalid name!'.  Branch ...
 
 
-== Determing the number of branches with bugs ==
-
-The count of branches that have bugs associated with them is another
-useful piece of summary information that is supplied on one of the initial
-pages to show that there can be a relationship created between
-branches and bugs.
-
-    >>> branchset.countBranchesWithAssociatedBugs()
-    2
-
-
 == Determining the recently changed, registered and imported branches ==
 
 The IBranchSet methods getRecentlyChangedBranches, getRecentlyImportedBranches,
@@ -275,19 +255,6 @@
 
 == Branch subscriptions ==
 
-Branches can be subscribed to and unsubscribed from by a Person.  An
-implicit subscription to the branch is created when the branch is created
-so that the branch owner can be informed of merge proposals or code review
-messages relating to their branches.
-
-    >>> owner = factory.makePerson()
-    >>> branch = factory.makeAnyBranch(owner=owner)
-    >>> subscriptions = list(branch.subscriptions)
-    >>> print len(subscriptions)
-    1
-    >>> subscriptions[0].person == owner
-    True
-
 Branch subscriptions have attributes associated with them.
 The notification_level is used to control what email is sent to the
 subscribed user, and max_diff_lines is used to control the size of
@@ -301,8 +268,6 @@
     >>> from lp.code.enums import (
     ...     BranchSubscriptionDiffSize, BranchSubscriptionNotificationLevel,
     ...     CodeReviewNotificationLevel)
-    >>> from lp.code.interfaces.branchsubscription import (
-    ...     IBranchSubscription)
     >>> subscriber = factory.makePerson(name='subscriber')
     >>> branch = factory.makeProductBranch(
     ...     owner=user, product=product, name='subscribed')
@@ -380,199 +345,6 @@
     subscriber
 
 
-== Branches and revisions ==
-
-See revision.txt for a doctest covering the creation of revisions and related
-objects. Revision data is loaded in the database by a batch job using a
-different user, Launchpad code is only concened with using this data.
-
-Let's get a branch with some revisions in it.
-
-    >>> personset = getUtility(IPersonSet)
-    >>> sample_person = personset.getByName('name12')
-    >>> junk = branch_lookup.getByUniqueName('~name12/+junk/junk.dev')
-    >>> print junk.unique_name
-    ~name12/+junk/junk.dev
-
-
-== Revision history of Branch ==
-
-Branch.revision_history gives the sequence of revisions in this branch's
-history, latest revisions first. All revision history items must implement the
-IBranchRevision interface. The Branch.revision_count attribute gives the length
-of the revision_history attribute but without building the list.
-
-    >>> from lp.code.interfaces.branchrevision import IBranchRevision
-    >>> junk.revision_count
-    6
-    >>> [verifyObject(IBranchRevision, a) for a in junk.revision_history]
-    [True, True, True, True, True, True]
-    >>> for branch_revision in junk.revision_history:
-    ...     print branch_revision.sequence, branch_revision.revision.id
-    6 9
-    5 8
-    4 7
-    3 6
-    2 5
-    1 4
-
-There are two methods for getting only the latest items of the revision
-history.
-
-Branch.latest_revisions give a specific count of BranchRevisions at the end of
-the history.
-
-    >>> three_latest = list(junk.revision_history)[:3]
-    >>> list(junk.latest_revisions(3)) == three_latest
-    True
-
-Branch.getRevisionsSince gives all the BranchRevisions for revisions committed
-since a given timestamp. It may give surprising results if some committers had a
-skewed clock.
-
-    >>> from datetime import datetime
-    >>> timestamp = datetime(2005, 10, 31, 12, 00, 00)
-    >>> two_latest = list(junk.revision_history)[:2]
-    >>> list(junk.getRevisionsSince(timestamp)) == two_latest
-    True
-
-
-== Ancestry of Revision ==
-
-The revision-history of a given branch, is only one possible ancestry path in
-the ancestry graph. It is also possible to examine the ancestry graph directly.
-
-A Bazaar branch may contains references (by revision_id) to revisions for which
-no data is available. Such revisions are called "ghosts".
-
-Initial commits (after a "bzr init") revisions have no parent.
-
-    >>> history = list(junk.revision_history)
-    >>> initial = history[-1].revision
-    >>> initial.parent_ids
-    []
-
-Normal commits (as opposed to merges) have exactly one parent. The first parent
-of a revision is always the revision that was current when committing.
-
-    >>> commit = history[-2].revision
-    >>> [type(a) for a in commit.parent_ids] == [unicode]
-    True
-
-Merges usually have two parents, but they may have more. Though the bzr user
-interface discourage such complex merges.
-
-    >>> merge = history[-4].revision
-    >>> len(merge.parent_ids)
-    2
-
-Parent revisions are identified by their globally unique id, and not by a
-foreign key, so existing parents and ghosts can be modelled in the same way.
-
-To try and retrieve a Revision given its globally unique id, you can use the
-RevisionSet utility.
-
-    >>> from lp.code.interfaces.revision import IRevisionSet
-    >>> revisionset = getUtility(IRevisionSet)
-    >>> [parent_id] = commit.parent_ids
-    >>> parent = revisionset.getByRevisionId(parent_id)
-    >>> parent == initial
-    True
-
-If the parent was a ghost at import time and is not currently available in the
-database. getByRevisionId returns None.
-
-    >>> revisionset.getByRevisionId('missing-revision-id') is None
-    True
-
-
-== Getting the tip revision for a Branch ==
-
-The last revision that we have stored in the database for any given branch
-is identified by the branch attribute "last_scanned_id".  This is the textual
-revision_id for the bzr revision.  The reason that it is a text id rather than
-an integer foreign key is so it can easily be compared to the
-"last_mirrored_id".  The "last_mirrored_id" is set by the branch puller, and is
-used to identify when a scan is needed for a branch.
-
-    >>> branch = branch_lookup.get(1)
-    >>> branch.last_scanned_id
-    >>> branch.getTipRevision() is None
-    True
-
-    >>> branch.last_scanned_id = 'null:'
-    >>> branch.getTipRevision() is None
-    True
-
-    >>> branch.last_scanned_id = 'test@xxxxxxxxxxxxx-20051031165248-6f1bb97973c2b4f4'
-    >>> rev = branch.getTipRevision()
-    >>> print rev.date_created
-    2005-10-31 17:21:47.381770+00:00
-    >>> print rev.log_body
-    initial import (empty)
-
-
-== Codebrowse and branches ==
-
-Most branches are able to be browsed using the loggerhead codebrowse
-instance at http://bazaar.launchpad.net.  Branches that have no
-revisions or private branches are not able to be viewed using code
-browse.
-
-The link to codebrowse is shown on the action context menu for branches.
-The enabling of this link is controlled using the branch property
-`code_is_browseable`.
-
-For a public branch with revisions, the link is enabled.
-
-    >>> branch = branch_lookup.getByUniqueName('~name12/+junk/junk.dev')
-    >>> print branch.private
-    False
-    >>> print branch.revision_count
-    6
-    >>> print branch.code_is_browseable
-    True
-
-For a public branch without revisions, the link is disabled.
-
-    >>> branch = branch_lookup.getByUniqueName('~name12/gnome-terminal/main')
-    >>> print branch.private
-    False
-    >>> print branch.revision_count
-    0
-    >>> print branch.code_is_browseable
-    False
-
-
-== Associated product series ==
-
-A branch is able to return a list of product series that the branch is
-associated with through ProductSeries.branch.
-
-    >>> branch = branch_lookup.getByUniqueName('~vcs-imports/evolution/main')
-    >>> series = list(branch.associatedProductSeries())
-    >>> len(series)
-    1
-    >>> series = series[0]
-    >>> print series.product.name, series.name
-    evolution trunk
-
-
-== Deleting branches ==
-
-If a user creates a branch in error, they should be able to remove that branch.
-
-A branch can be deleted trivially if it is not associated with any bugs or
-blueprints, has no subscribers, and hasn't been associated with any product
-series.
-
-Deleting the branch is done through Branch.destroySelf.  If the branch is not
-deletable then an exception is raised.
-
-More details can be found in the file
-canonical/launchpad/database/tests/test_branch.py.
-
-
 == Branch references ==
 
 When new references to the branch table are added, these need to be

=== modified file 'lib/lp/code/interfaces/branch.py'
--- lib/lp/code/interfaces/branch.py	2010-07-09 10:22:32 +0000
+++ lib/lp/code/interfaces/branch.py	2010-07-20 15:27:56 +0000
@@ -1160,12 +1160,6 @@
 
     export_as_webservice_collection(IBranch)
 
-    def countBranchesWithAssociatedBugs():
-        """Return the number of branches that have bugs associated.
-
-        Only counts public branches.
-        """
-
     def getRecentlyChangedBranches(
         branch_count=None,
         lifecycle_statuses=DEFAULT_BRANCH_STATUS_IN_LISTING,

=== modified file 'lib/lp/code/interfaces/revision.py'
--- lib/lp/code/interfaces/revision.py	2010-04-16 15:06:55 +0000
+++ lib/lp/code/interfaces/revision.py	2010-07-20 15:27:56 +0000
@@ -35,7 +35,11 @@
         title=_("Has karma been allocated for this revision?"),
         required=True, default=False)
     parents = Attribute("The RevisionParents for this revision.")
-    parent_ids = Attribute("The revision_ids of the parent Revisions.")
+    parent_ids = Attribute(
+        "The revision_ids of the parent Revisions. Parent revisions are "
+        "identified by their revision_id rather than a foreign key "
+        "so that ghosts and parents that actually exist can be modelled "
+        "in the same way.")
     properties = Attribute("The `RevisionProperty`s for this revision.")
 
     def getProperties():

=== modified file 'lib/lp/code/model/branch.py'
--- lib/lp/code/model/branch.py	2010-07-17 22:49:11 +0000
+++ lib/lp/code/model/branch.py	2010-07-20 15:27:56 +0000
@@ -1190,13 +1190,6 @@
 
     implements(IBranchSet)
 
-    def countBranchesWithAssociatedBugs(self):
-        """See `IBranchSet`."""
-        return Branch.select(
-            'NOT Branch.private AND Branch.id = BugBranch.branch',
-            clauseTables=['BugBranch'],
-            distinct=True).count()
-
     def getRecentlyChangedBranches(
         self, branch_count=None,
         lifecycle_statuses=DEFAULT_BRANCH_STATUS_IN_LISTING,

=== modified file 'lib/lp/code/model/tests/test_branch.py'
--- lib/lp/code/model/tests/test_branch.py	2010-07-17 23:15:30 +0000
+++ lib/lp/code/model/tests/test_branch.py	2010-07-20 15:27:56 +0000
@@ -14,6 +14,7 @@
 from unittest import TestLoader
 
 from bzrlib.bzrdir import BzrDir
+from bzrlib.revision import NULL_REVISION
 
 from pytz import UTC
 
@@ -49,13 +50,15 @@
 from lp.code.interfaces.branch import (
     BranchCannotBePrivate, BranchCannotBePublic,
     BranchCreatorNotMemberOfOwnerTeam, BranchCreatorNotOwner,
-    BranchTargetError, CannotDeleteBranch, DEFAULT_BRANCH_STATUS_IN_LISTING)
+    BranchTargetError, CannotDeleteBranch, DEFAULT_BRANCH_STATUS_IN_LISTING,
+    IBranch)
 from lp.code.interfaces.branchjob import (
     IBranchUpgradeJobSource, IBranchScanJobSource)
 from lp.code.interfaces.branchlookup import IBranchLookup
 from lp.code.interfaces.branchnamespace import IBranchNamespaceSet
 from lp.code.interfaces.branchmergeproposal import (
     BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES)
+from lp.code.interfaces.branchrevision import IBranchRevision
 from lp.code.interfaces.linkedbranch import ICanHasLinkedBranch
 from lp.code.interfaces.seriessourcepackagebranch import (
     IFindOfficialBranchLinks)
@@ -426,6 +429,28 @@
             SourcePackage(branch.sourcepackagename, branch.distroseries),
             branch.sourcepackage)
 
+    def test_implements_IBranch(self):
+        # Instances of Branch provide IBranch.
+        branch = self.factory.makeBranch()
+        # We don't care about security, we just want to check that it
+        # implements the interface.
+        self.assertProvides(removeSecurityProxy(branch), IBranch)
+
+    def test_associatedProductSeries_initial(self):
+        # By default, a branch has no associated product series.
+        branch = self.factory.makeBranch()
+        self.assertEqual([], list(branch.associatedProductSeries()))
+
+    def test_associatedProductSeries_linked(self):
+        # When a branch is linked to a product series, that product series is
+        # included in associatedProductSeries.
+        branch = self.factory.makeProductBranch()
+        product = removeSecurityProxy(branch.product)
+        ICanHasLinkedBranch(product).setBranch(branch)
+        self.assertEqual(
+            [product.development_focus],
+            list(branch.associatedProductSeries()))
+
 
 class TestBranchUpgrade(TestCaseWithFactory):
     """Test the upgrade functionalities of branches."""
@@ -1710,8 +1735,123 @@
             [(rev.revision_id, revision_number)])
 
 
-class TestCodebrowseURL(TestCaseWithFactory):
-    """Tests for `Branch.codebrowse_url`."""
+class TestRevisionHistory(TestCaseWithFactory):
+    """Tests for a branch's revision history."""
+
+    layer = DatabaseFunctionalLayer
+
+    def test_revision_count(self):
+        # A branch's revision count is equal to the number of revisions that
+        # are associated with it.
+        branch = self.factory.makeBranch()
+        some_number = 6
+        self.factory.makeRevisionsForBranch(branch, count=some_number)
+        self.assertEqual(some_number, branch.revision_count)
+
+    def test_revision_history_matches_count(self):
+        branch = self.factory.makeBranch()
+        some_number = 3
+        self.factory.makeRevisionsForBranch(branch, count=some_number)
+        self.assertEqual(
+            branch.revision_count, branch.revision_history.count())
+
+    def test_revision_history_is_made_of_revisions(self):
+        # Branch.revision_history contains IBranchRevision objects.
+        branch = self.factory.makeBranch()
+        some_number = 6
+        self.factory.makeRevisionsForBranch(branch, count=some_number)
+        for branch_revision in branch.revision_history:
+            self.assertProvides(branch_revision, IBranchRevision)
+
+    def test_continuous_sequence_numbers(self):
+        # The revisions in the revision history have sequence numbers which
+        # start from 1 at the oldest and don't have any gaps.
+        branch = self.factory.makeBranch()
+        some_number = 4
+        self.factory.makeRevisionsForBranch(branch, count=some_number)
+        self.assertEqual(
+            [4, 3, 2, 1], [br.sequence for br in branch.revision_history])
+
+    def test_most_recent_first(self):
+        # The revisions in the revision history start with the most recent
+        # first.
+        branch = self.factory.makeBranch()
+        some_number = 4
+        self.factory.makeRevisionsForBranch(branch, count=some_number)
+        revision_history = list(branch.revision_history)
+        sorted_by_date = sorted(
+            revision_history, key=lambda x: x.revision.revision_date,
+            reverse=True)
+        self.assertEqual(sorted_by_date, revision_history)
+
+    def test_latest_revisions(self):
+        # IBranch.latest_revisions gives only the latest revisions.
+        branch = self.factory.makeBranch()
+        some_number = 7
+        self.factory.makeRevisionsForBranch(branch, count=some_number)
+        smaller_number = some_number / 2
+        self.assertEqual(
+            list(branch.revision_history[:smaller_number]),
+            list(branch.latest_revisions(smaller_number)))
+
+    def test_getRevisionsSince(self):
+        # IBranch.getRevisionsSince gives all the BranchRevisions for
+        # revisions committed since a given timestamp.
+        branch = self.factory.makeBranch()
+        some_number = 7
+        self.factory.makeRevisionsForBranch(branch, count=some_number)
+        mid_sequence = some_number - 2
+        revisions = list(branch.revision_history)
+        mid_revision = revisions[mid_sequence]
+        since = branch.getRevisionsSince(mid_revision.revision.revision_date)
+        self.assertEqual(revisions[:mid_sequence], list(since))
+
+    def test_top_ancestor_has_no_parents(self):
+        # The top-most revision of a branch (i.e. the first one) has no
+        # parents.
+        branch = self.factory.makeBranch()
+        self.factory.makeRevisionsForBranch(branch, count=1)
+        revision = list(branch.revision_history)[0].revision
+        self.assertEqual([], revision.parent_ids)
+
+    def test_non_first_revisions_have_parents(self):
+        # Revisions which are not the first revision of the branch have
+        # parent_ids. When there are no merges present, there is only one
+        # parent which is the previous revision.
+        branch = self.factory.makeBranch()
+        some_number = 5
+        self.factory.makeRevisionsForBranch(branch, count=some_number)
+        revisions = list(branch.revision_history)
+        last_rev = revisions[0].revision
+        second_last_rev = revisions[1].revision
+        self.assertEqual(last_rev.parent_ids, [second_last_rev.revision_id])
+
+    def test_tip_revision_when_no_bazaar_data(self):
+        # When a branch has no revisions and no Bazaar data at all, its tip
+        # revision is None and its last_scanned_id is None.
+        branch = self.factory.makeBranch()
+        self.assertIs(None, branch.last_scanned_id)
+        self.assertIs(None, branch.getTipRevision())
+
+    def test_tip_revision_when_no_revisions(self):
+        # When a branch has no revisions but does have Bazaar data, its tip
+        # revision is None and its last_scanned_id is
+        # bzrlib.revision.NULL_REVISION.
+        branch = self.factory.makeBranch()
+        branch.updateScannedDetails(None, 0)
+        self.assertEqual(NULL_REVISION, branch.last_scanned_id)
+        self.assertIs(None, branch.getTipRevision())
+
+    def test_tip_revision_is_updated(self):
+        branch = self.factory.makeBranch()
+        revision = self.factory.makeRevision()
+        branch.updateScannedDetails(revision, 1)
+        self.assertEqual(revision.revision_id, branch.last_scanned_id)
+        self.assertEqual(revision, branch.getTipRevision())
+
+
+class TestCodebrowse(TestCaseWithFactory):
+    """Tests for branch codebrowse support."""
 
     layer = DatabaseFunctionalLayer
 
@@ -1745,6 +1885,17 @@
         self.assertEqual(
             branch.browse_source_url, branch.codebrowse_url('files'))
 
+    def test_no_revisions_not_browseable(self):
+        # A branch with no revisions is not browseable.
+        branch = self.factory.makeBranch()
+        self.assertFalse(branch.code_is_browseable)
+
+    def test_revisions_means_browseable(self):
+        # A branch that has revisions is browseable.
+        branch = self.factory.makeBranch()
+        self.factory.makeRevisionsForBranch(branch, count=5)
+        self.assertTrue(branch.code_is_browseable)
+
 
 class TestBranchNamespace(TestCaseWithFactory):
     """Tests for `IBranch.namespace`."""

=== modified file 'lib/lp/code/model/tests/test_branchset.py'
--- lib/lp/code/model/tests/test_branchset.py	2010-07-09 10:22:32 +0000
+++ lib/lp/code/model/tests/test_branchset.py	2010-07-20 15:27:56 +0000
@@ -7,6 +7,7 @@
 
 from unittest import TestLoader
 
+from lp.code.interfaces.branch import IBranchSet
 from lp.code.model.branch import BranchSet
 from lp.testing import TestCaseWithFactory
 from canonical.testing import DatabaseFunctionalLayer
@@ -20,6 +21,10 @@
         TestCaseWithFactory.setUp(self)
         self.branch_set = BranchSet()
 
+    def test_provides_IBranchSet(self):
+        # BranchSet instances provide IBranchSet.
+        self.assertProvides(self.branch_set, IBranchSet)
+
     def test_getByUrls(self):
         # getByUrls returns a list of branches matching the list of URLs that
         # it's given.

=== modified file 'lib/lp/code/model/tests/test_branchsubscription.py'
--- lib/lp/code/model/tests/test_branchsubscription.py	2010-05-28 09:04:16 +0000
+++ lib/lp/code/model/tests/test_branchsubscription.py	2010-07-20 15:27:56 +0000
@@ -21,6 +21,12 @@
 
     layer = DatabaseFunctionalLayer
 
+    def test_owner_subscribed(self):
+        # The owner of a branch is subscribed to the branch.
+        branch = self.factory.makeBranch()
+        [subscription] = list(branch.subscriptions)
+        self.assertEqual(branch.owner, subscription.person)
+
     def test_subscribed_by_set(self):
         """The user subscribing is recorded along the subscriber."""
         subscriber = self.factory.makePerson()

=== modified file 'lib/lp/code/model/tests/test_revision.py'
--- lib/lp/code/model/tests/test_revision.py	2010-07-12 13:06:41 +0000
+++ lib/lp/code/model/tests/test_revision.py	2010-07-20 15:27:56 +0000
@@ -225,6 +225,28 @@
         self.assertEqual(branch.product, karma.product)
 
 
+class TestRevisionSet(TestCaseWithFactory):
+    """Tests for IRevisionSet."""
+
+    layer = DatabaseFunctionalLayer
+
+    def setUp(self):
+        super(TestRevisionSet, self).setUp()
+        self.revision_set = getUtility(IRevisionSet)
+
+    def test_getRevisionById_existing(self):
+        # IRevisionSet.getByRevisionId returns the revision with that id.
+        revision = self.factory.makeRevision()
+        found = self.revision_set.getByRevisionId(revision.revision_id)
+        self.assertEquals(revision, found)
+
+    def test_getRevisionById_nonexistent(self):
+        # IRevisionSet.getByRevisionId returns None if there is no revision
+        # with that id.
+        found = self.revision_set.getByRevisionId('nonexistent')
+        self.assertIs(None, found)
+
+
 class TestRevisionGetBranch(TestCaseWithFactory):
     """Test the `getBranch` method of the revision."""
 

=== modified file 'lib/lp/code/templates/bazaar-index.pt'
--- lib/lp/code/templates/bazaar-index.pt	2010-06-10 16:44:26 +0000
+++ lib/lp/code/templates/bazaar-index.pt	2010-07-20 15:27:56 +0000
@@ -127,10 +127,6 @@
           </a>
         </div>
         <div>
-          <strong tal:content="view/branches_with_bugs_count">12</strong>
-          branches associated with bug reports
-        </div>
-        <div>
           Launchpad uses <a href="http://bazaar.canonical.com/";>Bazaar</a>
           <tal:version tal:content="view/bzr_version">2.0</tal:version>.
         </div>