fix(routers.packages): fix related package metadata

Closes #218

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2021-12-21 18:02:37 -08:00
parent 5142447b7e
commit 50eec96dd0
No known key found for this signature in database
GPG key ID: F7E46DED420788F3
4 changed files with 59 additions and 34 deletions

View file

@ -9,30 +9,35 @@ from sqlalchemy import and_, orm
from aurweb import db, l10n, models, util
from aurweb.models.official_provider import OFFICIAL_BASE
from aurweb.models.package import Package
from aurweb.models.package_dependency import PackageDependency
from aurweb.models.relation_type import PROVIDES_ID
from aurweb.redis import redis_connection
from aurweb.scripts import notify
from aurweb.templates import register_filter
def dep_extra_with_arch(dep: models.PackageDependency, annotation: str) -> str:
output = [annotation]
if dep.DepArch:
output.append(dep.DepArch)
return f"({', '.join(output)})"
def dep_depends_extra(dep: models.PackageDependency) -> str:
""" A function used to produce extra text for dependency display. """
return str()
def dep_makedepends_extra(dep: models.PackageDependency) -> str:
""" A function used to produce extra text for dependency display. """
return "(make)"
return dep_extra_with_arch(dep, "make")
def dep_checkdepends_extra(dep: models.PackageDependency) -> str:
""" A function used to produce extra text for dependency display. """
return "(check)"
return dep_extra_with_arch(dep, "check")
def dep_optdepends_extra(dep: models.PackageDependency) -> str:
""" A function used to produce extra text for dependency display. """
return "(optional)"
return dep_extra_with_arch(dep, "optional")
@register_filter("dep_extra")
@ -304,3 +309,11 @@ def add_comaintainers(request: Request, pkgbase: models.PackageBase,
# Send out notifications.
util.apply_all(notifications, lambda n: n.send())
def pkg_required(pkgname: str, provides: List[str], limit: int):
targets = set(provides + [pkgname])
query = db.query(PackageDependency).join(Package).filter(
PackageDependency.DepName.in_(targets)
).order_by(Package.Name.asc()).limit(limit)
return query.all()

View file

@ -1,3 +1,4 @@
from collections import defaultdict
from datetime import datetime
from http import HTTPStatus
from typing import Any, Dict, List
@ -9,7 +10,7 @@ from sqlalchemy import and_, case
import aurweb.filters
import aurweb.packages.util
from aurweb import db, defaults, l10n, logging, models, util
from aurweb import config, db, defaults, l10n, logging, models, util
from aurweb.auth import auth_required, creds
from aurweb.exceptions import InvariantError, ValidationError
from aurweb.models.package_request import ACCEPTED_ID, PENDING_ID, REJECTED_ID
@ -196,6 +197,16 @@ async def package(request: Request, name: str) -> Response:
pkg = get_pkg_or_base(name, models.Package)
pkgbase = pkg.PackageBase
rels = pkg.package_relations.order_by(models.PackageRelation.RelName.asc())
rels_data = defaultdict(list)
for rel in rels:
if rel.RelTypeID == CONFLICTS_ID:
rels_data["c"].append(rel)
elif rel.RelTypeID == PROVIDES_ID:
rels_data["p"].append(rel)
elif rel.RelTypeID == REPLACES_ID:
rels_data["r"].append(rel)
# Add our base information.
context = await make_single_context(request, pkgbase)
context["package"] = pkg
@ -205,17 +216,14 @@ async def package(request: Request, name: str) -> Response:
models.PackageSource.Source.asc()).all()
# Package dependencies.
dependencies = db.query(models.PackageDependency).join(
models.Package).join(models.PackageBase).filter(
models.PackageBase.ID == pkgbase.ID)
context["dependencies"] = dependencies
max_depends = config.getint("options", "max_depends")
context["dependencies"] = pkg.package_dependencies.order_by(
models.PackageDependency.DepName.desc()
).limit(max_depends).all()
# Package requirements (other packages depend on this one).
required_by = db.query(models.PackageDependency).join(
models.Package).filter(
models.PackageDependency.DepName == pkgbase.Name).order_by(
models.Package.Name.asc())
context["required_by"] = required_by
context["required_by"] = pkgutil.pkg_required(
pkg.Name, [p.RelName for p in rels_data.get("p", [])], max_depends)
context["licenses"] = pkg.package_licenses

View file

@ -1,7 +1,7 @@
<div id="pkgdeps" class="listing">
<h3>Dependencies ({{ dependencies.count() }})</h3>
<h3>Dependencies ({{ dependencies | length }})</h3>
<ul id="pkgdepslist">
{% for dep in dependencies.all() %}
{% for dep in dependencies %}
<li>
{% set broken = not dep.is_package() %}
{% if broken %}
@ -16,10 +16,7 @@
</a>
{% endif %}
{{ dep.Package | provides_list(dep.DepName) | safe }}
{% if dep.DepArch %}
<em>({{ dep.DepArch }})</em>
{% endif %}
<!-- If this dependency type is an optdepends (id: 4). -->
{# If this dependency type is an optdepends (id: 4). #}
{% if dep.DepTypeID == 4 %}
<em>{{ dep | dep_extra_desc }}</em>
{% else %}
@ -31,14 +28,21 @@
</div>
<div id="pkgreqs" class="listing">
<h3>Required by ({{ required_by.count() }})</h3>
<h3>Required by ({{ required_by | length }})</h3>
<ul id="pkgreqslist">
{% for depender in required_by.all() %}
{% for dep in required_by %}
<li>
<a href="{{ depender.Package | package_link }}">
{{ depender.Package.Name }}
<a href="{{ dep.Package | package_link }}">
{{ dep.Package.Name }}
</a>
<em>{{ depender | dep_extra }}</em>
{% if dep.DepName != package.Name %}
<span class="virtual-dep">
({{ "requires %s" | tr | format(dep.DepName) }})
</span>
{% endif %}
<em>{{ dep | dep_extra }}</em>
</li>
{% endfor %}
</ul>

View file

@ -446,12 +446,12 @@ def test_package_dependencies(client: TestClient, maintainer: User,
with db.begin():
dep_pkg = create_package("test-dep-1", maintainer)
dep = create_package_dep(package, dep_pkg.Name)
dep.DepArch = "x86_64"
# Also, create a makedepends.
make_dep_pkg = create_package("test-dep-2", maintainer)
make_dep = create_package_dep(package, make_dep_pkg.Name,
dep_type_name="makedepends")
make_dep.DepArch = "x86_64"
# And... a checkdepends!
check_dep_pkg = create_package("test-dep-3", maintainer)
@ -496,13 +496,13 @@ def test_package_dependencies(client: TestClient, maintainer: User,
official_dep.DepName
]
pkgdeps = root.findall('.//ul[@id="pkgdepslist"]/li/a')
for i, expectation in enumerate(expected):
for i, expectation in enumerate(reversed(expected)):
assert pkgdeps[i].text.strip() == expectation
# Let's make sure the DepArch was displayed for our first dep.
arch = root.findall('.//ul[@id="pkgdepslist"]/li')[0]
arch = arch.xpath('./em')[1]
assert arch.text.strip() == "(x86_64)"
# Let's make sure the DepArch was displayed for our target make dep.
arch = root.findall('.//ul[@id="pkgdepslist"]/li')[-2]
arch = arch.xpath('./em')[0]
assert arch.text.strip() == "(make, x86_64)"
broken_node = root.find('.//ul[@id="pkgdepslist"]/li/span')
assert broken_node.text.strip() == broken_dep.DepName