fix: handle broken packages which have valid provides

Closes #226

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2021-12-30 19:11:21 -08:00
parent 6fdaeee026
commit be7a96076e
No known key found for this signature in database
GPG key ID: F7E46DED420788F3
3 changed files with 50 additions and 27 deletions

View file

@ -1,3 +1,6 @@
from typing import List
from sqlalchemy import and_, literal
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import backref, relationship from sqlalchemy.orm import backref, relationship
@ -6,6 +9,7 @@ from aurweb.models.declarative import Base
from aurweb.models.dependency_type import DependencyType as _DependencyType from aurweb.models.dependency_type import DependencyType as _DependencyType
from aurweb.models.official_provider import OfficialProvider as _OfficialProvider from aurweb.models.official_provider import OfficialProvider as _OfficialProvider
from aurweb.models.package import Package as _Package from aurweb.models.package import Package as _Package
from aurweb.models.package_relation import PackageRelation
class PackageDependency(Base): class PackageDependency(Base):
@ -51,3 +55,24 @@ class PackageDependency(Base):
official = db.query(_OfficialProvider).filter( official = db.query(_OfficialProvider).filter(
_OfficialProvider.Name == self.DepName).exists() _OfficialProvider.Name == self.DepName).exists()
return db.query(pkg).scalar() or db.query(official).scalar() return db.query(pkg).scalar() or db.query(official).scalar()
def provides(self) -> List[PackageRelation]:
from aurweb.models.relation_type import PROVIDES_ID
rels = db.query(PackageRelation).join(_Package).filter(
and_(PackageRelation.RelTypeID == PROVIDES_ID,
PackageRelation.RelName == self.DepName)
).with_entities(
_Package.Name,
literal(False).label("is_official")
).order_by(_Package.Name.asc())
official_rels = db.query(_OfficialProvider).filter(
and_(_OfficialProvider.Provides == self.DepName,
_OfficialProvider.Name != self.DepName)
).with_entities(
_OfficialProvider.Name,
literal(True).label("is_official")
).order_by(_OfficialProvider.Name.asc())
return rels.union(official_rels).all()

View file

@ -5,18 +5,20 @@ from typing import Dict, List, Union
import orjson import orjson
from fastapi import HTTPException, Request from fastapi import HTTPException, Request
from sqlalchemy import and_, orm from sqlalchemy import orm
from aurweb import db, l10n, models, util from aurweb import db, l10n, models, util
from aurweb.models import Package, PackageBase, User from aurweb.models import Package, PackageBase, User
from aurweb.models.official_provider import OFFICIAL_BASE, OfficialProvider from aurweb.models.official_provider import OFFICIAL_BASE, OfficialProvider
from aurweb.models.package_comaintainer import PackageComaintainer from aurweb.models.package_comaintainer import PackageComaintainer
from aurweb.models.package_dependency import PackageDependency from aurweb.models.package_dependency import PackageDependency
from aurweb.models.relation_type import PROVIDES_ID from aurweb.models.package_relation import PackageRelation
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
Providers = List[Union[PackageRelation, OfficialProvider]]
def dep_extra_with_arch(dep: models.PackageDependency, annotation: str) -> str: def dep_extra_with_arch(dep: models.PackageDependency, annotation: str) -> str:
output = [annotation] output = [annotation]
@ -77,27 +79,13 @@ def package_link(package: Union[Package, OfficialProvider]) -> str:
return f"/packages/{package.Name}" return f"/packages/{package.Name}"
@register_filter("provides_list") @register_filter("provides_markup")
def provides_list(package: models.Package, depname: str) -> list: def provides_markup(provides: Providers) -> str:
providers = db.query(models.Package).join( return ", ".join([
models.PackageRelation).join(models.RelationType).filter(
and_(
models.PackageRelation.RelName == depname,
models.RelationType.ID == PROVIDES_ID
)
)
string = ", ".join([
f'<a href="{package_link(pkg)}">{pkg.Name}</a>' f'<a href="{package_link(pkg)}">{pkg.Name}</a>'
for pkg in providers for pkg in provides
]) ])
if string:
# If we actually constructed a string, wrap it.
string = f"<em>({string})</em>"
return string
def get_pkg_or_base( def get_pkg_or_base(
name: str, name: str,

View file

@ -1,23 +1,33 @@
<div id="pkgdeps" class="listing"> <div id="pkgdeps" class="listing">
<h3>Dependencies ({{ dependencies | length }})</h3> <h3>{{ "Dependencies" | tr }} ({{ dependencies | length }})</h3>
<ul id="pkgdepslist"> <ul id="pkgdepslist">
{% for dep in dependencies %} {% for dep in dependencies %}
{# Collect provides for `dep`. #}
{% set provides = dep.provides() %}
<li> <li>
{% set broken = not dep.is_package() %} {% set broken = not dep.is_package() %}
{% if broken %} {% if broken %}
{% if not provides %}
<span class="broken"> <span class="broken">
{% endif %}
{% else %} {% else %}
<a href="{{ dep.DepName | pkgname_link }}"> <a href="{{ dep.DepName | pkgname_link }}">
{% endif %} {% endif %}
{{ dep.DepName }} {{ dep.DepName }}
{% if broken %} {% if broken %}
{% if not provides %}
</span> </span>
{% endif %}
{% else %} {% else %}
</a> </a>
{% endif %} {% endif %}
{{ dep.Package | provides_list(dep.DepName) | safe }}
{# If this dependency type is an optdepends (id: 4). #} {% if provides %}
<em>({{ provides | provides_markup | safe }})</em>
{% endif %}
{% if dep.DepTypeID == 4 %} {% if dep.DepTypeID == 4 %}
{# If this dependency type is an optdepends (id: 4). #}
<em>{{ dep | dep_extra_desc }}</em> <em>{{ dep | dep_extra_desc }}</em>
{% else %} {% else %}
<em>{{ dep | dep_extra }}</em> <em>{{ dep | dep_extra }}</em>
@ -28,7 +38,7 @@
</div> </div>
<div id="pkgreqs" class="listing"> <div id="pkgreqs" class="listing">
<h3>Required by ({{ required_by | length }})</h3> <h3>{{ "Required by" | tr }} ({{ required_by | length }})</h3>
<ul id="pkgreqslist"> <ul id="pkgreqslist">
{% for dep in required_by %} {% for dep in required_by %}
<li> <li>
@ -49,7 +59,7 @@
</div> </div>
<div id="pkgfiles" class="listing"> <div id="pkgfiles" class="listing">
<h3>Sources ({{ sources | length }})</h3> <h3>{{ "Sources" | tr }} ({{ sources | length }})</h3>
</div> </div>
<div> <div>