diff --git a/dnf/base.py b/dnf/base.py index 0222c76dae..0551367e96 100644 --- a/dnf/base.py +++ b/dnf/base.py @@ -157,8 +157,14 @@ def _setup_default_conf(): conf = dnf.conf.Conf() subst = conf.substitutions if 'releasever' not in subst: - subst['releasever'] = \ - dnf.rpm.detect_releasever(conf.installroot) + releasever, major, minor = \ + dnf.rpm.detect_releasevers(conf.installroot) + subst['releasever'] = releasever + if major is not None: + subst['releasever_major'] = major + if minor is not None: + subst['releasever_minor'] = minor + return conf def _setup_modular_excludes(self): diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py index 2d20cf425c..0704b59433 100644 --- a/dnf/cli/cli.py +++ b/dnf/cli/cli.py @@ -951,13 +951,20 @@ def _read_conf_file(self, releasever=None): from_root = "/" subst = conf.substitutions subst.update_from_etc(from_root, varsdir=conf._get_value('varsdir')) + # cachedir, logs, releasever, and gpgkey are taken from or stored in installroot + major = None + minor = None if releasever is None and conf.releasever is None: - releasever = dnf.rpm.detect_releasever(conf.installroot) + releasever, major, minor = dnf.rpm.detect_releasevers(conf.installroot) elif releasever == '/': - releasever = dnf.rpm.detect_releasever(releasever) + releasever, major, minor = dnf.rpm.detect_releasevers(releasever) if releasever is not None: conf.releasever = releasever + if major is not None: + conf.releasever_major = major + if minor is not None: + conf.releasever_minor = minor if conf.releasever is None: logger.warning(_("Unable to detect release version (use '--releasever' to specify " "release version)")) diff --git a/dnf/const.py.in b/dnf/const.py.in index bcadc80410..5c48e0acbd 100644 --- a/dnf/const.py.in +++ b/dnf/const.py.in @@ -25,6 +25,8 @@ CONF_AUTOMATIC_FILENAME='/etc/dnf/automatic.conf' DISTROVERPKG=('system-release(releasever)', 'system-release', 'distribution-release(releasever)', 'distribution-release', 'redhat-release', 'suse-release') +DISTROVER_MAJOR_PKG='system-release-major' +DISTROVER_MINOR_PKG='system-release-minor' GROUP_PACKAGE_TYPES = ('mandatory', 'default', 'conditional') # :api INSTALLONLYPKGS=['kernel', 'kernel-PAE', 'installonlypkg(kernel)', diff --git a/dnf/rpm/__init__.py b/dnf/rpm/__init__.py index 12efca7fb4..33592193b4 100644 --- a/dnf/rpm/__init__.py +++ b/dnf/rpm/__init__.py @@ -26,12 +26,21 @@ import rpm # used by ansible (dnf.rpm.rpm.labelCompare in lib/ansible/modules/packaging/os/dnf.py) -def detect_releasever(installroot): +def detect_releasevers(installroot): # :api - """Calculate the release version for the system.""" + """Calculate the release version for the system, including releasever_major + and releasever_minor if they are overriden by the system-release-major or + system-release-minor provides.""" ts = transaction.initReadOnlyTransaction(root=installroot) ts.pushVSFlags(~(rpm._RPMVSF_NOSIGNATURES | rpm._RPMVSF_NODIGESTS)) + + distrover_major_pkg = dnf.const.DISTROVER_MAJOR_PKG + distrover_minor_pkg = dnf.const.DISTROVER_MINOR_PKG + if dnf.pycomp.PY3: + distrover_major_pkg = bytes(distrover_major_pkg, 'utf-8') + distrover_minor_pkg = bytes(distrover_minor_pkg, 'utf-8') + for distroverpkg in dnf.const.DISTROVERPKG: if dnf.pycomp.PY3: distroverpkg = bytes(distroverpkg, 'utf-8') @@ -47,6 +56,8 @@ def detect_releasever(installroot): msg = 'Error: rpmdb failed to list provides. Try: rpm --rebuilddb' raise dnf.exceptions.Error(msg) releasever = hdr['version'] + releasever_major = None + releasever_minor = None try: try: # header returns bytes -> look for bytes @@ -61,15 +72,39 @@ def detect_releasever(installroot): if hdr['name'] not in (distroverpkg, distroverpkg.decode("utf8")): # override the package version releasever = ver + + for provide, flag, ver in zip( + hdr[rpm.RPMTAG_PROVIDENAME], + hdr[rpm.RPMTAG_PROVIDEFLAGS], + hdr[rpm.RPMTAG_PROVIDEVERSION]): + if isinstance(provide, str): + provide = bytes(provide, "utf-8") + if provide == distrover_major_pkg and flag == rpm.RPMSENSE_EQUAL and ver: + releasever_major = ver + if provide == distrover_minor_pkg and flag == rpm.RPMSENSE_EQUAL and ver: + releasever_minor = ver + except (ValueError, KeyError, IndexError): pass if is_py3bytes(releasever): releasever = str(releasever, "utf-8") - return releasever + if is_py3bytes(releasever_major): + releasever_major = str(releasever_major, "utf-8") + if is_py3bytes(releasever_minor): + releasever_minor = str(releasever_minor, "utf-8") + return releasever, releasever_major, releasever_minor return None +def detect_releasever(installroot): + # :api + """Calculate the release version for the system.""" + + releasever, _, _ = detect_releasevers(installroot) + return releasever + + def _header(path): """Return RPM header of the file.""" ts = transaction.initReadOnlyTransaction()