[3/3] isar: Add provides explorer

Message ID 20230921063247.3114251-4-amikan@ilbers.de
State New
Headers show
Series [1/3] conf: Enable bbappends | expand

Commit Message

Anton Mikanovich Sept. 21, 2023, 6:32 a.m. UTC
Explore Isar recipes for any packages declared in debian/control but
not added as PROVIDES of recipe.

Usage (inside build dir):
$ ../scripts/explore.py provides mc:qemuamd64-bullseye:isar-image-base

This script requires python3-apt to be installed.

Signed-off-by: Anton Mikanovich <amikan@ilbers.de>
---
 scripts/explore.py | 95 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 92 insertions(+), 3 deletions(-)

Patch

diff --git a/scripts/explore.py b/scripts/explore.py
index 56c7378a..ca387e6e 100755
--- a/scripts/explore.py
+++ b/scripts/explore.py
@@ -71,6 +71,89 @@  class IsarBuilder:
         else:
             return True
 
+    def provides_lookup(self):
+        try:
+            self.isar_apt_update()
+            self.sr = apt_pkg.SourceRecords()
+        except:
+            print('No apt-cache found')
+
+        sources_build = []
+        provides_all = []
+        for pn, fns in self.recipecache.pkg_pn.items():
+            if pn.endswith('-native') or pn.endswith('-compat'):
+                continue
+
+            provider = self.tinfoil.find_best_provider(pn)
+            if provider[3] is None or provider[3].endswith('linux-distro.bb'):
+                continue
+
+            pn_mc = pn if not self.mc else ':'.join(['mc', self.mc, pn])
+
+            local_d = self.tinfoil.parse_recipe(pn_mc)
+            source_task = local_d.getVar('do_deploy_source', expand=True)
+            if not source_task:
+                continue
+
+            # Filter out conflict packages
+            list = 0
+            provides = local_d.getVar('PROVIDES', expand=True)
+            for provides_list in provides_all:
+                for prov in provides.split():
+                    if prov in provides_list:
+                        break
+                else:
+                    break
+                list += 1
+
+            if list >= len(provides_all):
+                provides_all.append([])
+            if list >= len(sources_build):
+                sources_build.append([])
+
+            provides_all[list].extend(provides.split())
+            if hasattr(self, 'sr'):
+                self.sr.restart()
+                if not self.sr.lookup(pn):
+                    sources_build[list].append(pn)
+            else:
+                sources_build[list].append(pn)
+
+        for sources in sources_build:
+            if not self.bitbake(sources, 'do_deploy_source'):
+                return
+
+        if not hasattr(self, 'sr'):
+            try:
+                self.isar_apt_update()
+                self.sr = apt_pkg.SourceRecords()
+            except:
+                print('No apt-cache found')
+
+        for pn, fns in self.recipecache.pkg_pn.items():
+            if pn.endswith('-native') or pn.endswith('-compat'):
+                continue
+
+            provider = self.tinfoil.find_best_provider(pn)
+
+            self.sr.restart()
+            while self.sr.lookup(pn):
+                pn_mc = pn if not self.mc else ':'.join(['mc', self.mc, pn])
+                local_d = self.tinfoil.parse_recipe(pn_mc)
+                provides = local_d.getVar('PROVIDES', expand=True)
+
+                for bin in self.sr.binaries:
+                    if bin == pn:
+                        continue
+
+                    if bin in provides:
+                        continue
+
+                    print(f'{pn} provides {bin}')
+                    append_filename = provider[3].rsplit(':', 1)[-1] + 'append'
+                    with open(append_filename, 'a') as f:
+                        f.write(f'PROVIDES += "{bin}"\n')
+
     def deps_lookup(self, pkg, parent_provider, add=True):
         if pkg in self.cache:
             return
@@ -154,8 +237,8 @@  class IsarBuilder:
         if self.need_source:
             print('Following packages still left unchecked: ' + str(self.need_source))
 
-if len(sys.argv) != 3:
-    print('Usage: ../scripts/explore.py deps mc:qemuamd64-bullseye:isar-image-base')
+if len(sys.argv) != 3 or sys.argv[1] not in ['all', 'deps', 'provides']:
+    print('Usage: ../scripts/explore.py [ all | deps | provides ] mc:qemuamd64-bullseye:isar-image-base')
     exit(1)
 
 mc = ''
@@ -170,6 +253,12 @@  else:
 ib = IsarBuilder()
 try:
     ib.init(mc, target)
-    ib.explore_deps()
+    if sys.argv[1] == 'all':
+        ib.provides_lookup()
+        ib.explore_deps()
+    elif sys.argv[1] == 'deps':
+        ib.explore_deps()
+    elif sys.argv[1] == 'provides':
+        ib.provides_lookup()
 finally:
     ib.shutdown()