summaryrefslogtreecommitdiffstats
path: root/meta/lib
diff options
context:
space:
mode:
authorAníbal Limón <anibal.limon@linux.intel.com>2015-06-25 13:21:15 -0500
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-06-27 22:42:52 +0100
commitb2c9e7347acdfd0efe1c3dabb853d609233b61b6 (patch)
tree7bdf2e39ed38c50925c663abe25d58209877ef38 /meta/lib
parentf8661aaeba4d4b1fb328106c36493a5019b59110 (diff)
downloadpoky-b2c9e7347acdfd0efe1c3dabb853d609233b61b6.tar.gz
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>
Diffstat (limited to 'meta/lib')
-rw-r--r--meta/lib/oe/rootfs.py156
1 files changed, 101 insertions, 55 deletions
diff --git a/meta/lib/oe/rootfs.py b/meta/lib/oe/rootfs.py
index 48e5754b27..327c8eae86 100644
--- a/meta/lib/oe/rootfs.py
+++ b/meta/lib/oe/rootfs.py
@@ -495,8 +495,98 @@ class RpmRootfs(Rootfs):
495 if os.path.isdir(self.pm.install_dir_path) and not os.listdir(self.pm.install_dir_path): 495 if os.path.isdir(self.pm.install_dir_path) and not os.listdir(self.pm.install_dir_path):
496 bb.utils.remove(self.pm.install_dir_path, True) 496 bb.utils.remove(self.pm.install_dir_path, True)
497 497
498class DpkgOpkgRootfs(Rootfs):
499 def __init__(self, d):
500 super(DpkgOpkgRootfs, self).__init__(d)
501
502 def _get_pkgs_postinsts(self, status_file):
503 def _get_pkg_depends_list(pkg_depends):
504 pkg_depends_list = []
505 # filter version requirements like libc (>= 1.1)
506 for dep in pkg_depends.split(', '):
507 m_dep = re.match("^(.*) \(.*\)$", dep)
508 if m_dep:
509 dep = m_dep.group(1)
510 pkg_depends_list.append(dep)
511
512 return pkg_depends_list
513
514 pkgs = {}
515 pkg_name = ""
516 pkg_status_match = False
517 pkg_depends = ""
518
519 with open(status_file) as status:
520 data = status.read()
521 status.close()
522 for line in data.split('\n'):
523 m_pkg = re.match("^Package: (.*)", line)
524 m_status = re.match("^Status:.*unpacked", line)
525 m_depends = re.match("^Depends: (.*)", line)
526
527 if m_pkg is not None:
528 if pkg_name and pkg_status_match:
529 pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
530
531 pkg_name = m_pkg.group(1)
532 pkg_status_match = False
533 pkg_depends = ""
534 elif m_status is not None:
535 pkg_status_match = True
536 elif m_depends is not None:
537 pkg_depends = m_depends.group(1)
538
539 # remove package dependencies not in postinsts
540 pkg_names = pkgs.keys()
541 for pkg_name in pkg_names:
542 deps = pkgs[pkg_name][:]
543
544 for d in deps:
545 if d not in pkg_names:
546 pkgs[pkg_name].remove(d)
547
548 return pkgs
549
550 def _get_delayed_postinsts_common(self, status_file):
551 def _dep_resolve(graph, node, resolved, seen):
552 seen.append(node)
553
554 for edge in graph[node]:
555 if edge not in resolved:
556 if edge in seen:
557 raise RuntimeError("Packages %s and %s have " \
558 "a circular dependency in postinsts scripts." \
559 % (node, edge))
560 _dep_resolve(graph, edge, resolved, seen)
561
562 resolved.append(node)
563
564 pkg_list = []
498 565
499class DpkgRootfs(Rootfs): 566 pkgs = self._get_pkgs_postinsts(status_file)
567 if pkgs:
568 root = "__packagegroup_postinst__"
569 pkgs[root] = pkgs.keys()
570 _dep_resolve(pkgs, root, pkg_list, [])
571 pkg_list.remove(root)
572
573 if len(pkg_list) == 0:
574 return None
575
576 return pkg_list
577
578 def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
579 num = 0
580 for p in self._get_delayed_postinsts():
581 bb.utils.mkdirhier(dst_postinst_dir)
582
583 if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
584 shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
585 os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
586
587 num += 1
588
589class DpkgRootfs(DpkgOpkgRootfs):
500 def __init__(self, d, manifest_dir): 590 def __init__(self, d, manifest_dir):
501 super(DpkgRootfs, self).__init__(d) 591 super(DpkgRootfs, self).__init__(d)
502 self.log_check_regex = '^E:' 592 self.log_check_regex = '^E:'
@@ -540,34 +630,13 @@ class DpkgRootfs(Rootfs):
540 return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMAND'] 630 return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMAND']
541 631
542 def _get_delayed_postinsts(self): 632 def _get_delayed_postinsts(self):
543 pkg_list = [] 633 status_file = self.image_rootfs + "/var/lib/dpkg/status"
544 with open(self.image_rootfs + "/var/lib/dpkg/status") as status: 634 return self._get_delayed_postinsts_common(status_file)
545 for line in status:
546 m_pkg = re.match("^Package: (.*)", line)
547 m_status = re.match("^Status:.*unpacked", line)
548 if m_pkg is not None:
549 pkg_name = m_pkg.group(1)
550 elif m_status is not None:
551 pkg_list.append(pkg_name)
552
553 if len(pkg_list) == 0:
554 return None
555
556 return pkg_list
557 635
558 def _save_postinsts(self): 636 def _save_postinsts(self):
559 num = 0 637 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
560 for p in self._get_delayed_postinsts(): 638 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
561 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts") 639 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
562 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
563
564 bb.utils.mkdirhier(dst_postinst_dir)
565
566 if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
567 shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
568 os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
569
570 num += 1
571 640
572 def _handle_intercept_failure(self, registered_pkgs): 641 def _handle_intercept_failure(self, registered_pkgs):
573 self.pm.mark_packages("unpacked", registered_pkgs.split()) 642 self.pm.mark_packages("unpacked", registered_pkgs.split())
@@ -580,7 +649,7 @@ class DpkgRootfs(Rootfs):
580 pass 649 pass
581 650
582 651
583class OpkgRootfs(Rootfs): 652class OpkgRootfs(DpkgOpkgRootfs):
584 def __init__(self, d, manifest_dir): 653 def __init__(self, d, manifest_dir):
585 super(OpkgRootfs, self).__init__(d) 654 super(OpkgRootfs, self).__init__(d)
586 self.log_check_regex = '(exit 1|Collected errors)' 655 self.log_check_regex = '(exit 1|Collected errors)'
@@ -810,38 +879,15 @@ class OpkgRootfs(Rootfs):
810 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'] 879 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']
811 880
812 def _get_delayed_postinsts(self): 881 def _get_delayed_postinsts(self):
813 pkg_list = []
814 status_file = os.path.join(self.image_rootfs, 882 status_file = os.path.join(self.image_rootfs,
815 self.d.getVar('OPKGLIBDIR', True).strip('/'), 883 self.d.getVar('OPKGLIBDIR', True).strip('/'),
816 "opkg", "status") 884 "opkg", "status")
817 885 return self._get_delayed_postinsts_common(status_file)
818 with open(status_file) as status:
819 for line in status:
820 m_pkg = re.match("^Package: (.*)", line)
821 m_status = re.match("^Status:.*unpacked", line)
822 if m_pkg is not None:
823 pkg_name = m_pkg.group(1)
824 elif m_status is not None:
825 pkg_list.append(pkg_name)
826
827 if len(pkg_list) == 0:
828 return None
829
830 return pkg_list
831 886
832 def _save_postinsts(self): 887 def _save_postinsts(self):
833 num = 0 888 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/ipk-postinsts")
834 for p in self._get_delayed_postinsts(): 889 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${OPKGLIBDIR}/opkg/info")
835 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/ipk-postinsts") 890 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
836 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${OPKGLIBDIR}/opkg/info")
837
838 bb.utils.mkdirhier(dst_postinst_dir)
839
840 if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
841 shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
842 os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
843
844 num += 1
845 891
846 def _handle_intercept_failure(self, registered_pkgs): 892 def _handle_intercept_failure(self, registered_pkgs):
847 self.pm.mark_packages("unpacked", registered_pkgs.split()) 893 self.pm.mark_packages("unpacked", registered_pkgs.split())