[1/2] fix: only remove binary packages created by PN

Message ID 20261014155009.937200-1-felix.moessbauer@siemens.com
State New
Headers show
Series [1/2] fix: only remove binary packages created by PN | expand

Commit Message

Felix Moessbauer Oct. 14, 2026, 3:50 p.m. UTC
Cleaning the correct set of packages from isar-apt is surprisingly hard.
In fd0d030a we changed the cleanup logic to remove all binary packages
that are created by a single source package. This however broke the case
that multiple build variants (which use the same source package) are
built in a single run, hence each variant cleans all other generated
binary packages on do_deploy_deb. Having multiple builds of a single
variant is perfectly fine in Debian (e.g. independent builds of arch=all
and arch=any packages).

To fix this, we switch back to cleaning just the generated packages, but
we change the clean order on cleansstate: First run deb_clean to remove
the packages from the apt-cache, then run sstate clean to drop the
packages from the cache. Doing it the other way round would result in
the original error fixed in fd0d030a, by which the packages did not get
removed from isar-apt.

Fixes: fd0d030a ("fix(dpkg-build): clean isar-apt by source ...")
Reported-by: Kaba, Gamze Nur <gamzenur.kaba@siemens.com>
Signed-off-by: Felix Moessbauer <felix.moessbauer@siemens.com>
---
 meta/classes-recipe/dpkg-base.bbclass  | 36 ++++++++++++--------------
 meta/classes-recipe/repository.bbclass | 22 ----------------
 2 files changed, 17 insertions(+), 41 deletions(-)

Patch

diff --git a/meta/classes-recipe/dpkg-base.bbclass b/meta/classes-recipe/dpkg-base.bbclass
index b392211b..4ec0ddbe 100644
--- a/meta/classes-recipe/dpkg-base.bbclass
+++ b/meta/classes-recipe/dpkg-base.bbclass
@@ -229,24 +229,18 @@  python do_dpkg_build_setscene() {
 
 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)
+# Prepend, so that deb_clean() runs before sstate_cleanall(): the latter calls
+# sstate_clean() of do_dpkg_build, which empties DEPLOY_DIR_DEB.
+CLEANFUNCS =+ "deb_clean"
 
+# Remove by .deb file, so that only the binary packages of this very recipe are
+# dropped (instead of its variants)
 deb_clean() {
-    repo_del_by_source "${REPO_ISAR_DIR}"/"${DISTRO}" \
-        "${REPO_ISAR_DB_DIR}"/"${DISTRO}" "${DEBDISTRONAME}" \
-        "${BPN}" ${@deb_clean_archs(d)}
+    [ -d "${DEPLOY_DIR_DEB}" ] || return 0
+    for deb in $(find ${DEPLOY_DIR_DEB} -maxdepth 1 -name '*.deb'); do
+        repo_del_package "${REPO_ISAR_DIR}"/"${DISTRO}" \
+            "${REPO_ISAR_DB_DIR}"/"${DISTRO}" "${DEBDISTRONAME}" "${deb}"
+    done
 }
 # 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
@@ -255,8 +249,9 @@  do_clean[lockfiles] = "${REPO_ISAR_DIR}/isar.lock"
 do_clean[network] = "${TASK_USE_SUDO}"
 
 do_deploy_deb() {
-    # Removal is by source name and architecture (deb_clean), so a single scan
-    # of DEPLOY_DIR_DEB is only needed for the addition below.
+    # Scan DEPLOY_DIR_DEB once: the same list drives both the removal of the
+    # previous revisions of this recipe's own binary packages and the addition
+    # of the new ones.
     debs=$(find ${DEPLOY_DIR_DEB} -maxdepth 1 -name '*.deb')
     if [ -z "${debs}" ]; then
         # DEPLOY_DIR_DEB is shared by all multiconfigs with the same DISTRO and
@@ -267,7 +262,10 @@  do_deploy_deb() {
         bbnote "${DEPLOY_DIR_DEB} is empty, leaving isar-apt untouched"
         return
     fi
-    deb_clean
+    for deb in ${debs}; do
+        repo_del_package "${REPO_ISAR_DIR}"/"${DISTRO}" \
+            "${REPO_ISAR_DB_DIR}"/"${DISTRO}" "${DEBDISTRONAME}" "${deb}"
+    done
     repo_add_packages "${REPO_ISAR_DIR}"/"${DISTRO}" \
         "${REPO_ISAR_DB_DIR}"/"${DISTRO}" "${DEBDISTRONAME}" ${debs}
 }
diff --git a/meta/classes-recipe/repository.bbclass b/meta/classes-recipe/repository.bbclass
index b9097de5..1b6acd9b 100644
--- a/meta/classes-recipe/repository.bbclass
+++ b/meta/classes-recipe/repository.bbclass
@@ -129,28 +129,6 @@  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"