← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/bugsummary-v2-app-no-fixed-upstream into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/bugsummary-v2-app-no-fixed-upstream into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #950502 in Launchpad itself: ""Bugs fixed elsewhere" count is expensive and of dubious utility"
  https://bugs.launchpad.net/launchpad/+bug/950502

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/bugsummary-v2-app-no-fixed-upstream/+merge/106557

This branch continues bug #950502, completely removing the application side of the "Bugs fixed elsewhere" count that has been disabled on production for two months. BugSummary.fixed_upstream support gets ripped out of the model, in preparation for its purging from the DB next week.
-- 
https://code.launchpad.net/~wgrant/launchpad/bugsummary-v2-app-no-fixed-upstream/+merge/106557
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/bugsummary-v2-app-no-fixed-upstream into lp:launchpad.
=== modified file 'lib/lp/bugs/browser/bugtask.py'
--- lib/lp/bugs/browser/bugtask.py	2012-05-01 07:24:59 +0000
+++ lib/lp/bugs/browser/bugtask.py	2012-05-21 03:40:21 +0000
@@ -1977,8 +1977,8 @@
         # Circular fail.
         from lp.bugs.model.bugsummary import BugSummary
         bug_task_set = getUtility(IBugTaskSet)
-        groups = (BugSummary.status, BugSummary.importance,
-            BugSummary.has_patch, BugSummary.fixed_upstream)
+        groups = (
+            BugSummary.status, BugSummary.importance, BugSummary.has_patch)
         counts = bug_task_set.countBugs(self.user, [self.context], groups)
         # Sum the split out aggregates.
         new = 0
@@ -1987,12 +1987,10 @@
         critical = 0
         high = 0
         with_patch = 0
-        resolved_upstream = 0
         for metadata, count in counts.items():
             status = metadata[0]
             importance = metadata[1]
             has_patch = metadata[2]
-            was_resolved_upstream = metadata[3]
             if status == BugTaskStatus.NEW:
                 new += count
             elif status == BugTaskStatus.INPROGRESS:
@@ -2003,20 +2001,13 @@
                 high += count
             if has_patch and DISPLAY_BUG_STATUS_FOR_PATCHES[status]:
                 with_patch += count
-            if was_resolved_upstream:
-                resolved_upstream += count
             open += count
-        result = dict(new=new, open=open, inprogress=inprogress, high=high,
-            critical=critical, with_patch=with_patch,
-            resolved_upstream=resolved_upstream)
+        result = dict(
+            new=new, open=open, inprogress=inprogress, high=high,
+            critical=critical, with_patch=with_patch)
         return result
 
     @property
-    def bugs_fixed_elsewhere_count(self):
-        """A count of bugs fixed elsewhere."""
-        return self._bug_stats['resolved_upstream']
-
-    @property
     def open_cve_bugs_count(self):
         """A count of open bugs linked to CVEs."""
         params = get_default_search_params(self.user)

