[projects/pld-builder.new] Rework PHP version handling: repo-based detection, chroot cleanup, split concerns
arekm
arekm at pld-linux.org
Wed Apr 15 22:43:16 CEST 2026
commit 859f89b844a5e817445563c32c6c83efcf700e52
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Wed Apr 15 22:42:08 2026 +0200
Rework PHP version handling: repo-based detection, chroot cleanup, split concerns
Replace rpm --eval '%{php_name}' with poldek repo queries for PHP
version detection. The macro resolves via php-config --sysconfdir
which reflects whatever PHP is currently installed in the chroot,
not what should be installed — on a dirty chroot with php53, it
would return 'php53' and keep the wrong version.
Instead, discover phpNN-program packages from the repo via poldek
(with network access) and cache the result per build.
Split the ignore mechanism into two concerns:
cleanup_patterns() — what to remove from the dirty chroot before
checking BRs. When -D php_suffix is set, removes all PHP except
that version. Without php_suffix, removes ALL versioned PHP
(clean slate) so poldek resolves from scratch using its EVR
tiebreaker and the spec's version constraints.
ignore_patterns() — what to pass as --ignore to poldek. Only
active when -D php_suffix is set (explicit version request from
client scripts like php82.sh). Without php_suffix, returns empty
so poldek resolves freely.
This correctly handles specs with version ranges (e.g.
php(core) >= 5.6 and php(core) < 8.0) — poldek picks the newest
valid provider instead of being forced to a single version.
Chroot cleanup uses uninstall() for safety (hold list, crucial
package checks) instead of raw rpm -e. Call is placed in
rpm_builder.py between uninstall_self_conflict and install_br.
Also add log.notice() calls for build step visibility in syslog.
PLD_Builder/install.py | 39 ++++++++++++++++----------------
PLD_Builder/request.py | 56 +++++++++++++++++++++++++---------------------
PLD_Builder/rpm_builder.py | 2 +-
3 files changed, 52 insertions(+), 45 deletions(-)
---
diff --git a/PLD_Builder/install.py b/PLD_Builder/install.py
index e304503..ea5e90d 100644
--- a/PLD_Builder/install.py
+++ b/PLD_Builder/install.py
@@ -100,6 +100,7 @@ def uninstall(conflicting, b):
return True
def uninstall_self_conflict(b):
+ log.notice("checking BuildConflicts for %s" % b.spec)
b.log_line("checking BuildConflict-ing packages")
rpmcommand = "rpmbuild --nobuild -br"
cmd = "set -e; TMPDIR=%(tmpdir)s %(rpmcommand)s %(rpmdefs)s %(topdir)s/%(spec)s 2>&1" % {
@@ -126,40 +127,40 @@ def uninstall_self_conflict(b):
b.log_line("no BuildConflicts found")
return True
-def remove_ignored_packages(b):
- """Remove installed packages that match the ignore patterns.
+def cleanup_stale_packages(b):
+ """Remove stale multi-version packages from the chroot.
The builder reuses chroots across builds, so a previous build may
- have installed packages that should be ignored (e.g. php53-* when
- the default PHP is php85). These satisfy virtual deps in the rpm
- db, preventing poldek from installing the correct version. Remove
- them so that get_missing_br() reports the deps as unmet and poldek
- installs the right packages.
+ have installed packages from the wrong version family (e.g. php53-*
+ when the current build needs php85). These satisfy virtual deps in
+ the rpm db, preventing poldek from installing the correct version.
+
+ When -D php_suffix is set, only that version is kept. Otherwise,
+ all versioned PHP packages are removed — poldek will reinstall
+ whatever the spec actually needs, guided by its EVR tiebreaker and
+ the spec's version constraints.
"""
- patterns = b.ignore_patterns()
+ log.notice("cleaning up stale packages for %s" % b.spec)
+ patterns = b.cleanup_patterns()
if not patterns:
return
query = ' '.join("'%s'" % p for p in patterns)
f = chroot.popen("rpm -qa %s --queryformat '%%{NAME}\\n'" % query, user = "root", encoding = "utf-8")
- seen = {}
+ stale = {}
for l in f:
name = l.strip()
if name:
- seen[name] = 1
+ stale[name] = 1
f.close()
- if not seen:
- return
-
- to_remove = ' '.join(seen.keys())
- b.log_line("removing ignored packages from chroot: %s" % to_remove)
- res = chroot.run("rpm --allmatches -e %s" % to_remove,
- logfile = b.logfile, user = "root")
- if res != 0:
- b.log_line("warning: removal of ignored packages failed")
+ if stale:
+ b.log_line("removing stale packages from chroot: %s" % ' '.join(stale.keys()))
+ uninstall(stale, b)
def install_br(r, b):
+ log.notice("installing BuildRequires for %s" % b.spec)
+
def get_missing_br(r, b):
# ignore internal rpm dependencies, see lib/rpmns.c for list
ignore_br = re.compile(r'^\s*(rpmlib|cpuinfo|getconf|uname|soname|user|group|mounted|diskspace|digest|gnupg|macro|envvar|running|sanitycheck|vcheck|signature|verify|exists|executable|readable|writable)\(.*')
diff --git a/PLD_Builder/request.py b/PLD_Builder/request.py
index a014a6a..08a243d 100644
--- a/PLD_Builder/request.py
+++ b/PLD_Builder/request.py
@@ -400,48 +400,54 @@ class Batch:
"--define '_builddir %{_topdir}/BUILD' "
return rpmdefs + rpmopts
- def php_ignores(self):
- # Determine which PHP version to keep. If -D php_suffix was
- # passed in the build request, use that. Otherwise, ask the
- # chroot what rpm --eval '%{php_name}' returns — this is the
- # system-default PHP set by rpmbuild macros and stays current
- # without any hardcoded version lists.
- if 'php_suffix' in self.defines:
- keep_prefix = "php%s" % self.defines['php_suffix']
- else:
- f = chroot.popen("rpm --eval '%{php_name}'", encoding = "utf-8")
- keep_prefix = f.read().strip()
- f.close()
- if not re.match(r'^php\d+$', keep_prefix):
- log.notice("php_ignores: unexpected %%{php_name} value: '%s', skipping php ignores" % keep_prefix)
- return []
-
- # Discover all phpNN-* version prefixes available in the repo
- # by looking at php*-program packages. Ignore every prefix
- # except the one we want to keep.
+ def _php_repo_prefixes(self):
+ """Discover all phpNN version prefixes available in the repo (cached)."""
+ if hasattr(self, '_cached_php_prefixes'):
+ return set(self._cached_php_prefixes)
+
rx = re.compile(r'^(php\d+)-program-')
prefixes = set()
- f = chroot.popen("poldek -q --shcmd='ls -q php*-program'", encoding = "utf-8")
+ f = chroot.popen("poldek -q --shcmd='ls -q php*-program'", encoding = "utf-8", nonet = False)
for l in f:
m = rx.match(l.strip())
if m:
prefixes.add(m.group(1))
f.close()
+ self._cached_php_prefixes = prefixes
+ return set(prefixes)
- if len(prefixes) == 0:
- log.notice("php_ignores: no php*-program packages found in repo, skipping php ignores")
+ def _php_patterns(self, require_suffix=False):
+ """Build glob patterns for unwanted PHP version packages.
+
+ When require_suffix is True, return [] if php_suffix is not set
+ (used for --ignore: let poldek resolve freely). When False,
+ return patterns for all versioned PHP except the explicitly
+ requested one (used for chroot cleanup).
+ """
+ if require_suffix and 'php_suffix' not in self.defines:
return []
- prefixes.discard(keep_prefix)
+ prefixes = self._php_repo_prefixes()
+ if not prefixes:
+ return []
+
+ if 'php_suffix' in self.defines:
+ prefixes.discard("php%s" % self.defines['php_suffix'])
res = ['hhvm-*']
for p in sorted(prefixes):
res.append("%s-*" % p)
-
return res
+ def cleanup_patterns(self):
+ """Patterns for removing stale multi-version packages from the chroot."""
+ return self._php_patterns(require_suffix=False)
+
def ignore_patterns(self):
- return self.php_ignores()
+ """Patterns for --ignore flags passed to poldek.
+ Only active when -D php_suffix explicitly requests a version.
+ """
+ return self._php_patterns(require_suffix=True)
# build ignore package list for poldek
def ignores(self):
diff --git a/PLD_Builder/rpm_builder.py b/PLD_Builder/rpm_builder.py
index 14ed8ce..e5c8ddb 100644
--- a/PLD_Builder/rpm_builder.py
+++ b/PLD_Builder/rpm_builder.py
@@ -232,7 +232,7 @@ def build_rpm(r, b):
if ("no-install-br" not in r.flags) and not install.uninstall_self_conflict(b):
res = "FAIL_DEPS_UNINSTALL"
if ("no-install-br" not in r.flags):
- install.remove_ignored_packages(b)
+ install.cleanup_stale_packages(b)
if ("no-install-br" not in r.flags) and not install.install_br(r, b):
res = "FAIL_DEPS_INSTALL"
if not res:
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/projects/pld-builder.new.git/commitdiff/859f89b844a5e817445563c32c6c83efcf700e52
More information about the pld-cvs-commit
mailing list