From 17ecaad8dd5416369507b373dbcd6bac97c3bc6d Mon Sep 17 00:00:00 2001 From: 14Do <138010054+14Do@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:27:20 +0100 Subject: [PATCH] sysupdate: skip the obsoleted packages in dnf output (#3525) dnf lists the packages an upgrade obsoletes indented beneath it, under a separate heading. Those rows are removals carrying their installed version, so they were parsed as upgrades from a version to itself and counted as pending. Skip indented rows. The heading is translated, so matching it would only work in English. --- core/internal/server/sysupdate/backend_dnf.go | 4 ++ .../server/sysupdate/backend_dnf_test.go | 39 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/core/internal/server/sysupdate/backend_dnf.go b/core/internal/server/sysupdate/backend_dnf.go index 34bb55bc2..d90f9aece 100644 --- a/core/internal/server/sysupdate/backend_dnf.go +++ b/core/internal/server/sysupdate/backend_dnf.go @@ -117,6 +117,10 @@ func parseDnfList(text, backendID string, installed map[string]string) []Package var pkgs []Package seen := make(map[string]struct{}) for line := range strings.SplitSeq(text, "\n") { + // indented rows are packages being obsoleted, which are removals rather than upgrades + if strings.HasPrefix(line, " ") || strings.HasPrefix(line, "\t") { + continue + } fields := strings.Fields(line) if len(fields) < 2 { continue diff --git a/core/internal/server/sysupdate/backend_dnf_test.go b/core/internal/server/sysupdate/backend_dnf_test.go index 5082292c5..2a381f3a6 100644 --- a/core/internal/server/sysupdate/backend_dnf_test.go +++ b/core/internal/server/sysupdate/backend_dnf_test.go @@ -81,6 +81,45 @@ kernel.x86_64 6.14.3-1.fc41 updates`, {Name: "kernel.x86_64", Repo: RepoSystem, Backend: "dnf5", FromVersion: "6.14.1-1.fc41", ToVersion: "6.14.3-1.fc41"}, }, }, + { + name: "skips the obsoleted packages listed under an upgrade", + input: `Upgrades +example-lib.x86_64 2.0.0-1.fc44 updates +example-app.noarch 3.1.0-1.fc44 updates + +Obsoleting packages +example-app.noarch 3.1.0-1.fc44 updates + example-app-old.noarch 3.0.0-1.fc44 updates + example-helper.x86_64 1.4.0-1.fc44 updates`, + backendID: "dnf5", + installed: map[string]string{ + "example-lib": "1.9.0-1.fc44", + "example-app": "3.0.0-1.fc44", + "example-app-old": "3.0.0-1.fc44", + "example-helper": "1.4.0-1.fc44", + }, + want: []Package{ + {Name: "example-lib.x86_64", Repo: RepoSystem, Backend: "dnf5", FromVersion: "1.9.0-1.fc44", ToVersion: "2.0.0-1.fc44"}, + {Name: "example-app.noarch", Repo: RepoSystem, Backend: "dnf5", FromVersion: "3.0.0-1.fc44", ToVersion: "3.1.0-1.fc44"}, + }, + }, + { + name: "skips obsoleted packages in dnf4 output, which has no upgrades heading", + input: `example-lib.x86_64 2.0.0-1.fc41 updates +Obsoleting Packages +example-app.noarch 3.1.0-1.fc41 updates + example-app-old.noarch 3.0.0-1.fc41 @updates`, + backendID: "dnf", + installed: map[string]string{ + "example-lib": "1.9.0-1.fc41", + "example-app": "3.0.0-1.fc41", + "example-app-old": "3.0.0-1.fc41", + }, + want: []Package{ + {Name: "example-lib.x86_64", Repo: RepoSystem, Backend: "dnf", FromVersion: "1.9.0-1.fc41", ToVersion: "2.0.0-1.fc41"}, + {Name: "example-app.noarch", Repo: RepoSystem, Backend: "dnf", FromVersion: "3.0.0-1.fc41", ToVersion: "3.1.0-1.fc41"}, + }, + }, { name: "skips dnf5 banner / column header lines", input: `Updates available