=== removed file 'lib/lp/bugs/browser/tests/special/bugs-fixed-elsewhere.txt'
--- lib/lp/bugs/browser/tests/special/bugs-fixed-elsewhere.txt	2012-04-04 05:46:26 +0000
+++ lib/lp/bugs/browser/tests/special/bugs-fixed-elsewhere.txt	1970-01-01 00:00:00 +0000
@@ -1,144 +0,0 @@
-Bugs Fixed Elsewhere
-====================
-
-The +bugtarget-portlet-bugfilters-info view for a distribution or
-product contains a property for a URL to a list of bugs fixed
-elsewhere.
-
-    >>> from zope.component import getMultiAdapter
-    >>> from lp.services.webapp.servers import LaunchpadTestRequest
-
-    >>> view = getMultiAdapter(
-    ...     (bugtarget, LaunchpadTestRequest()),
-    ...     name='+bugtarget-portlet-bugfilters-info')
-    >>> view.initialize()
-
-    >>> view.bugs_fixed_elsewhere_url
-    u'http://.../+bugs?field.status_upstream=resolved_upstream'
-
-The +bugtarget-portlet-bugfilters-stats view for a distribution or
-product contains the URL as above in addition to a count of how many
-bugs that are fixed elsewhere. This count can take a while to
-calculate, so it is put on this separate view which can be requested
-asyncronously.
-
-    >>> def get_view():
-    ...     view = getMultiAdapter(
-    ...         (bugtarget, LaunchpadTestRequest()),
-    ...         name='+bugtarget-portlet-bugfilters-stats')
-    ...     view.initialize()
-    ...     return view
-
-    >>> view = get_view()
-    >>> view.bugs_fixed_elsewhere_url
-    u'http://.../+bugs?field.status_upstream=resolved_upstream'
-    >>> view.bugs_fixed_elsewhere_count
-    0
-
-Simply opening a bug elsewhere won't increase the count.
-
-    >>> from lp.registry.interfaces.product import IProductSet
-    >>> evolution = getUtility(IProductSet).getByName('evolution')
-    >>> evolution != bugtarget
-    True
-
-    >>> bug = filebug(bugtarget, 'Example Bug')
-
-    >>> from lp.bugs.interfaces.bugtask import IBugTaskSet
-    >>> elsewhere = getUtility(IBugTaskSet).createTask(
-    ...     bug, getUtility(ILaunchBag).user, evolution)
-    >>> get_view().bugs_fixed_elsewhere_count
-    0
-
-But if we mark the bug as fixed in the other, the count will increase
-by one.
-
-    >>> from lp.bugs.interfaces.bugtask import BugTaskStatus
-    >>> elsewhere.transitionToStatus(
-    ...     BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
-
-    >>> get_view().bugs_fixed_elsewhere_count
-    1L
-
-Bugs fixed elsewhere also show up when we perform an advanced bug
-search, using the appropriate query string parameter to ask for "bugs
-resolved elsewhere":
-
-    >>> search_view = getMultiAdapter(
-    ...     (bugtarget,
-    ...      LaunchpadTestRequest(
-    ...         form={'field.status_upstream': 'resolved_upstream'})),
-    ...     name='+bugs')
-    >>> search_view.initialize()
-    >>> navigator = search_view.search()
-
-    >>> for task in search_view.search().batch:
-    ...     for related_task in task.related_tasks:
-    ...         print related_task.target.name
-    ...         print related_task.status.name
-    evolution
-    FIXRELEASED
-
-
-Private Bugs
-------------
-
-Only bugs that the user has permission to view are included in the count.
-
-    >>> another_bug = filebug(bugtarget, 'Example Bug')
-    >>> another_bug.setPrivate(True, getUtility(ILaunchBag).user)
-    True
-
-    >>> another_elsewhere = getUtility(IBugTaskSet).createTask(
-    ...     another_bug, getUtility(ILaunchBag).user, evolution)
-    >>> another_elsewhere.transitionToStatus(
-    ...     BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
-
-    >>> get_view().bugs_fixed_elsewhere_count
-    2L
-
-This means that No Privileges Person will see that there is only one bug
-fixed elsewhere.
-
-    >>> login('no-priv@xxxxxxxxxxxxx')
-    >>> get_view().bugs_fixed_elsewhere_count
-    1L
-
-If the private bug is made public again, he will of course see that
-there are two bugs fixed.
-
-    >>> login('foo.bar@xxxxxxxxxxxxx')
-    >>> another_bug.setPrivate(False, getUtility(ILaunchBag).user)
-    True
-
-    >>> login('no-priv@xxxxxxxxxxxxx')
-    >>> get_view().bugs_fixed_elsewhere_count
-    2L
-
-
-Duplicate Bugs
---------------
-
-Bugs that are duplicate of other bugs aren't included in the count.
-
-    >>> another_bug.markAsDuplicate(bug)
-
-    >>> get_view().bugs_fixed_elsewhere_count
-    1L
-
-
-Resolved Bugs
--------------
-
-The count includes only bugs that are open in the current context.
-
-    >>> for bugtask in bug.bugtasks:
-    ...     if bugtask.target == bugtarget:
-    ...         break
-    ... else:
-    ...     print "Couldn't find a bugtasks for %r" % bugtarget
-    >>> bugtask.transitionToStatus(
-    ...     BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
-
-    >>> get_view().bugs_fixed_elsewhere_count
-    0

=== removed file 'lib/lp/bugs/browser/tests/test_bugs_fixed_elsewhere.py'
--- lib/lp/bugs/browser/tests/test_bugs_fixed_elsewhere.py	2011-12-30 06:14:56 +0000
+++ lib/lp/bugs/browser/tests/test_bugs_fixed_elsewhere.py	1970-01-01 00:00:00 +0000
@@ -1,73 +0,0 @@
-# Copyright 2009 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Test harness for running the bugs-fixed-elsewhere.txt tests."""
-
-__metaclass__ = type
-
-__all__ = []
-
-import unittest
-
-from zope.component import getUtility
-
-from lp.bugs.interfaces.bug import CreateBugParams
-from lp.bugs.interfaces.bugtask import BugTaskStatus
-from lp.registry.interfaces.distribution import IDistributionSet
-from lp.registry.interfaces.product import IProductSet
-from lp.services.database.sqlbase import (
-    cursor,
-    sqlvalues,
-    )
-from lp.services.webapp.interfaces import ILaunchBag
-from lp.testing import login
-from lp.testing.layers import LaunchpadFunctionalLayer
-from lp.testing.systemdocs import (
-    LayeredDocFileSuite,
-    setUp,
-    tearDown,
-    )
-
-
-def bugtarget_filebug(bugtarget, summary):
-    """File a bug as the current user on the bug target and return it."""
-    return bugtarget.createBug(CreateBugParams(
-        getUtility(ILaunchBag).user, summary, comment=summary))
-
-def commonSetUp(test):
-    """Set up common for all tests."""
-    setUp(test)
-    test.globs['filebug'] = bugtarget_filebug
-    login('test@xxxxxxxxxxxxx')
-    # Ensure that there are no fixed bugs in sample data that might
-    # interfere with the tests.
-    cur = cursor()
-    cur.execute("UPDATE BugTask SET status = %s" % (
-        sqlvalues(BugTaskStatus.NEW)))
-
-
-def productSetUp(test):
-    commonSetUp(test)
-    test.globs['bugtarget'] = getUtility(IProductSet).getByName('firefox')
-
-
-def distributionSetUp(test):
-    commonSetUp(test)
-    test.globs['bugtarget'] = getUtility(IDistributionSet).getByName('ubuntu')
-
-
-def test_suite():
-    suite = unittest.TestSuite()
-
-    setUpMethods = [
-        productSetUp,
-        distributionSetUp,
-        ]
-
-    for setUpMethod in setUpMethods:
-        test = LayeredDocFileSuite(
-            'special/bugs-fixed-elsewhere.txt',
-            setUp=setUpMethod, tearDown=tearDown,
-            layer=LaunchpadFunctionalLayer)
-        suite.addTest(test)
-    return suite

=== modified file 'lib/lp/bugs/doc/bugsummary.txt'
--- lib/lp/bugs/doc/bugsummary.txt	2012-05-02 05:25:11 +0000
+++ lib/lp/bugs/doc/bugsummary.txt	2012-05-21 03:40:21 +0000
@@ -14,20 +14,19 @@
     - milestone
     - importance
     - has_patch
-    - fixed_upstream
 
 
 First we should setup some helpers to use in the examples. These will
 let us dump the BugSummary table in a readable format.
 
     ---------------------------------------------------------------
-    prod ps   dist ds   spn   tag mile status import pa up vis    #
+    prod ps   dist ds   spn   tag mile status import pa vis    #
     ---------------------------------------------------------------
 
 The columns are product, productseries, distribution, distroseries,
 sourcepackagename, tag, milestone, status, importance, has_patch,
-fixed_upstream, viewed_by and the count. viewed_by is a team reference
-and used to query private bug counts.
+viewed_by and the count. viewed_by is a team reference and used to
+query private bug counts.
 
     >>> from lp.services.database.lpstorm import IMasterStore
     >>> from lp.bugs.interfaces.bugtask import BugTaskStatus
@@ -60,14 +59,13 @@
     ...         BugSummary.sourcepackagename_id, BugSummary.tag,
     ...         BugSummary.milestone_id, BugSummary.status,
     ...         BugSummary.importance, BugSummary.has_patch,
-    ...         BugSummary.fixed_upstream, BugSummary.viewed_by_id,
-    ...         BugSummary.id)
+    ...         BugSummary.viewed_by_id, BugSummary.id)
     ...     fmt = (
     ...         "%-4s %-4s %-4s %-4s %-5s %-3s %-4s "
-    ...         "%-6s %-6s %-2s %-2s %-4s %3s")
+    ...         "%-6s %-6s %-2s %-4s %3s")
     ...     header = fmt % (
     ...         'prod', 'ps', 'dist', 'ds', 'spn', 'tag', 'mile',
-    ...         'status', 'import', 'pa', 'up', 'vis', '#')
+    ...         'status', 'import', 'pa', 'vis', '#')
     ...     print "-" * len(header)
     ...     print header
     ...     print "-" * len(header)
