[elbe-devel] [PATCH 07/11] pkgutils: be aware of package dependencies

Manuel Traut manut at linutronix.de
Mon Jan 29 13:21:06 CET 2018


allow optional download and extraction of packages including all the
runtime dependencies of the specified package

Signed-off-by: Manuel Traut <manut at linutronix.de>
---
 elbepack/pkgutils.py | 151 ++++++++++++++++++++++++++++++++-------------------
 1 file changed, 94 insertions(+), 57 deletions(-)

diff --git a/elbepack/pkgutils.py b/elbepack/pkgutils.py
index 41131432..3ce9d31e 100644
--- a/elbepack/pkgutils.py
+++ b/elbepack/pkgutils.py
@@ -132,8 +132,35 @@ def get_uri_nonvirtapt(apt_sources, target_pkg, arch):
             if pkg:
                 return "", pkg
 
+def getdeps(pkg):
+    for dd in pkg.depends_list.get("Depends", []):
+        for d in dd:
+            yield d.target_pkg.name
 
-def get_uri(prj, defs, arch, target_pkg):
+def lookup_uri(v, d, target_pkg):
+
+    pkg = v.cache[target_pkg]
+
+    c = d.get_candidate_ver(pkg)
+
+    x = v.source.find_index(c.file_list[0][0])
+
+    r = virtapt.apt_pkg.PackageRecords(v.cache)
+    r.lookup(c.file_list[0])
+    uri = x.archive_uri(r.filename)
+
+    if not x.is_trusted:
+        return target_pkg, uri, ""
+
+    # TODO remove r.sha256_hash path as soon as initvm is stretch or later
+    try:
+        hashval = r.sha256_hash
+    except DeprecationWarning:
+        hashval = str(r.hashes.find('SHA256')).split(':')[1]
+
+    return target_pkg, uri, hashval
+
+def get_uri(prj, defs, arch, target_pkg, incl_deps=False):
     if arch == "default":
         arch = prj.text("buildimage/arch", default=defs, key="arch")
     suite = prj.text("suite")
@@ -148,24 +175,27 @@ def get_uri(prj, defs, arch, target_pkg):
             return get_uri_nonvirtapt(apt_sources, target_pkg, arch)
 
         d = virtapt.apt_pkg.DepCache(v.cache)
-        pkg = v.cache[target_pkg]
 
-        c = d.get_candidate_ver(pkg)
-        x = v.source.find_index(c.file_list[0][0])
+        if not incl_deps:
+            return [lookup_uri(v, d, target_pkg)]
+
+        if incl_deps:
+            deps = [lookup_uri(v, d, target_pkg)]
+            togo = [target_pkg]
+            while len(togo):
+                pp = togo.pop()
+                pkg= v.cache[pp]
+                c = d.get_candidate_ver(pkg)
+                for p in getdeps(c):
+                    if len([y for y in deps if y[0] == p]):
+                        continue
+                    if p != target_pkg and p == pp:
+                        continue
+                    deps.append(lookup_uri(v, d, p))
+                    togo.append(p)
+
+            return deps
 
-        r = virtapt.apt_pkg.PackageRecords(v.cache)
-        r.lookup(c.file_list[0])
-        uri = x.archive_uri(r.filename)
-
-        if not x.is_trusted:
-            return "", uri
-
-        # TODO remove r.sha256_hash path as soon as initvm is stretch or later
-        try:
-            return r.sha256_hash, uri
-        except DeprecationWarning:
-            hashval = r.hashes.find('SHA256')
-            return hashval, uri
     else:
         return get_uri_nonvirtapt(apt_sources, target_pkg, arch)
 
@@ -189,12 +219,10 @@ def get_dsc_size(fname):
     return sz
 
 
-def download_pkg(prj, target_dir, defs, package, arch="default"):
-
-    dest = os.path.join(target_dir, "%s.deb" % package)
+def download_pkg(prj, target_dir, defs, package, arch="default", incl_deps=False):
 
     try:
-        sha256, uri = get_uri(prj, defs, arch, package)
+        urilist = get_uri(prj, defs, arch, package, incl_deps)
     except KeyError:
         raise NoKinitrdException('no package %s available' % package)
         return
