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 <sop...@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 <sop...@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