@@ -83,7 +81,6 @@
     ...             str(bugsummary.status)[:6],
     ...             str(bugsummary.importance)[:6],
     ...             str(bugsummary.has_patch)[:1],
-    ...             str(bugsummary.fixed_upstream)[:1],
     ...             name(bugsummary.viewed_by),
     ...             bugsummary.count)
     ...     print " " * (len(header) - 4),
@@ -122,12 +119,12 @@
     ...     BugSummary.tag == None)
 
     >>> print_result(bug_summaries)
-    ---------------------------------------------------------------
-    prod ps   dist ds   spn   tag mile status import pa up vis    #
-    ---------------------------------------------------------------
-    pr-a x    x    x    x     x   x    New    Undeci F  F  x      1
-                                                                ===
-                                                                  1
+    ------------------------------------------------------------
+    prod ps   dist ds   spn   tag mile status import pa vis    #
+    ------------------------------------------------------------
+    pr-a x    x    x    x     x   x    New    Undeci F  x      1
+                                                             ===
+                                                               1
 
 There is one row per tag per combination of product, status and milestone.
 If we are interested in all bugs targeted to a product regardless of how
@@ -148,13 +145,13 @@
     ...     BugSummary.product == prod_a,
     ...     BugSummary.tag == None,
     ...     BugSummary.viewed_by == None)
