Define compat shims for %patchN when building for EL <= 10

Thanks Ray Strode for the idea of searching the spec file for used %patchN macros.

Signed-off-by: Miro Hrončok <miro@hroncok.cz>
This commit is contained in:
Miro Hrončok 2024-11-05 13:38:09 +01:00
parent 4273360dd0
commit 12342a17b7

View file

@ -16,10 +16,12 @@
# the full text of the license. # the full text of the license.
import os
import re import re
import warnings import warnings
import git import git
import rpm
from pyrpkg import Commands, rpkgError from pyrpkg import Commands, rpkgError
from pyrpkg.utils import cached_property from pyrpkg.utils import cached_property
@ -201,6 +203,55 @@ class Commands(Commands):
self.branch_merge, self.branch_merge,
) )
def _define_patchn_compatiblity_macros(self):
"""
RPM 4.19 deprecated the %patchN macro. RPM 4.20 removed it completely.
The macro works on c8s, c9s, c10s, but does not work on Fedora 41+.
We can no longer even parse RPM spec files with the %patchN macros.
When we build for old streams, we define the %patchN macros manually as %patch -P N.
Since N can be any number including zero-prefixed numbers,
we regex-search the spec file for %patchN uses and define only the macros found.
"""
# Only do this on RPM 4.19.90+ (4.19.9x were pre-releases of 4.20)
if tuple(int(i) for i in rpm.__version_info__) < (4, 19, 90):
return
# Only do this when building for CentOS Stream version with RPM < 4.20
try:
if int(self._distval.split("_")[0]) > 10:
return
except ValueError as e:
self.log.debug(
"Cannot parse major dist version as int: %s",
self._distval.split("_")[0],
exc_info=e,
)
return
defined_patchn = False
try:
specfile_path = os.path.join(self.layout.specdir, self.spec)
with open(specfile_path, "rb") as specfile:
# Find all uses of %patchN in the spec files
# Using a benevolent regex: commented out macros, etc. match as well
for patch in re.findall(rb"%{?patch(\d+)\b", specfile.read()):
# We operate on bytes becasue we don't know the spec encoding
# but the matched part only includes ASCII digits
patch = patch.decode("ascii")
self._rpmdefines.extend(
[
"--define",
# defines parametric macro %patchN which passes all arguments to %patch -P N
"patch%s(-) %%patch -P %s %%{?**}" % (patch, patch),
]
)
defined_patchn = True
except OSError as e:
self.log.debug("Cannot read spec.", exc_info=e)
if defined_patchn:
self.log.warn(
"centpkg defined %patchN compatibility shims to parse the spec file. "
"%patchN is obsolete, use %patch -P N instead."
)
# redefined loaders # redefined loaders
def load_rpmdefines(self): def load_rpmdefines(self):
""" """
@ -245,6 +296,7 @@ class Commands(Commands):
"--eval", "--eval",
"%%undefine %s" % self._distunset, "%%undefine %s" % self._distunset,
] ]
self._define_patchn_compatiblity_macros()
self.log.debug("RPMDefines: %s" % self._rpmdefines) self.log.debug("RPMDefines: %s" % self._rpmdefines)
def construct_build_url(self, *args, **kwargs): def construct_build_url(self, *args, **kwargs):