Commit 2e0c3464 authored by Jan Tojnar's avatar Jan Tojnar
Browse files

maintainers/scripts/update.nix: Fix reverse toposort with independent packages



When updating GNOME packages in reverse topological order using the following command:

    nix-shell maintainers/scripts/update.nix --arg predicate '(path: pkg: builtins.any (team: team.shortName == "GNOME") pkg.meta.teams or [])' --argstr order reverse-topological

the `update.py` script would crash with `ValueError` on calling `ordered.index("adwaita-fonts")`.

This happened because the `adwaita-fonts` does not depend on any other GNOME package, nor it is depended upon by one.
As a result, it had been discarded by the `reverse_edges` function.

Co-authored-by: default avatarPhilip Taron <philip.taron@gmail.com>
parent 4b62180e
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
from graphlib import TopologicalSorter
from pathlib import Path
from typing import Any, Generator, Literal
from typing import Any, Final, Generator, Literal
import argparse
import asyncio
import contextlib
@@ -15,6 +15,11 @@ import tempfile
Order = Literal["arbitrary", "reverse-topological", "topological"]


FAKE_DEPENDENCY_FOR_INDEPENDENT_PACKAGES: Final[str] = (
    "::fake_dependency_for_independent_packages"
)


class CalledProcessError(Exception):
    process: asyncio.subprocess.Process
    stderr: bytes | None
@@ -116,10 +121,14 @@ def requisites_to_attrs(
def reverse_edges(graph: dict[str, set[str]]) -> dict[str, set[str]]:
    """
    Flips the edges of a directed graph.

    Packages without any dependency relation in the updated set
    will be added to `FAKE_DEPENDENCY_FOR_INDEPENDENT_PACKAGES` node.
    """

    reversed_graph: dict[str, set[str]] = {}
    for dependent, dependencies in graph.items():
        dependencies = dependencies or {FAKE_DEPENDENCY_FOR_INDEPENDENT_PACKAGES}
        for dependency in dependencies:
            reversed_graph.setdefault(dependency, set()).add(dependent)

@@ -413,6 +422,8 @@ async def populate_queue(
        ready_packages = list(sorter.get_ready())
        eprint(f"Enqueuing group of {len(ready_packages)} packages")
        for package in ready_packages:
            if package == FAKE_DEPENDENCY_FOR_INDEPENDENT_PACKAGES:
                continue
            await packages_to_update.put(attr_packages[package])
        await packages_to_update.join()
        sorter.done(*ready_packages)