-    ---------------------------------------------------------------
-    prod ps   dist ds   spn   tag mile status import pa up vis    #
-    ---------------------------------------------------------------
-    pr-a x    x    x    x     x   x    New    Undeci F  F  x      2
-    pr-a x    x    x    x     x   x    Confir Undeci F  F  x      2
-                                                                ===
-                                                                  4
+    ------------------------------------------------------------
+    prod ps   dist ds   spn   tag mile status import pa vis    #
+    ------------------------------------------------------------
+    pr-a x    x    x    x     x   x    New    Undeci F  x      2
+    pr-a x    x    x    x     x   x    Confir Undeci F  x      2
+                                                             ===
+                                                               4
 
 Here are the rows associated with the 't-a' tag. There is 1 Confirmed
 bug task targetted to the pr-a product who's bug is tagged 't-a'.:
@@ -163,12 +160,12 @@
     ...     BugSummary.product == prod_a,
     ...     BugSummary.tag == u't-a',
     ...     BugSummary.viewed_by == None)
-    ---------------------------------------------------------------
-    prod ps   dist ds   spn   tag mile status import pa up vis    #
-    ---------------------------------------------------------------
-    pr-a x    x    x    x     t-a x    Confir Undeci F  F  x      1
-                                                                ===
-                                                                  1
+    ------------------------------------------------------------
+    prod ps   dist ds   spn   tag mile status import pa vis    #
+    ------------------------------------------------------------
+    pr-a x    x    x    x     t-a x    Confir Undeci F  x      1
+                                                             ===
+                                                               1
 
 You will normally want to get the total count counted in the database
 rather than waste transmission time to calculate the rows client side.