@@ -204,51 +232,60 @@ def download_pkg(prj, target_dir, defs, package, arch="default"):
     except CommandError as e:
         raise NoKinitrdException("couldn't download package %s" % package)
 
-    try:
-        if uri.startswith("file://"):
-            system('cp "%s" "%s"' % (uri[len("file://"):], dest))
-
-        elif uri.startswith("http://") or uri.startswith("ftp://"):
-            system('wget -O "%s" "%s"' % (dest, uri))
-        else:
-            raise NoKinitrdException('could not retreive %s' % (package, uri))
-    except CommandError as e:
-        raise NoKinitrdException("couldn't download package %s" % package)
-        return
+    for u in urilist:
+        sha256 = u[2]
+        uri = u[1]
+        dest = os.path.join(target_dir, "%s.deb" % u[0])
 
-    if len(sha256) > 0:
-        m = hashlib.sha256()
-        with open(dest, "rb") as f:
-            buf = f.read(65536)
-            while len(buf) > 0:
-                m.update(buf)
+        try:
+            if uri.startswith("file://"):
+                system('cp "%s" "%s"' % (uri[len("file://"):], dest))
+            elif uri.startswith("http://") or uri.startswith("ftp://"):
+                system('wget -O "%s" "%s"' % (dest, uri))
+            else:
+                raise NoKinitrdException('could not retreive %s' % uri)
+        except CommandError as e:
+            raise NoKinitrdException("couldn't download package %s" % package)
+
+        if len(sha256) > 0:
+            m = hashlib.sha256()
+            with open(dest, "rb") as f:
                 buf = f.read(65536)
+                while len(buf) > 0:
+                    m.update(buf)
+                    buf = f.read(65536)
 
-        if m.hexdigest() != sha256:
-            raise NoKinitrdException('%s failed to verify !!!' % package)
-    else:
-        print("-----------------------------------------------------")
-        print("WARNING:")
-        print("Using untrusted %s package" % package)
-        print("-----------------------------------------------------")
-    return
+            if m.hexdigest() != sha256:
+                raise NoKinitrdException('%s failed to verify !!!' % package)
+        else:
+            # TODO this should be logged to validation.txt or stderr depending
+            # on use-case
+            print("-----------------------------------------------------")
+            print("WARNING:")
+            print("Using untrusted %s package" % package)
+            print("-----------------------------------------------------")
 
+    return [y[0] for y in urilist]
 
-def extract_pkg(prj, target_dir, defs, package, arch="default"):
 
-    download_pkg(prj, target_dir, defs, package, arch)
+def extract_pkg(prj, target_dir, defs, package, arch="default",
+                incl_deps=False):
 
-    try:
-        system('dpkg -x "%s" "%s"' %
-               (os.path.join(target_dir, "%s.deb" % package), target_dir))
-    except CommandError:
+    pkgs = download_pkg(prj, target_dir, defs, package, arch, incl_deps)
+
+    for package in pkgs:
+        ppath = os.path.join(target_dir, "%s.deb" % package)
         try:
-            # dpkg did not work, try falling back to ar and tar
-            system('ar p "%s" data.tar.gz | tar xz -C "%s"' %
-                   (os.path.join(target_dir, "%s.deb" % package), target_dir))
+            system('dpkg -x "%s" "%s"' % (ppath, target_dir))
         except CommandError:
-            system('ar p "%s" data.tar.xz | tar xJ -C "%s"' %
-                   (os.path.join(target_dir, "%s.deb" % package), target_dir))
+            try:
+                # dpkg did not work, try falling back to ar and tar
+                system('ar p "%s" data.tar.gz | tar xz -C "%s"' % (ppath,
+                                                                   target_dir))
+            except CommandError:
+                system('ar p "%s" data.tar.xz | tar xJ -C "%s"' % (ppath,
+                                                                   target_dir))
+        system('rm -f "%s"' % ppath)
 
 
 def copy_kinitrd(prj, target_dir, defs, arch="default"):
-- 
2.15.1




More information about the elbe-devel mailing list