diff options
author | Dan McGee <dan@archlinux.org> | 2012-07-23 09:45:44 -0500 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2012-07-23 09:55:46 -0500 |
commit | 946d90d08f29094153142056a1778cd595e568a3 (patch) | |
tree | a01ce81fd31d617aec5d4f962e976fe44a3462cf | |
parent | 872d4bcaa2ce85d2d319a1146e0fc05ab6808eb9 (diff) |
Add '410 Gone' support for packages moved out of repositories
This allows us to do better than a generic 404 handler when we know a
package previously existed in a given repository, and should also make
things a bit nicer when getting sent in from a search engine to a page
that no longer exists.
Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r-- | packages/models.py | 3 | ||||
-rw-r--r-- | packages/views/display.py | 46 | ||||
-rw-r--r-- | templates/packages/removed.html | 28 |
3 files changed, 72 insertions, 5 deletions
diff --git a/packages/models.py b/packages/models.py index 45ff3c08..18a62a3c 100644 --- a/packages/models.py +++ b/packages/models.py @@ -297,6 +297,9 @@ class Update(models.Model): return u'%d:%s-%s' % (self.new_epoch, self.new_pkgver, self.new_pkgrel) return u'%s-%s' % (self.new_pkgver, self.new_pkgrel) + def elsewhere(self): + return Package.objects.filter(pkgname=self.pkgname, arch=self.arch) + def __unicode__(self): return u'%s of %s on %s' % (self.get_action_flag_display(), self.pkgname, self.created) diff --git a/packages/views/display.py b/packages/views/display.py index dd57571a..5332dc13 100644 --- a/packages/views/display.py +++ b/packages/views/display.py @@ -1,18 +1,21 @@ +import datetime import json from string import Template from urllib import urlencode from django.http import HttpResponse, Http404 -from django.shortcuts import get_object_or_404, redirect +from django.shortcuts import get_object_or_404, redirect, render +from django.utils.timezone import now from django.views.generic.simple import direct_to_template from django.views.decorators.vary import vary_on_headers from main.models import Package, PackageFile, Arch, Repo from mirrors.utils import get_mirror_url_for_download +from ..models import Update from ..utils import get_group_info, PackageJSONEncoder -def split_package_details(request, name='', repo='', arch=''): +def split_package_details(request, name, repo, arch): arch = get_object_or_404(Arch, name=arch) arches = [ arch ] arches.extend(Arch.objects.filter(agnostic=True)) @@ -21,10 +24,10 @@ def split_package_details(request, name='', repo='', arch=''): repo__testing=repo.testing, repo__staging=repo.staging, arch__in=arches).order_by('pkgname') if len(pkgs) == 0: - raise Http404 + return None # we have packages, but ensure at least one is in the given repo if not any(True for pkg in pkgs if pkg.repo == repo): - raise Http404 + return None context = { 'list_title': 'Split Package Details', 'name': name, @@ -35,6 +38,30 @@ def split_package_details(request, name='', repo='', arch=''): context) +CUTOFF = datetime.timedelta(days=60) + + +def recently_removed_package(request, name, repo, arch, cutoff=CUTOFF): + '''We're just steps away from raising a 404, but check our packages update + table first to see if this package has existed in this repo before. If so, + we can show a 410 Gone page and point the requester in the right + direction.''' + arch = get_object_or_404(Arch, name=arch) + arches = [ arch ] + arches.extend(Arch.objects.filter(agnostic=True)) + match = Update.objects.select_related('arch', 'repo').filter( + pkgname=name, repo__name__iexact=repo, arch__in=arches) + if cutoff is not None: + when = now() - cutoff + match = match.filter(created__gte=when) + try: + match = match.latest() + return render(request, 'packages/removed.html', + {'update': match, }, status=410) + except Update.DoesNotExist: + return None + + def details(request, name='', repo='', arch=''): if all([name, repo, arch]): try: @@ -54,7 +81,16 @@ def details(request, name='', repo='', arch=''): repo__name__iexact=repo, arch__agnostic=True) if len(pkgs) == 1: return redirect(pkgs[0], permanent=True) - return split_package_details(request, name, repo, arch) + # do we have a split package matching this criteria? + ret = split_package_details(request, name, repo, arch) + if ret is None: + # maybe we have a recently-removed package? + ret = recently_removed_package(request, name, repo, arch) + if ret is not None: + return ret + else: + # we've tried everything at this point, nothing to see + raise Http404 else: pkg_data = [ ('arch', arch.lower()), diff --git a/templates/packages/removed.html b/templates/packages/removed.html new file mode 100644 index 00000000..17b1f989 --- /dev/null +++ b/templates/packages/removed.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} +{% load url from future %} +{% load package_extras %} + +{% block title %}Arch Linux - Not Available - {{ update.pkgname }} {{ update.old_version }} ({{ update.arch.name }}){% endblock %} +{% block navbarclass %}anb-packages{% endblock %} + +{% block content %} +<div id="pkg-gone" class="box"> + <h2>{{ update.pkgname }} {{ update.old_version }} is no longer available</h2> + + <p>{{ update.pkgname }} {{ update.old_version }} has been removed from the [{{ update.repo.name|lower }}] repository.</p> + + {% with update.elsewhere as elsewhere %}{% if elsewhere %} + <p>However, this package is available in other repositories:</p> + <ul> + {% for pkg in elsewhere %} + <li>{% pkg_details_link pkg %} {{ pkg.full_version }} [{{ pkg.repo.name|lower }}] ({{ pkg.arch.name }})</li> + {% endfor %} + </ul> + {% else %} + <p>Unfortunately, this package cannot be found in any other repositories. + Try using the <a href="{% url 'packages-search' %}?name={{ update.pkgname|urlencode }}">package search page</a>, + or try <a href="https://aur.archlinux.org/packages.php?K={{ update.pkgname|urlencode }}">searching the AUR</a> + to see if the package can be found there.</p> + {% endif %}{% endwith %} +</div> +{% endblock %} |