@@ -208,17 +205,17 @@
     >>> print_find(
     ...     BugSummary.product == prod_a,
     ...     BugSummary.viewed_by == None)
-    ---------------------------------------------------------------
-    prod ps   dist ds   spn   tag mile status import pa up vis    #
-    ---------------------------------------------------------------
-    pr-a x    x    x    x     t-a x    Confir Undeci F  F  x      1
-    pr-a x    x    x    x     t-b ms-a New    Undeci F  F  x      1
-    pr-a x    x    x    x     t-c ms-a New    Undeci F  F  x      1
-    pr-a x    x    x    x     x   ms-a New    Undeci F  F  x      1
-    pr-a x    x    x    x     x   x    New    Undeci F  F  x      2
-    pr-a x    x    x    x     x   x    Confir Undeci F  F  x      2
-                                                                ===
-                                                                  8
+    ------------------------------------------------------------
+    prod ps   dist ds   spn   tag mile status import pa vis    #
+    ------------------------------------------------------------
+    pr-a x    x    x    x     t-a x    Confir Undeci F  x      1
+    pr-a x    x    x    x     t-b ms-a New    Undeci F  x      1
+    pr-a x    x    x    x     t-c ms-a New    Undeci F  x      1
+    pr-a x    x    x    x     x   ms-a New    Undeci F  x      1
+    pr-a x    x    x    x     x   x    New    Undeci F  x      2
+    pr-a x    x    x    x     x   x    Confir Undeci F  x      2
+                                                             ===
+                                                               8
 
 Number of New bugs not targeted to a milestone. Note the difference
 between selecting records where tag is None, and where milestone is None:
@@ -272,13 +269,13 @@
     ...         BugSummary.productseries == productseries_b,
     ...         BugSummary.product == prod_b),
     ...     BugSummary.viewed_by == None)
-    ---------------------------------------------------------------
-    prod ps   dist ds   spn   tag mile status import pa up vis    #
-    ---------------------------------------------------------------
-    pr-b x    x    x    x     x   x    New    Undeci F  F  x      1
-    x    ps-b x    x    x     x   x    New    Undeci F  F  x      1
-                                                                ===
-                                                                  2
+    ------------------------------------------------------------
+    prod ps   dist ds   spn   tag mile status import pa vis    #
+    ------------------------------------------------------------
+    pr-b x    x    x    x     x   x    New    Undeci F  x      1
+    x    ps-b x    x    x     x   x    New    Undeci F  x      1
+                                                             ===
+                                                               2
 
 Distribution Bug Counts
 -----------------------
@@ -300,14 +297,14 @@
     >>> print_find(
     ...     BugSummary.distribution == distribution,
     ...     BugSummary.viewed_by == None)
-    ---------------------------------------------------------------
-    prod ps   dist ds   spn   tag mile status import pa up vis    #
-    ---------------------------------------------------------------
-    x    x    di-a x    sp-a  x   x    New    Undeci F  F  x      1
-    x    x    di-a x    x     x   x    New    Undeci F  F  x      1
-    x    x    di-a x    x     x   x    Confir Undeci F  F  x      1
-                                                                ===
-                                                                  3
+    ------------------------------------------------------------
+    prod ps   dist ds   spn   tag mile status import pa vis    #
+    ------------------------------------------------------------
+    x    x    di-a x    sp-a  x   x    New    Undeci F  x      1
+    x    x    di-a x    x     x   x    New    Undeci F  x      1
+    x    x    di-a x    x     x   x    Confir Undeci F  x      1
+                                                             ===
+                                                               3
 
 How many bugs targeted to a distribution?
 
