diff --git a/README.md b/README.md
index 69de8329..253f5c7c 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,7 @@ probably want the following:
uv run ./manage.py loaddata devel/fixtures/*.json
uv run ./manage.py loaddata mirrors/fixtures/*.json
uv run ./manage.py loaddata releng/fixtures/*.json
+ uv run ./manage.py loaddata todolists/fixtures/*.json
7. Use the following commands to start a service instance
uv run ./manage.py runserver
diff --git a/templates/todolists/view.html b/templates/todolists/view.html
index 5b08ab47..26ff6549 100644
--- a/templates/todolists/view.html
+++ b/templates/todolists/view.html
@@ -75,6 +75,7 @@
Filter Todo List Packages
Name |
Current Version |
Staging Version |
+ Testing Version |
Maintainers |
Status |
Last Touched By |
@@ -96,6 +97,9 @@ Filter Todo List Packages
{% with staging=pkg.staging %}
{% if staging %}{% pkg_details_link staging staging.full_version %}{% endif %} |
{% endwith %}
+ {% with testing=pkg.testing %}
+ {% if testing %}{% pkg_details_link testing testing.full_version %}{% endif %} |
+ {% endwith %}
{{ pkg.maintainers|join:', ' }} |
{% if perms.todolists.change_todolistpackage %}
diff --git a/todolists/fixtures/todolist.json b/todolists/fixtures/todolist.json
new file mode 100644
index 00000000..9802f097
--- /dev/null
+++ b/todolists/fixtures/todolist.json
@@ -0,0 +1,158 @@
+[
+ {
+ "model": "auth.user",
+ "pk": 1,
+ "fields": {
+ "username": "developer",
+ "first_name": "Test",
+ "last_name": "Developer",
+ "email": "developer@archlinux.org",
+ "password": "pbkdf2_sha256$1000000$5mOVHaWggfkqKGsKsVpWH8$kS2tNunBSv+rrDohZXeuP9L/kX8oDe09vzab+m3WQXo=",
+ "is_staff": true,
+ "is_active": true,
+ "is_superuser": true,
+ "date_joined": "2024-01-01T00:00:00Z",
+ "last_login": null,
+ "groups": [],
+ "user_permissions": []
+ }
+ },
+ {
+ "model": "main.package",
+ "pk": 6,
+ "fields": {
+ "repo": 3,
+ "arch": 3,
+ "pkgname": "linux",
+ "pkgbase": "linux",
+ "pkgver": "6.9.1",
+ "pkgrel": "2",
+ "epoch": 0,
+ "pkgdesc": "The Linux kernel and modules",
+ "url": "https://www.kernel.org/",
+ "filename": "linux-6.9.1-2-x86_64.pkg.tar.zst",
+ "compressed_size": 72000000,
+ "installed_size": 91000000,
+ "build_date": "2024-05-20T10:00:00Z",
+ "last_update": "2024-05-20T10:00:00Z",
+ "files_last_update": null,
+ "created": "2024-05-20T10:00:00Z",
+ "packager_str": "Test Developer ",
+ "packager": null,
+ "signature_bytes": null,
+ "flag_date": null
+ }
+ },
+ {
+ "model": "main.package",
+ "pk": 7,
+ "fields": {
+ "repo": 16,
+ "arch": 3,
+ "pkgname": "systemd",
+ "pkgbase": "systemd",
+ "pkgver": "256.1",
+ "pkgrel": "1",
+ "epoch": 0,
+ "pkgdesc": "system and service manager",
+ "url": "https://www.github.com/systemd/systemd",
+ "filename": "systemd-256.1-1-x86_64.pkg.tar.zst",
+ "compressed_size": 4100000,
+ "installed_size": 19000000,
+ "build_date": "2024-05-22T08:00:00Z",
+ "last_update": "2024-05-22T08:00:00Z",
+ "files_last_update": null,
+ "created": "2024-05-22T08:00:00Z",
+ "packager_str": "Test Developer ",
+ "packager": null,
+ "signature_bytes": null,
+ "flag_date": null
+ }
+ },
+ {
+ "model": "todolists.todolist",
+ "pk": 1,
+ "fields": {
+ "slug": "glibc-2-40-rebuild",
+ "name": "glibc 2.40 rebuild",
+ "description": "Rebuild of packages affected by the glibc 2.40 soname bump.",
+ "creator": 1,
+ "created": "2024-05-20T09:00:00Z",
+ "kind": 0,
+ "last_modified": "2024-05-22T08:00:00Z",
+ "raw": "linux\ncoreutils\npacman\nsystemd"
+ }
+ },
+ {
+ "model": "todolists.todolistpackage",
+ "pk": 1,
+ "fields": {
+ "todolist": 1,
+ "pkg": 1,
+ "pkgname": "linux",
+ "pkgbase": "linux",
+ "arch": 3,
+ "repo": 1,
+ "created": "2024-05-20T09:00:00Z",
+ "last_modified": "2024-05-20T09:00:00Z",
+ "removed": null,
+ "status": 0,
+ "user": null,
+ "comments": null
+ }
+ },
+ {
+ "model": "todolists.todolistpackage",
+ "pk": 2,
+ "fields": {
+ "todolist": 1,
+ "pkg": 2,
+ "pkgname": "coreutils",
+ "pkgbase": "coreutils",
+ "arch": 3,
+ "repo": 1,
+ "created": "2024-05-20T09:00:00Z",
+ "last_modified": "2024-05-21T14:30:00Z",
+ "removed": null,
+ "status": 1,
+ "user": 1,
+ "comments": null
+ }
+ },
+ {
+ "model": "todolists.todolistpackage",
+ "pk": 3,
+ "fields": {
+ "todolist": 1,
+ "pkg": 4,
+ "pkgname": "pacman",
+ "pkgbase": "pacman",
+ "arch": 3,
+ "repo": 1,
+ "created": "2024-05-20T09:00:00Z",
+ "last_modified": "2024-05-22T10:00:00Z",
+ "removed": null,
+ "status": 2,
+ "user": 1,
+ "comments": null
+ }
+ },
+ {
+ "model": "todolists.todolistpackage",
+ "pk": 4,
+ "fields": {
+ "todolist": 1,
+ "pkg": 5,
+ "pkgname": "systemd",
+ "pkgbase": "systemd",
+ "arch": 3,
+ "repo": 1,
+ "created": "2024-05-20T09:00:00Z",
+ "last_modified": "2024-05-20T09:00:00Z",
+ "removed": null,
+ "status": 0,
+ "user": null,
+ "comments": null
+ }
+ }
+]
diff --git a/todolists/tests/test_utils.py b/todolists/tests/test_utils.py
new file mode 100644
index 00000000..0f84dcfe
--- /dev/null
+++ b/todolists/tests/test_utils.py
@@ -0,0 +1,103 @@
+import pytest
+from django.utils.timezone import now
+
+from main.models import Package, Repo
+from todolists.models import TodolistPackage
+from todolists.utils import attach_staging, attach_testing
+
+
+def make_package(pkgname, repo, arch):
+ return Package.objects.create(
+ pkgname=pkgname,
+ pkgbase=pkgname,
+ pkgver='1.0',
+ pkgrel='1',
+ epoch=0,
+ pkgdesc='Test package',
+ url='https://example.com',
+ filename=f'{pkgname}-1.0-1-x86_64.pkg.tar.zst',
+ compressed_size=1000,
+ installed_size=2000,
+ build_date=now(),
+ last_update=now(),
+ created=now(),
+ packager_str='Test Packager',
+ repo=repo,
+ arch=arch,
+ )
+
+
+@pytest.fixture
+def stable_pkg(repos, package):
+ return Package.objects.get(pkgname='linux')
+
+
+@pytest.fixture
+def todolist_with_linux(todolist, stable_pkg, user):
+ arch = stable_pkg.arch
+ repo = stable_pkg.repo
+ tlpkg = TodolistPackage.objects.create(
+ todolist=todolist,
+ pkg=stable_pkg,
+ pkgname=stable_pkg.pkgname,
+ pkgbase=stable_pkg.pkgbase,
+ arch=arch,
+ repo=repo,
+ user=user,
+ )
+ yield todolist
+ tlpkg.delete()
+
+
+def test_attach_testing_no_testing_pkg(todolist_with_linux):
+ todolist = todolist_with_linux
+ attach_testing(todolist.packages(), todolist.pk)
+ for pkg in todolist.packages():
+ assert pkg.testing is None
+
+
+def test_attach_testing_finds_testing_pkg(todolist_with_linux):
+ todolist = todolist_with_linux
+ stable_pkg = Package.objects.get(pkgname='linux', repo__testing=False, repo__staging=False)
+ testing_repo = Repo.objects.get(name='Core-Testing')
+
+ testing_pkg = make_package('linux', testing_repo, stable_pkg.arch)
+ try:
+ attach_testing(todolist.packages(), todolist.pk)
+ for pkg in todolist.packages():
+ if pkg.pkgname == 'linux':
+ assert pkg.testing is not None
+ assert pkg.testing.repo.testing is True
+ finally:
+ testing_pkg.delete()
+
+
+def test_attach_testing_ignores_staging_repos(todolist_with_linux):
+ todolist = todolist_with_linux
+ stable_pkg = Package.objects.get(pkgname='linux', repo__testing=False, repo__staging=False)
+ staging_repo = Repo.objects.get(name='Core-Staging')
+
+ staging_pkg = make_package('linux', staging_repo, stable_pkg.arch)
+ try:
+ attach_testing(todolist.packages(), todolist.pk)
+ for pkg in todolist.packages():
+ if pkg.pkgname == 'linux':
+ assert pkg.testing is None
+ finally:
+ staging_pkg.delete()
+
+
+def test_attach_staging_still_works(todolist_with_linux):
+ todolist = todolist_with_linux
+ stable_pkg = Package.objects.get(pkgname='linux', repo__testing=False, repo__staging=False)
+ staging_repo = Repo.objects.get(name='Core-Staging')
+
+ staging_pkg = make_package('linux', staging_repo, stable_pkg.arch)
+ try:
+ attach_staging(todolist.packages(), todolist.pk)
+ for pkg in todolist.packages():
+ if pkg.pkgname == 'linux':
+ assert pkg.staging is not None
+ assert pkg.staging.repo.staging is True
+ finally:
+ staging_pkg.delete()
diff --git a/todolists/utils.py b/todolists/utils.py
index eee4c07d..11836500 100644
--- a/todolists/utils.py
+++ b/todolists/utils.py
@@ -39,21 +39,34 @@ def get_annotated_todolists(incomplete_only=False):
return lists
-def attach_staging(packages, list_id):
- '''Look for any staging version of the packages provided and attach them
- to the 'staging' attribute on each package if found.'''
+def _attach_repo_version(packages, list_id, kind):
+ '''Look for related packages in repos flagged by kind and attach them.
+
+ kind is a Repo boolean field name used as repo__{kind}=True. Only
+ 'staging' and 'testing' are used; they set package.staging or
+ package.testing for the todolist templates.
+ '''
pkgnames = TodolistPackage.objects.filter(
todolist_id=list_id).values('pkgname')
- staging_pkgs = Package.objects.normal().filter(repo__staging=True,
- pkgname__in=pkgnames)
- # now build a lookup dict to attach to the correct package
- lookup = {(p.pkgname, p.arch): p for p in staging_pkgs}
+ related_pkgs = Package.objects.normal().filter(
+ **{f'repo__{kind}': True},
+ pkgname__in=pkgnames,
+ )
+ lookup = {(p.pkgname, p.arch): p for p in related_pkgs}
- annotated = []
for package in packages:
- in_staging = lookup.get((package.pkgname, package.arch), None)
- package.staging = in_staging
+ setattr(package, kind, lookup.get((package.pkgname, package.arch)))
+
+
+def attach_staging(packages, list_id):
+ '''Look for any staging version of the packages provided and attach them
+ to the 'staging' attribute on each package if found.'''
+ _attach_repo_version(packages, list_id, 'staging')
+
- return annotated
+def attach_testing(packages, list_id):
+ '''Look for any testing version of the packages provided and attach them
+ to the 'testing' attribute on each package if found.'''
+ _attach_repo_version(packages, list_id, 'testing')
# vim: set ts=4 sw=4 et:
diff --git a/todolists/views.py b/todolists/views.py
index 5009ff23..d51c177e 100644
--- a/todolists/views.py
+++ b/todolists/views.py
@@ -16,7 +16,7 @@
from packages.utils import PackageJSONEncoder, attach_maintainers
from .models import Todolist, TodolistPackage
-from .utils import attach_staging, get_annotated_todolists
+from .utils import attach_staging, attach_testing, get_annotated_todolists
class TodoListForm(forms.ModelForm):
@@ -65,6 +65,7 @@ def view(request, slug):
# so accessing maintainers in the template is now cheap
attach_maintainers(todolist.packages())
attach_staging(todolist.packages(), todolist.pk)
+ attach_testing(todolist.packages(), todolist.pk)
arches = {tp.arch for tp in todolist.packages()}
repos = {tp.repo for tp in todolist.packages()}
context = {
|