Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/release-notes/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@ https://keepachangelog.com/en/1.1.0/
---

- **`4.0.0-B4` — a non-interactive install no longer removes a package it conflicts with because another package in the batch names itself.** Some AUR packages declare `provides` and `conflicts` on their own name (`cbonsai` does). sysforge read that as a drop-in replacing the installed copy and passed `--ask=4`, which pacman applies to every conflict question in the transaction. An `update` that rebuilt `cbonsai` alongside an unrelated conflicting package then removed the installed side without asking, instead of stopping. A package no longer counts as replacing itself, so only a real drop-in (`replaces`, or `conflicts` plus `provides` naming another installed package) gets the auto-confirm. Found by `45-interactive` in CI.

---

- **`4.0.0-B6` — `update --versions` reports a new repo kernel again when the kernel is renamed.** With `[kernel] source = "repo"` and a local name such as `pkgname = "linux-sysforge"`, sysforge looked up the renamed package in pacman's sync database, which only carries `linux`. The lookup found nothing and the kernel was left out, so a pending 7.2.9 → 7.2.11 never appeared in `update --versions` or in the reminder at the end of `update`. The check now falls back to the stock name the build records (`origin_pkgbase`), the same name `run kernel` already uses to pick which repo version to build.
13 changes: 11 additions & 2 deletions sysforge/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,9 @@ def _detect_stage_owned_updates(
# The walk's exclusion and the pin's lifecycle stay untouched —
# syncing stage-owned sources from `update` is exactly the
# double-processing the owner_stage skip exists to prevent.
hit = _stage_owned_repo_advisory(pkgbase, pkgnames, all_installed, owner)
hit = _stage_owned_repo_advisory(
pkgbase, pkgnames, all_installed, owner,
origin=entry.get("origin_pkgbase"))
if hit is not None:
installed_ver, candidate_ver = hit
advisories.append((pkgbase, installed_ver, candidate_ver, owner))
Expand All @@ -624,7 +626,7 @@ def _detect_stage_owned_updates(

def _stage_owned_repo_advisory(
pkgbase: str, pkgnames: list[str], all_installed: dict[str, str],
owner: str = "",
owner: str = "", origin: str | None = None,
) -> tuple[str, str] | None:
"""Sync-DB candidate for a stage-owned ``source = "repo"`` pkgbase.

Expand All @@ -633,6 +635,11 @@ def _stage_owned_repo_advisory(
unresolvable name, a package the sync DB does not know, or a vercmp
failure omits the advisory rather than raising — this path is advisory
only and must never fail an update run (3.0.0-B1).

``origin`` is the stock upstream base of a locally renamed build (the
kernel's ``linux`` → ``linux-sysforge``): the sync DB knows only that
name, so a miss on the renamed one retries it, as the repo pin does
(2.1.0-B12). Without it a renamed kernel never advised (4.0.0-B6).
"""
from sysforge.primitives.pacman import get_pacman_sync_version
from sysforge.primitives.version import vercmp
Expand All @@ -645,6 +652,8 @@ def _stage_owned_repo_advisory(
continue
try:
candidate_ver = get_pacman_sync_version(name)
if not candidate_ver and origin and origin != name:
candidate_ver = get_pacman_sync_version(origin)
except Exception: # noqa: S112 — advisory only, skip on probe failure
continue
if not candidate_ver:
Expand Down
4 changes: 2 additions & 2 deletions sysforge/update_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ def _check_one_pkgbase(
# For a coexist-renamed package the entry's ``pkgbase`` carries the
# renamed value (e.g. ``llvm-sysforge``), but the RPC cache is keyed by
# the stock upstream base — so fall back to ``origin_pkgbase`` when the
# renamed base misses. This is the sole read of origin_pkgbase in the
# update path; the rest of the correlation flows through pkgbuild_dir.
# renamed base misses. This is the per-pkgbase check's only read of
# origin_pkgbase; the rest of the correlation flows through pkgbuild_dir.
rpc_ver = rpc_version_by_base.get(pkgbase)
if not rpc_ver:
origin = entry.get("origin_pkgbase")
Expand Down
22 changes: 22 additions & 0 deletions tests/test_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,28 @@ def test_detect_stage_owned_repo_unknown_to_sync_db_is_silent(monkeypatch):
assert out == []


def test_detect_stage_owned_repo_renamed_kernel_queries_origin(monkeypatch):
"""4.0.0-B6: a repo-sourced kernel renamed locally (`linux` → `linux-sysforge`)
is unknown to the sync DB under its renamed name, so the advisory went
silent and `update --versions` hid a pending 7.2.9 → 7.2.11. Fall back to
``origin_pkgbase``, the name the repo pin itself queries (2.1.0-B12)."""
import sysforge.update as up
import sysforge.primitives.pacman as pac
sync_db = {"linux": "7.2.11.arch1-1"}
monkeypatch.setattr(pac, "get_pacman_sync_version", sync_db.get)

entry = {"owner_stage": "kernel", "source": "repo",
"pkgbase": "linux-sysforge", "origin_pkgbase": "linux"}
out = up._detect_stage_owned_updates(
{"linux-sysforge": dict(entry), "linux-sysforge-headers": dict(entry)},
all_installed={"linux-sysforge": "7.2.9.arch1-1",
"linux-sysforge-headers": "7.2.9.arch1-1"},
sync_failures={}, rpc_version_by_base={}, pacman_updates_map=None,
skip_sync_check=False, offline=False,
)
assert out == [("linux-sysforge", "7.2.9.arch1-1", "7.2.11.arch1-1", "kernel")]


def test_detect_stage_owned_aur_still_uses_rpc_path(monkeypatch):
"""3.0.0-B1 fixes the repo origin only: AUR-sourced stage-owned packages
get their upstream version from RPC without a sync, so they keep running
Expand Down
Loading