mirror of
https://git.yoctoproject.org/poky
synced 2026-05-30 12:29:55 +00:00
oe/rootfs.py: DpkgRootfs/OpkgRootfs add support for dependency handling in postinsts scripts.
The old code don't take into account package dependencies causing undefined execution order in postinsts scripts, in order to fix: Add DpkgOpkgRootfs class for store common operations in DpkgRootfs and OpkgRootfs. Add _get_delayed_postinsts_common method that process Depends from status file in dpkg/opkg and resolve dependency order causing an execption if found circular dependencies. [YOCTO #5318] (From OE-Core rev: ed52d1040ee8be0bfa080d5679c583b1012bb575) Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
committed by
Richard Purdie
parent
f8661aaeba
commit
b2c9e7347a
+101
-55
@@ -495,8 +495,98 @@ class RpmRootfs(Rootfs):
|
|||||||
if os.path.isdir(self.pm.install_dir_path) and not os.listdir(self.pm.install_dir_path):
|
if os.path.isdir(self.pm.install_dir_path) and not os.listdir(self.pm.install_dir_path):
|
||||||
bb.utils.remove(self.pm.install_dir_path, True)
|
bb.utils.remove(self.pm.install_dir_path, True)
|
||||||
|
|
||||||
|
class DpkgOpkgRootfs(Rootfs):
|
||||||
|
def __init__(self, d):
|
||||||
|
super(DpkgOpkgRootfs, self).__init__(d)
|
||||||
|
|
||||||
class DpkgRootfs(Rootfs):
|
def _get_pkgs_postinsts(self, status_file):
|
||||||
|
def _get_pkg_depends_list(pkg_depends):
|
||||||
|
pkg_depends_list = []
|
||||||
|
# filter version requirements like libc (>= 1.1)
|
||||||
|
for dep in pkg_depends.split(', '):
|
||||||
|
m_dep = re.match("^(.*) \(.*\)$", dep)
|
||||||
|
if m_dep:
|
||||||
|
dep = m_dep.group(1)
|
||||||
|
pkg_depends_list.append(dep)
|
||||||
|
|
||||||
|
return pkg_depends_list
|
||||||
|
|
||||||
|
pkgs = {}
|
||||||
|
pkg_name = ""
|
||||||
|
pkg_status_match = False
|
||||||
|
pkg_depends = ""
|
||||||
|
|
||||||
|
with open(status_file) as status:
|
||||||
|
data = status.read()
|
||||||
|
status.close()
|
||||||
|
for line in data.split('\n'):
|
||||||
|
m_pkg = re.match("^Package: (.*)", line)
|
||||||
|
m_status = re.match("^Status:.*unpacked", line)
|
||||||
|
m_depends = re.match("^Depends: (.*)", line)
|
||||||
|
|
||||||
|
if m_pkg is not None:
|
||||||
|
if pkg_name and pkg_status_match:
|
||||||
|
pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
|
||||||
|
|
||||||
|
pkg_name = m_pkg.group(1)
|
||||||
|
pkg_status_match = False
|
||||||
|
pkg_depends = ""
|
||||||
|
elif m_status is not None:
|
||||||
|
pkg_status_match = True
|
||||||
|
elif m_depends is not None:
|
||||||
|
pkg_depends = m_depends.group(1)
|
||||||
|
|
||||||
|
# remove package dependencies not in postinsts
|
||||||
|
pkg_names = pkgs.keys()
|
||||||
|
for pkg_name in pkg_names:
|
||||||
|
deps = pkgs[pkg_name][:]
|
||||||
|
|
||||||
|
for d in deps:
|
||||||
|
if d not in pkg_names:
|
||||||
|
pkgs[pkg_name].remove(d)
|
||||||
|
|
||||||
|
return pkgs
|
||||||
|
|
||||||
|
def _get_delayed_postinsts_common(self, status_file):
|
||||||
|
def _dep_resolve(graph, node, resolved, seen):
|
||||||
|
seen.append(node)
|
||||||
|
|
||||||
|
for edge in graph[node]:
|
||||||
|
if edge not in resolved:
|
||||||
|
if edge in seen:
|
||||||
|
raise RuntimeError("Packages %s and %s have " \
|
||||||
|
"a circular dependency in postinsts scripts." \
|
||||||
|
% (node, edge))
|
||||||
|
_dep_resolve(graph, edge, resolved, seen)
|
||||||
|
|
||||||
|
resolved.append(node)
|
||||||
|
|
||||||
|
pkg_list = []
|
||||||
|
|
||||||
|
pkgs = self._get_pkgs_postinsts(status_file)
|
||||||
|
if pkgs:
|
||||||
|
root = "__packagegroup_postinst__"
|
||||||
|
pkgs[root] = pkgs.keys()
|
||||||
|
_dep_resolve(pkgs, root, pkg_list, [])
|
||||||
|
pkg_list.remove(root)
|
||||||
|
|
||||||
|
if len(pkg_list) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return pkg_list
|
||||||
|
|
||||||
|
def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
|
||||||
|
num = 0
|
||||||
|
for p in self._get_delayed_postinsts():
|
||||||
|
bb.utils.mkdirhier(dst_postinst_dir)
|
||||||
|
|
||||||
|
if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
|
||||||
|
shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
|
||||||
|
os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
|
||||||
|
|
||||||
|
num += 1
|
||||||
|
|
||||||
|
class DpkgRootfs(DpkgOpkgRootfs):
|
||||||
def __init__(self, d, manifest_dir):
|
def __init__(self, d, manifest_dir):
|
||||||
super(DpkgRootfs, self).__init__(d)
|
super(DpkgRootfs, self).__init__(d)
|
||||||
self.log_check_regex = '^E:'
|
self.log_check_regex = '^E:'
|
||||||
@@ -540,34 +630,13 @@ class DpkgRootfs(Rootfs):
|
|||||||
return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMAND']
|
return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMAND']
|
||||||
|
|
||||||
def _get_delayed_postinsts(self):
|
def _get_delayed_postinsts(self):
|
||||||
pkg_list = []
|
status_file = self.image_rootfs + "/var/lib/dpkg/status"
|
||||||
with open(self.image_rootfs + "/var/lib/dpkg/status") as status:
|
return self._get_delayed_postinsts_common(status_file)
|
||||||
for line in status:
|
|
||||||
m_pkg = re.match("^Package: (.*)", line)
|
|
||||||
m_status = re.match("^Status:.*unpacked", line)
|
|
||||||
if m_pkg is not None:
|
|
||||||
pkg_name = m_pkg.group(1)
|
|
||||||
elif m_status is not None:
|
|
||||||
pkg_list.append(pkg_name)
|
|
||||||
|
|
||||||
if len(pkg_list) == 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return pkg_list
|
|
||||||
|
|
||||||
def _save_postinsts(self):
|
def _save_postinsts(self):
|
||||||
num = 0
|
dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
|
||||||
for p in self._get_delayed_postinsts():
|
src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
|
||||||
dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
|
return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
|
||||||
src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
|
|
||||||
|
|
||||||
bb.utils.mkdirhier(dst_postinst_dir)
|
|
||||||
|
|
||||||
if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
|
|
||||||
shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
|
|
||||||
os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
|
|
||||||
|
|
||||||
num += 1
|
|
||||||
|
|
||||||
def _handle_intercept_failure(self, registered_pkgs):
|
def _handle_intercept_failure(self, registered_pkgs):
|
||||||
self.pm.mark_packages("unpacked", registered_pkgs.split())
|
self.pm.mark_packages("unpacked", registered_pkgs.split())
|
||||||
@@ -580,7 +649,7 @@ class DpkgRootfs(Rootfs):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class OpkgRootfs(Rootfs):
|
class OpkgRootfs(DpkgOpkgRootfs):
|
||||||
def __init__(self, d, manifest_dir):
|
def __init__(self, d, manifest_dir):
|
||||||
super(OpkgRootfs, self).__init__(d)
|
super(OpkgRootfs, self).__init__(d)
|
||||||
self.log_check_regex = '(exit 1|Collected errors)'
|
self.log_check_regex = '(exit 1|Collected errors)'
|
||||||
@@ -810,38 +879,15 @@ class OpkgRootfs(Rootfs):
|
|||||||
return ['IPKGCONF_SDK', 'IPK_FEED_URIS', 'DEPLOY_DIR_IPK', 'IPKGCONF_TARGET', 'INC_IPK_IMAGE_GEN', 'OPKG_ARGS', 'OPKGLIBDIR', 'OPKG_PREPROCESS_COMMANDS', 'OPKG_POSTPROCESS_COMMANDS', 'OPKGLIBDIR']
|
return ['IPKGCONF_SDK', 'IPK_FEED_URIS', 'DEPLOY_DIR_IPK', 'IPKGCONF_TARGET', 'INC_IPK_IMAGE_GEN', 'OPKG_ARGS', 'OPKGLIBDIR', 'OPKG_PREPROCESS_COMMANDS', 'OPKG_POSTPROCESS_COMMANDS', 'OPKGLIBDIR']
|
||||||
|
|
||||||
def _get_delayed_postinsts(self):
|
def _get_delayed_postinsts(self):
|
||||||
pkg_list = []
|
|
||||||
status_file = os.path.join(self.image_rootfs,
|
status_file = os.path.join(self.image_rootfs,
|
||||||
self.d.getVar('OPKGLIBDIR', True).strip('/'),
|
self.d.getVar('OPKGLIBDIR', True).strip('/'),
|
||||||
"opkg", "status")
|
"opkg", "status")
|
||||||
|
return self._get_delayed_postinsts_common(status_file)
|
||||||
with open(status_file) as status:
|
|
||||||
for line in status:
|
|
||||||
m_pkg = re.match("^Package: (.*)", line)
|
|
||||||
m_status = re.match("^Status:.*unpacked", line)
|
|
||||||
if m_pkg is not None:
|
|
||||||
pkg_name = m_pkg.group(1)
|
|
||||||
elif m_status is not None:
|
|
||||||
pkg_list.append(pkg_name)
|
|
||||||
|
|
||||||
if len(pkg_list) == 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return pkg_list
|
|
||||||
|
|
||||||
def _save_postinsts(self):
|
def _save_postinsts(self):
|
||||||
num = 0
|
dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/ipk-postinsts")
|
||||||
for p in self._get_delayed_postinsts():
|
src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${OPKGLIBDIR}/opkg/info")
|
||||||
dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/ipk-postinsts")
|
return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
|
||||||
src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${OPKGLIBDIR}/opkg/info")
|
|
||||||
|
|
||||||
bb.utils.mkdirhier(dst_postinst_dir)
|
|
||||||
|
|
||||||
if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
|
|
||||||
shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
|
|
||||||
os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
|
|
||||||
|
|
||||||
num += 1
|
|
||||||
|
|
||||||
def _handle_intercept_failure(self, registered_pkgs):
|
def _handle_intercept_failure(self, registered_pkgs):
|
||||||
self.pm.mark_packages("unpacked", registered_pkgs.split())
|
self.pm.mark_packages("unpacked", registered_pkgs.split())
|
||||||
|
|||||||
Reference in New Issue
Block a user