@@ -372,12 +369,12 @@
     >>> print_find(
     ...     BugSummary.distroseries == series_c,
     ...     BugSummary.viewed_by == None)
-    ---------------------------------------------------------------
-    prod ps   dist ds   spn   tag mile status import pa up vis    #
-    ---------------------------------------------------------------
-    x    x    x    ds-c x     x   x    New    Undeci F  F  x      1
-                                                                ===
-                                                                  1
+    ------------------------------------------------------------
+    prod ps   dist ds   spn   tag mile status import pa vis    #
+    ------------------------------------------------------------
+    x    x    x    ds-c x     x   x    New    Undeci F  x      1
+                                                             ===
+                                                               1
 
 
 Privacy
@@ -444,18 +441,18 @@
     ...     BugSummary.distribution == distro_p,
     ...     BugSummary.distroseries == series_p)
     >>> print_find(distro_or_series)
-    ---------------------------------------------------------------
-    prod ps   dist ds   spn   tag mile status import pa up vis    #
-    ---------------------------------------------------------------
-    x    x    di-p x    x     x   x    New    Undeci F  F  p-b    1
-    x    x    di-p x    x     x   x    New    Undeci F  F  own    3
-    x    x    di-p x    x     x   x    New    Undeci F  F  t-a    1
-    x    x    di-p x    x     x   x    New    Undeci F  F  t-c    1
-    x    x    di-p x    x     x   x    New    Undeci F  F  x      1
-    x    x    x    ds-p x     x   x    New    Undeci F  F  own    1
-    x    x    x    ds-p x     x   x    New    Undeci F  F  t-c    1
-                                                                ===
-                                                                  9
+    ------------------------------------------------------------
+    prod ps   dist ds   spn   tag mile status import pa vis    #
+    ------------------------------------------------------------
+    x    x    di-p x    x     x   x    New    Undeci F  p-b    1
+    x    x    di-p x    x     x   x    New    Undeci F  own    3
+    x    x    di-p x    x     x   x    New    Undeci F  t-a    1
+    x    x    di-p x    x     x   x    New    Undeci F  t-c    1
+    x    x    di-p x    x     x   x    New    Undeci F  x      1
+    x    x    x    ds-p x     x   x    New    Undeci F  own    1
+    x    x    x    ds-p x     x   x    New    Undeci F  t-c    1
+                                                             ===
+                                                               9
 
 So how many public bugs are there on the distro?
 

=== modified file 'lib/lp/bugs/interfaces/bugsummary.py'
--- lib/lp/bugs/interfaces/bugsummary.py	2011-12-24 16:54:44 +0000
+++ lib/lp/bugs/interfaces/bugsummary.py	2012-05-21 03:40:21 +0000
@@ -72,7 +72,6 @@
     viewed_by = Object(IPerson, readonly=True)
 
     has_patch = Bool(readonly=True)
-    fixed_upstream = Bool(readonly=True)
 
 
 class IBugSummaryDimension(Interface):

=== modified file 'lib/lp/bugs/model/bugsummary.py'
--- lib/lp/bugs/model/bugsummary.py	2011-12-30 06:14:56 +0000
+++ lib/lp/bugs/model/bugsummary.py	2012-05-21 03:40:21 +0000
@@ -78,7 +78,6 @@
     viewed_by = Reference(viewed_by_id, Person.id)
 
     has_patch = Bool()
-    fixed_upstream = Bool()
 
 
 class CombineBugSummaryConstraint:

=== modified file 'lib/lp/bugs/model/tests/test_bugsummary.py'
--- lib/lp/bugs/model/tests/test_bugsummary.py	2012-05-02 05:25:11 +0000
+++ lib/lp/bugs/model/tests/test_bugsummary.py	2012-05-21 03:40:21 +0000
@@ -976,143 +976,6 @@
                 BugSummary.milestone == milestone),
             0)
 
