[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#756741: tracker.debian.org: Dead package warning



Control: tag-1 + patch


Here are 2 patches to fix this

--
Sophie Brun



>From 70612cefe4521658c352a1fc1ad037df2c6c0839 Mon Sep 17 00:00:00 2001
From: Sophie Brun <sophie@freexian.com>
Date: Fri, 12 Sep 2014 14:17:21 +0200
Subject: [PATCH 1/2] core/models: add Repository.is_development_repository()

Identifying development repositories is important to know when a package
is going away (because it's no longer in any development repository).
---
 distro_tracker/core/models.py             | 21 +++++++++++++++++++++
 distro_tracker/core/tests/tests_models.py | 22 ++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/distro_tracker/core/models.py b/distro_tracker/core/models.py
index eb43765..4ab27dd 100644
--- a/distro_tracker/core/models.py
+++ b/distro_tracker/core/models.py
@@ -952,6 +952,27 @@ class Repository(models.Model):
                 raise ValidationError(
                     "Only one repository can be set as the default")
 
+    def is_development_repository(self):
+        """Returns a boolean indicating whether the repository is used for
+        development.
+
+        A developement repository is a repository where new
+        versions of packages tend to be uploaded. The list of development
+        repositories can be provided in the list
+        DISTRO_TRACKER_DEVEL_REPOSITORIES (it should contain codenames and/or
+        suite names). If that setting does not exist, then the default
+        repository is assumed to be the only development repository.
+
+        :rtype: bool
+        """
+        if hasattr(settings, 'DISTRO_TRACKER_DEVEL_REPOSITORIES'):
+            for repo in settings.DISTRO_TRACKER_DEVEL_REPOSITORIES:
+                if self.codename == repo or self.suite == repo:
+                    return True
+        else:
+            return self.default
+        return False
+
 
 @python_2_unicode_compatible
 class ContributorName(models.Model):
diff --git a/distro_tracker/core/tests/tests_models.py b/distro_tracker/core/tests/tests_models.py
index ca4a7f7..ef64ab4 100644
--- a/distro_tracker/core/tests/tests_models.py
+++ b/distro_tracker/core/tests/tests_models.py
@@ -620,6 +620,12 @@ class RepositoryTests(TestCase):
             binary_package_name=self.bin_pkg_name,
             version='1.0.0',
             source_package=self.source_package)
+        self.repo1 = Repository.objects.create(
+            name='repo1', shorthand='repo1', codename='codename1',
+            suite='suite1')
+        self.repo2 = Repository.objects.create(
+            name='repo2', shorthand='repo2', codename='codename2',
+            suite='suite2')
 
     def test_add_source_entry_to_repository(self):
         """
@@ -783,6 +789,22 @@ class RepositoryTests(TestCase):
                 self.source_package.source_package_name.name),
             expected_entry)
 
+    def test_is_development_repository_default_case(self):
+        """We have not provided any explicit list of development repositories.
+        The default repository is the only development repository."""
+        self.assertTrue(self.repository.is_development_repository())
+        self.assertFalse(self.repo1.is_development_repository())
+        self.assertFalse(self.repo2.is_development_repository())
+
+    @override_settings(
+        DISTRO_TRACKER_DEVEL_REPOSITORIES=['suite1', 'codename2'])
+    def test_is_development_repository_explicit_list(self):
+        """We have provided an explicit list of development repositories. It
+        should be the reference."""
+        self.assertFalse(self.repository.is_development_repository())
+        self.assertTrue(self.repo1.is_development_repository())
+        self.assertTrue(self.repo2.is_development_repository())
+
 
 class SourcePackageTests(TestCase):
     fixtures = ['repository-test-fixture.json']
-- 
2.1.0



>From 3be7f31236e1a6023dfd1e97c52746c3e15c097b Mon Sep 17 00:00:00 2001
From: Sophie Brun <sophie@freexian.com>
Date: Fri, 12 Sep 2014 15:54:37 +0200
Subject: [PATCH 2/2] core: add a panel displaying a warning when the package
 is gone

Closes: #756741
---
 distro_tracker/core/panels.py                      | 37 ++++++++++++
 .../templates/core/panels/package-is-gone.html     | 23 ++++++++
 distro_tracker/core/tests/tests_panels.py          | 66 +++++++++++++++++++++-
 distro_tracker/project/settings/debian.py          |  6 ++
 4 files changed, 129 insertions(+), 3 deletions(-)
 create mode 100644 distro_tracker/core/templates/core/panels/package-is-gone.html

diff --git a/distro_tracker/core/panels.py b/distro_tracker/core/panels.py
index efd0878..057c19d 100644
--- a/distro_tracker/core/panels.py
+++ b/distro_tracker/core/panels.py
@@ -19,6 +19,7 @@ from distro_tracker.core.utils import get_vcs_name
 from distro_tracker.core.utils import get_or_none
 from distro_tracker import vendor
 from distro_tracker.core.models import SourcePackageName
+from distro_tracker.core.models import PseudoPackageName
 from distro_tracker.core.models import ActionItem
 from distro_tracker.core.models import PackageExtractedInfo
 from distro_tracker.core.models import MailingList
@@ -930,3 +931,39 @@ class ActionNeededPanel(BasePanel):
     @property
     def has_content(self):
         return bool(self.context['items'])
+
+
+class DeadPackageWarningPanel(BasePanel):
+    """
+    The panel displays a warning when the package has been dropped
+    from development repositories, and another one when the package no longer
+    exists in any repository.
+    """
+    title = 'package is gone'
+    template_name = 'core/panels/package-is-gone.html'
+    panel_importance = 9
+    position = 'center'
+
+    @property
+    def has_content(self):
+        if isinstance(self.package, SourcePackageName):
+            for repo in self.package.repositories:
+                if repo.is_development_repository():
+                    return False
+            return True
+        elif isinstance(self.package, PseudoPackageName):
+            return False
+        else:
+            return True
+
+    @cached_property
+    def context(self):
+        if isinstance(self.package, SourcePackageName):
+            disappeared = len(self.package.repositories) == 0
+        else:
+            disappeared = True
+        return {
+            'disappeared': disappeared,
+            'removals_url': getattr(settings, 'DISTRO_TRACKER_REMOVALS_URL',
+                                    ''),
+        }
diff --git a/distro_tracker/core/templates/core/panels/package-is-gone.html b/distro_tracker/core/templates/core/panels/package-is-gone.html
new file mode 100644
index 0000000..8938db1
--- /dev/null
+++ b/distro_tracker/core/templates/core/panels/package-is-gone.html
@@ -0,0 +1,23 @@
+{% extends 'core/panels/panel.html' %}
+
+{% block panel-body %}
+{% if panel.context.disappeared %}
+This package is not part of any {{ DISTRO_TRACKER_VENDOR_NAME }}
+distribution. Thus you won't find much information here. The package is
+either very new and hasn't appeared on mirrors yet, or it's an old package
+that eventually got removed. The old news are kept for historic purpose
+only.
+{% else %}
+This package is not in any development repository. This probably
+means that the package
+{% if panel.context.removals_url %}
+<a href="{{ panel.context.removals_url }}">has been removed</a>
+{% else %}
+has been removed
+{% endif %}
+(or has been renamed). Thus the information here is of little interest ...
+the package is going to disappear unless someone takes it over and
+reintroduces it.
+{% endif %}
+{% endblock %}
+
diff --git a/distro_tracker/core/tests/tests_panels.py b/distro_tracker/core/tests/tests_panels.py
index f02fa93..b56b3ff 100644
--- a/distro_tracker/core/tests/tests_panels.py
+++ b/distro_tracker/core/tests/tests_panels.py
@@ -14,12 +14,16 @@
 Tests for the Distro Tracker core panels.
 """
 from __future__ import unicode_literals
-from distro_tracker.test import TestCase
 from django.core.urlresolvers import reverse
+from bs4 import BeautifulSoup as soup
+
+from distro_tracker.test import TestCase
 from distro_tracker.core.models import SourcePackageName
+from distro_tracker.core.models import PseudoPackageName
+from distro_tracker.core.models import PackageName
 from distro_tracker.core.models import SourcePackage
-from distro_tracker.core.panels import VersionedLinks
-from bs4 import BeautifulSoup as soup
+from distro_tracker.core.models import Repository, SourcePackageRepositoryEntry
+from distro_tracker.core.panels import VersionedLinks, DeadPackageWarningPanel
 
 
 class VersionedLinksPanelTests(TestCase):
@@ -124,3 +128,59 @@ class GeneralInfoLinkPanelItemsTests(TestCase):
         response = self.get_package_page_response()
         self.assertTrue(self.get_general_info_link_panel(response))
         self.assertTrue(self.homepage_is_in_linkspanel(response))
+
+
+class DeadPackageWarningPanelTests(TestCase):
+    def setUp(self):
+        self.pkgname = SourcePackageName.objects.create(name='dummy-package')
+        self.srcpkg = SourcePackage.objects.create(
+            source_package_name=self.pkgname, version='1.0.0')
+        self.default_repo = \
+            Repository.objects.create(name='default', shorthand='default',
+                                      default=True)
+        self.repo1 = Repository.objects.create(name='repo1', shorthand='repo1')
+        self.panel = DeadPackageWarningPanel(self.pkgname, None)
+
+    def test_has_content_pkg_in_no_repository(self):
+        """The package is not in any repository. We should display the
+        warning."""
+        self.assertTrue(self.panel.has_content)
+
+    def test_has_content_pkg_not_in_devel_repos(self):
+        """The package is not in a development repository. We should display
+        the warning."""
+        SourcePackageRepositoryEntry.objects.create(
+            source_package=self.srcpkg, repository=self.repo1)
+        self.assertTrue(self.panel.has_content)
+
+    def test_has_content_pkg_in_devel_repos(self):
+        """The package is in at least one of the development repositories.
+        We should not display the warning."""
+        SourcePackageRepositoryEntry.objects.create(
+            source_package=self.srcpkg, repository=self.default_repo)
+        self.assertFalse(self.panel.has_content)
+
+    def test_has_content_for_pseudo_package(self):
+        """A pseudo-package is never obsolete. No warning displayed."""
+        pkgname = PseudoPackageName.objects.create(name='pseudo')
+        panel = DeadPackageWarningPanel(pkgname, None)
+
+        self.assertFalse(panel.has_content)
+
+    def test_has_content_for_old_packages(self):
+        """Old package only exists as PackageName. We should display the
+        warning in this case."""
+        pkgname = PackageName.objects.create(name='oldpkg')
+        panel = DeadPackageWarningPanel(pkgname, None)
+
+        self.assertTrue(panel.has_content)
+
+    def test_context_pkg_disappeared_completely(self):
+        """The package is not in any repository. The context exports this."""
+        self.assertTrue(self.panel.context['disappeared'])
+
+    def test_context_pkg_disappeared_from_devel_repository(self):
+        """The package is in a few repositories. The context exports this."""
+        SourcePackageRepositoryEntry.objects.create(
+            source_package=self.srcpkg, repository=self.repo1)
+        self.assertFalse(self.panel.context['disappeared'])
diff --git a/distro_tracker/project/settings/debian.py b/distro_tracker/project/settings/debian.py
index e80b5b7..2c36283 100644
--- a/distro_tracker/project/settings/debian.py
+++ b/distro_tracker/project/settings/debian.py
@@ -34,6 +34,12 @@ DISTRO_TRACKER_DEBIAN_PIUPARTS_SUITES = (
     'sid',
 )
 
+#: The page documenting package removals
+DISTRO_TRACKER_REMOVALS_URL = "https://ftp-master.debian.org/removals.txt";
+
+#: A list of the repositories where new versions are uploaded
+DISTRO_TRACKER_DEVEL_REPOSITORIES = ['unstable', 'experimental']
+
 # Various settings for sso.debian.org support
 _index_auth = MIDDLEWARE_CLASSES.index(
     'django.contrib.auth.middleware.AuthenticationMiddleware') + 1
-- 
2.1.0




Reply to: