[2/4] fix(dpkg-build): clean isar-apt by source package and arch

Message ID 20260910140201.250854-3-felix.moessbauer@siemens.com
State New
Headers show
Series Fix various race conditions on multiconfig | expand

Commit Message

Felix Moessbauer Sept. 10, 2026, 2:01 p.m. UTC
deb_clean() removed the packages from isar-apt by iterating the .deb
files in DEPLOY_DIR_DEB. Since do_dpkg_build updates DEPLOY_DIR_DEB via
sstate, its sstate_clean() empties the directory before deb_clean() runs,
so the scan finds nothing and stale packages are left behind in isar-apt.

Remove the packages by their source package name and architecture
instead, using reprepro's removefilter. This no longer depends on the
.deb files being present, is idempotent, and also copes with binary
packages that were split off or renamed between builds.

Fixes: 1182a45b ("fix(dpkg-build): deploy debs via shared sstate dir")
Reported-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
---
 meta/classes-recipe/dpkg-base.bbclass  | 22 +++++++++++++++-------
 meta/classes-recipe/repository.bbclass | 22 ++++++++++++++++++++++
 2 files changed, 37 insertions(+), 7 deletions(-)

Patch

diff --git a/meta/classes-recipe/dpkg-base.bbclass b/meta/classes-recipe/dpkg-base.bbclass
index 164f247e..66f4d177 100644
--- a/meta/classes-recipe/dpkg-base.bbclass
+++ b/meta/classes-recipe/dpkg-base.bbclass
@@ -231,14 +231,22 @@  addtask dpkg_build_setscene
 
 CLEANFUNCS += "deb_clean"
 
+# Architectures under which this recipe's binary packages end up in the repo:
+# the concrete build arch (PACKAGE_ARCH resolves DPKG_ARCH=any), plus "all"
+# when this is the build that also produces the arch-independent packages.
+def deb_clean_archs(d):
+    dpkg_arch = d.getVar('DPKG_ARCH') or 'any'
+    package_arch = d.getVar('PACKAGE_ARCH')
+    host_arch = d.getVar('HOST_ARCH')
+    archs = [package_arch if dpkg_arch == 'any' else dpkg_arch]
+    if package_arch == host_arch and 'all' not in archs:
+        archs.append('all')
+    return ' '.join(a for a in archs if a)
+
 deb_clean() {
-    DEBS=$( find ${DEPLOY_DIR_DEB} -maxdepth 1 -name "*.deb" || [ ! -d ${S} ] )
-    if [ -n "${DEBS}" ]; then
-        for d in ${DEBS}; do
-            repo_del_package "${REPO_ISAR_DIR}"/"${DISTRO}" \
-                "${REPO_ISAR_DB_DIR}"/"${DISTRO}" "${DEBDISTRONAME}" "${d}"
-        done
-    fi
+    repo_del_by_source "${REPO_ISAR_DIR}"/"${DISTRO}" \
+        "${REPO_ISAR_DB_DIR}"/"${DISTRO}" "${DEBDISTRONAME}" \
+        "${BPN}" ${@deb_clean_archs(d)}
 }
 # the clean function modifies isar-apt. Do not add DEPLOY_DIR_DEB_LOCK here:
 # CLEANFUNCS also runs sstate_cleanall(), which takes that lock itself, and
diff --git a/meta/classes-recipe/repository.bbclass b/meta/classes-recipe/repository.bbclass
index a2061100..d255d1c8 100644
--- a/meta/classes-recipe/repository.bbclass
+++ b/meta/classes-recipe/repository.bbclass
@@ -129,6 +129,28 @@  repo_del_package() {
     repo_set_release_date "${dir}" "${codename}"
 }
 
+repo_del_by_source() {
+    local dir="$1"
+    local dbdir="$2"
+    local codename="$3"
+    local source="$4"
+    shift 4
+
+    if [ -n "${GNUPGHOME}" ]; then
+        export GNUPGHOME="${GNUPGHOME}"
+    fi
+    local arch_filter=""
+    local arch
+    for arch in "$@"; do
+        [ -n "${arch_filter}" ] && arch_filter="${arch_filter}|"
+        arch_filter="${arch_filter}Architecture (= ${arch})"
+    done
+    reprepro -b "${dir}" --dbdir "${dbdir}" -C main \
+        removefilter "${codename}" \
+        '$Source (= '"${source}"'), ('"${arch_filter}"'), $PackageType (= deb)'
+    repo_set_release_date "${dir}" "${codename}"
+}
+
 repo_contains_package() {
     local dir="$1"
     local dbdir="$2"