-    def test_fixUpstream(self):
-        distribution = self.factory.makeDistribution()
-        product = self.factory.makeProduct()
-        distro_bugtask = self.factory.makeBugTask(target=distribution)
-        bug = distro_bugtask.bug
-        product_bugtask = self.factory.makeBugTask(bug=bug, target=product)
-
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == True),
-            0)
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == False),
-            1)
-
-        product_bugtask.transitionToStatus(
-            BugTaskStatus.FIXRELEASED, bug.owner)
-
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == True),
-            1)
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == False),
-            0)
-
-    def test_breakUpstream(self):
-        distribution = self.factory.makeDistribution()
-        product = self.factory.makeProduct()
-        distro_bugtask = self.factory.makeBugTask(target=distribution)
-        bug = distro_bugtask.bug
-        product_bugtask = self.factory.makeBugTask(bug=bug, target=product)
-
-        product_bugtask.transitionToStatus(
-            BugTaskStatus.FIXCOMMITTED, bug.owner)
-
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == True),
-            1)
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == False),
-            0)
-
-        product_bugtask.transitionToStatus(
-            BugTaskStatus.INPROGRESS, bug.owner)
-
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == True),
-            0)
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == False),
-            1)
-
-    def test_fixUpstreamViaWatch(self):
-        distribution = self.factory.makeDistribution()
-        product = self.factory.makeProduct()
-        distro_bugtask = self.factory.makeBugTask(target=distribution)
-        bug = distro_bugtask.bug
-        product_bugtask = self.factory.makeBugTask(bug=bug, target=product)
-        self.factory.makeBugWatch(bug_task=product_bugtask)
-
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == True),
-            0)
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == False),
-            1)
-
-        # Bugs flagged INVALID by upstream count as fixed upstream.
-        product_bugtask.transitionToStatus(
-            BugTaskStatus.INVALID, bug.owner)
-
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == True),
-            1)
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == False),
-            0)
-
-    def test_breakUpstreamViaWatch(self):
-        distribution = self.factory.makeDistribution()
-        product = self.factory.makeProduct()
-        distro_bugtask = self.factory.makeBugTask(target=distribution)
-        bug = distro_bugtask.bug
-        product_bugtask = self.factory.makeBugTask(bug=bug, target=product)
-        self.factory.makeBugWatch(bug_task=product_bugtask)
-
-        product_bugtask.transitionToStatus(
-            BugTaskStatus.FIXCOMMITTED, bug.owner)
-
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == True),
-            1)
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == False),
-            0)
-
-        product_bugtask.transitionToStatus(
-            BugTaskStatus.UNKNOWN, bug.owner)
-
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == True),
-            0)
-        self.assertEqual(
-            self.getPublicCount(
-                BugSummary.distribution == distribution,
-                BugSummary.fixed_upstream == False),
-            1)
-
     def test_addPatch(self):
         product = self.factory.makeProduct()
         bug = self.factory.makeBug(product=product)

=== modified file 'lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt'
--- lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt	2012-03-15 05:55:42 +0000
+++ lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt	2012-05-21 03:40:21 +0000
@@ -37,7 +37,7 @@
     0 Critical bugs
     0 High importance bugs
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     2 Open CVE bugs - CVE reports
 
@@ -71,7 +71,7 @@
     0 Bugs reported by me
       Bugs affecting me
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     2 Open CVE bugs - CVE reports
 
@@ -107,7 +107,7 @@
     0 Critical bugs
     0 High importance bugs
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     1 Open CVE bug - CVE report
 
@@ -140,7 +140,7 @@
     0 Bugs reported by me
       Bugs affecting me
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     1 Open CVE bug - CVE report
 
@@ -175,7 +175,7 @@
     0 Critical bugs
     0 High importance bugs
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     2 Open CVE bugs
 
