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 import db, l10n, models, util
from aurweb.models.official_provider import OFFICIAL_BASE 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.models.relation_type import PROVIDES_ID
from aurweb.redis import redis_connection from aurweb.redis import redis_connection
from aurweb.scripts import notify from aurweb.scripts import notify
from aurweb.templates import register_filter 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: def dep_depends_extra(dep: models.PackageDependency) -> str:
""" A function used to produce extra text for dependency display. """
return str() return str()
def dep_makedepends_extra(dep: models.PackageDependency) -> str: def dep_makedepends_extra(dep: models.PackageDependency) -> str:
""" A function used to produce extra text for dependency display. """ return dep_extra_with_arch(dep, "make")
return "(make)"
def dep_checkdepends_extra(dep: models.PackageDependency) -> str: def dep_checkdepends_extra(dep: models.PackageDependency) -> str:
""" A function used to produce extra text for dependency display. """ return dep_extra_with_arch(dep, "check")
return "(check)"
def dep_optdepends_extra(dep: models.PackageDependency) -> str: def dep_optdepends_extra(dep: models.PackageDependency) -> str:
""" A function used to produce extra text for dependency display. """ return dep_extra_with_arch(dep, "optional")
return "(optional)"
@register_filter("dep_extra") @register_filter("dep_extra")
@ -304,3 +309,11 @@ def add_comaintainers(request: Request, pkgbase: models.PackageBase,
# Send out notifications. # Send out notifications.
util.apply_all(notifications, lambda n: n.send()) 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 datetime import datetime
from http import HTTPStatus from http import HTTPStatus
from typing import Any, Dict, List from typing import Any, Dict, List
@ -9,7 +10,7 @@ from sqlalchemy import and_, case
import aurweb.filters import aurweb.filters
import aurweb.packages.util 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.auth import auth_required, creds
from aurweb.exceptions import InvariantError, ValidationError from aurweb.exceptions import InvariantError, ValidationError
from aurweb.models.package_request import ACCEPTED_ID, PENDING_ID, REJECTED_ID 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) pkg = get_pkg_or_base(name, models.Package)
pkgbase = pkg.PackageBase 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. # Add our base information.
context = await make_single_context(request, pkgbase) context = await make_single_context(request, pkgbase)
context["package"] = pkg context["package"] = pkg
@ -205,17 +216,14 @@ async def package(request: Request, name: str) -> Response:
models.PackageSource.Source.asc()).all() models.PackageSource.Source.asc()).all()
# Package dependencies. # Package dependencies.
dependencies = db.query(models.PackageDependency).join( max_depends = config.getint("options", "max_depends")
models.Package).join(models.PackageBase).filter( context["dependencies"] = pkg.package_dependencies.order_by(
models.PackageBase.ID == pkgbase.ID) models.PackageDependency.DepName.desc()
context["dependencies"] = dependencies ).limit(max_depends).all()
# Package requirements (other packages depend on this one). # Package requirements (other packages depend on this one).
required_by = db.query(models.PackageDependency).join( context["required_by"] = pkgutil.pkg_required(
models.Package).filter( pkg.Name, [p.RelName for p in rels_data.get("p", [])], max_depends)
models.PackageDependency.DepName == pkgbase.Name).order_by(
models.Package.Name.asc())
context["required_by"] = required_by
context["licenses"] = pkg.package_licenses context["licenses"] = pkg.package_licenses

View file

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

View file

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