@@ -208,7 +208,7 @@
     0 Bugs reported by me
       Bugs affecting me
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     2 Open CVE bugs
 
@@ -247,7 +247,7 @@
     0 Critical bugs
     0 High importance bugs
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     1 Open CVE bug
 
@@ -280,7 +280,7 @@
     0 Bugs reported by me
       Bugs affecting me
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     1 Open CVE bug
 
@@ -318,7 +318,7 @@
     1 Critical bug
     0 High importance bugs
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     1 Open CVE bug
 
@@ -352,7 +352,7 @@
     0 Bugs reported by me
       Bugs affecting me
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     1 Open CVE bug
 
@@ -390,7 +390,7 @@
     1 Critical bug
     0 High importance bugs
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     1 Open CVE bug - CVE report
 
@@ -424,7 +424,7 @@
     0 Bugs reported by me
       Bugs affecting me
     <BLANKLINE>
-    0 Bugs fixed elsewhere
+      Bugs fixed elsewhere
     0 Bugs with patches
     1 Open CVE bug - CVE report
 
@@ -433,30 +433,3 @@
 
     >>> print user_browser.getLink('CVE report').url
     http://bugs.launchpad.dev/firefox/+cve
-
-
-Hiding "Bugs fixed elsewhere" counts
-------------------------------------
-
-The count of bugs fixed elsewhere is of dubious utility, and it's
-expensive to calculate when generating BugSummary. As a trial before we
-remove it, there's a feature flag to hide the count.
-
-    >>> print_bugfilters_portlet_filled(user_browser, path)
-    3 New bugs
-    ...
-    <BLANKLINE>
-    0 Bugs fixed elsewhere
-    0 Bugs with patches
-    ...
-
-    >>> from lp.services.features.testing import FeatureFixture
-    >>> with FeatureFixture(
-    ...     {'bugs.statistics_portlet.hide_fixed_elsewhere_count': 'true'}):
-    ...     print print_bugfilters_portlet_filled(user_browser, path)
-    3 New bugs
-    ...
-    <BLANKLINE>
-      Bugs fixed elsewhere
-    0 Bugs with patches
-    ...

=== modified file 'lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt'
--- lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt	2012-03-14 13:19:43 +0000
+++ lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt	2012-05-21 03:40:21 +0000
@@ -110,18 +110,7 @@
 
   <tr><td colspan="2"><br /></td></tr>
 
-  <tr tal:condition="not: request/features/bugs.statistics_portlet.hide_fixed_elsewhere_count"
-      tal:define="count view/bugs_fixed_elsewhere_count|nothing;
-                  plural string: Bugs fixed elsewhere;
-                  singular string: Bug fixed elsewhere;">
-    <td class="bugs-count" tal:content="count" />
-    <td class="bugs-link">
-      <a tal:attributes="href string:${view/bugs_fixed_elsewhere_url}">
-      <metal:message use-macro="context/@@+base-layout-macros/plural-message"/>
-      </a>
-    </td>
-  </tr>
-  <tr tal:condition="request/features/bugs.statistics_portlet.hide_fixed_elsewhere_count">
+  <tr>
     <tal:comment condition="nothing">
       No count here, because generating it is expensive.
     </tal:comment>

=== modified file 'lib/lp/services/features/flags.py'
--- lib/lp/services/features/flags.py	2012-05-08 01:31:10 +0000
+++ lib/lp/services/features/flags.py	2012-05-21 03:40:21 +0000
@@ -96,13 +96,6 @@
      '',
      '',
      ''),
-    ('bugs.statistics_portlet.hide_fixed_elsewhere_count',
-     'boolean',
-     ('Hides the "Bugs fixed elsewhere" count in the bug target statistics '
-      'portlet.'),
-     '',
-     '',
-     ''),
     ('code.ajax_revision_diffs.enabled',
      'boolean',
      ("Offer expandable inline diffs for branch revisions."),


Follow ups