diff options
author | Mariano Lopez <mariano.lopez@linux.intel.com> | 2016-05-12 11:28:13 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-05-14 07:26:40 +0100 |
commit | 7d214b34e11dc57316ed5c1c7747c4601286f6d2 (patch) | |
tree | ca31f00ec365bbaa446f7752d7357f101b31696a /meta/lib | |
parent | 799bc1d1c747aad02b6d844bf55abfbd3ecc034c (diff) | |
download | openembedded-core-7d214b34e11dc57316ed5c1c7747c4601286f6d2.tar.gz openembedded-core-7d214b34e11dc57316ed5c1c7747c4601286f6d2.tar.bz2 openembedded-core-7d214b34e11dc57316ed5c1c7747c4601286f6d2.zip |
package_manager.py: Add extract() method for opkg and dpkg
Sometimes it is needed to have the content of a package outside
the recipe context. This new method extract the content of an
IPK/DEB file to a tmpdir, without actually installing the package.
A new OpkgDpkgPM class was added to share the code for opkg and dpkg.
There were need some changes to opkg_query() in order to use it
with apt-cache output. Also set default values to avoid UnboundLocalError
[YOCTO #9569]
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib')
-rw-r--r-- | meta/lib/oe/package_manager.py | 140 |
1 files changed, 134 insertions, 6 deletions
diff --git a/meta/lib/oe/package_manager.py b/meta/lib/oe/package_manager.py index 427518da68..f5517a4aae 100644 --- a/meta/lib/oe/package_manager.py +++ b/meta/lib/oe/package_manager.py @@ -35,9 +35,12 @@ when the packages are in deb or ipk format. def opkg_query(cmd_output): verregex = re.compile(' \([=<>]* [^ )]*\)') output = dict() + pkg = "" + arch = "" + ver = "" filename = "" dep = [] - pkg = "" + pkgarch = "" for line in cmd_output.splitlines(): line = line.rstrip() if ':' in line: @@ -47,8 +50,10 @@ def opkg_query(cmd_output): arch = line.split(": ")[1] elif line.startswith("Version: "): ver = line.split(": ")[1] - elif line.startswith("File: "): + elif line.startswith("File: ") or line.startswith("Filename:"): filename = line.split(": ")[1] + if "/" in filename: + filename = os.path.basename(filename) elif line.startswith("Depends: "): depends = verregex.sub('', line.split(": ")[1]) for depend in depends.split(", "): @@ -57,16 +62,23 @@ def opkg_query(cmd_output): recommends = verregex.sub('', line.split(": ")[1]) for recommend in recommends.split(", "): dep.append("%s [REC]" % recommend) - else: + elif line.startswith("PackageArch: "): + pkgarch = line.split(": ")[1] + + # When there is a blank line save the package information + elif not line: # IPK doesn't include the filename if not filename: filename = "%s_%s_%s.ipk" % (pkg, ver, arch) if pkg: output[pkg] = {"arch":arch, "ver":ver, - "filename":filename, "deps": dep } + "filename":filename, "deps": dep, "pkgarch":pkgarch } pkg = "" + arch = "" + ver = "" filename = "" dep = [] + pkgarch = "" if pkg: if not filename: @@ -1397,7 +1409,70 @@ class RpmPM(PackageManager): bb.utils.remove(f, True) -class OpkgPM(PackageManager): +class OpkgDpkgPM(PackageManager): + """ + This is an abstract class. Do not instantiate this directly. + """ + def __init__(self, d): + super(OpkgDpkgPM, self).__init__(d) + + """ + Returns a dictionary with the package info. + + This method extracts the common parts for Opkg and Dpkg + """ + def package_info(self, pkg, cmd): + + try: + output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) + except subprocess.CalledProcessError as e: + bb.fatal("Unable to list available packages. Command '%s' " + "returned %d:\n%s" % (cmd, e.returncode, e.output)) + return opkg_query(output) + + """ + Returns the path to a tmpdir where resides the contents of a package. + + Deleting the tmpdir is responsability of the caller. + + This method extracts the common parts for Opkg and Dpkg + """ + def extract(self, pkg, pkg_path): + + ar_cmd = bb.utils.which(os.getenv("PATH"), "ar") + tar_cmd = bb.utils.which(os.getenv("PATH"), "tar") + + if not os.path.isfile(pkg_path): + bb.fatal("Unable to extract package for '%s'." + "File %s doesn't exists" % (pkg, pkg_path)) + + tmp_dir = tempfile.mkdtemp() + current_dir = os.getcwd() + os.chdir(tmp_dir) + + try: + cmd = "%s x %s" % (ar_cmd, pkg_path) + output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) + cmd = "%s xf data.tar.*" % tar_cmd + output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) + except subprocess.CalledProcessError as e: + bb.utils.remove(tmp_dir, recurse=True) + bb.fatal("Unable to extract %s package. Command '%s' " + "returned %d:\n%s" % (pkg_path, cmd, e.returncode, e.output)) + except OSError as e: + bb.utils.remove(tmp_dir, recurse=True) + bb.fatal("Unable to extract %s package. Command '%s' " + "returned %d:\n%s at %s" % (pkg_path, cmd, e.errno, e.strerror, e.filename)) + + bb.note("Extracted %s to %s" % (pkg_path, tmp_dir)) + bb.utils.remove(os.path.join(tmp_dir, "debian-binary")) + bb.utils.remove(os.path.join(tmp_dir, "control.tar.gz")) + os.chdir(current_dir) + + return tmp_dir + + +class OpkgPM(OpkgDpkgPM): def __init__(self, d, target_rootfs, config_file, archs, task_name='target'): super(OpkgPM, self).__init__(d) @@ -1732,8 +1807,34 @@ class OpkgPM(PackageManager): self.opkg_dir, symlinks=True) + """ + Returns a dictionary with the package info. + """ + def package_info(self, pkg): + cmd = "%s %s info %s" % (self.opkg_cmd, self.opkg_args, pkg) + return super(OpkgPM, self).package_info(pkg, cmd) + + """ + Returns the path to a tmpdir where resides the contents of a package. + + Deleting the tmpdir is responsability of the caller. + """ + def extract(self, pkg): + pkg_info = self.package_info(pkg) + if not pkg_info: + bb.fatal("Unable to get information for package '%s' while " + "trying to extract the package." % pkg) + + pkg_arch = pkg_info[pkg]["arch"] + pkg_filename = pkg_info[pkg]["filename"] + pkg_path = os.path.join(self.deploy_dir, pkg_arch, pkg_filename) + + tmp_dir = super(OpkgPM, self).extract(pkg, pkg_path) + bb.utils.remove(os.path.join(tmp_dir, "data.tar.gz")) + + return tmp_dir -class DpkgPM(PackageManager): +class DpkgPM(OpkgDpkgPM): def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None): super(DpkgPM, self).__init__(d) self.target_rootfs = target_rootfs @@ -1744,6 +1845,7 @@ class DpkgPM(PackageManager): self.apt_conf_dir = apt_conf_dir self.apt_conf_file = os.path.join(self.apt_conf_dir, "apt.conf") self.apt_get_cmd = bb.utils.which(os.getenv('PATH'), "apt-get") + self.apt_cache_cmd = bb.utils.which(os.getenv('PATH'), "apt-cache") self.apt_args = d.getVar("APT_ARGS", True) @@ -2027,6 +2129,32 @@ class DpkgPM(PackageManager): def list_installed(self): return DpkgPkgsList(self.d, self.target_rootfs).list_pkgs() + """ + Returns a dictionary with the package info. + """ + def package_info(self, pkg): + cmd = "%s show %s" % (self.apt_cache_cmd, pkg) + return super(DpkgPM, self).package_info(pkg, cmd) + + """ + Returns the path to a tmpdir where resides the contents of a package. + + Deleting the tmpdir is responsability of the caller. + """ + def extract(self, pkg): + pkg_info = self.package_info(pkg) + if not pkg_info: + bb.fatal("Unable to get information for package '%s' while " + "trying to extract the package." % pkg) + + pkg_arch = pkg_info[pkg]["pkgarch"] + pkg_filename = pkg_info[pkg]["filename"] + pkg_path = os.path.join(self.deploy_dir, pkg_arch, pkg_filename) + + tmp_dir = super(DpkgPM, self).extract(pkg, pkg_path) + bb.utils.remove(os.path.join(tmp_dir, "data.tar.xz")) + + return tmp_dir def generate_index_files(d): classes = d.getVar('PACKAGE_CLASSES', True).replace("package_", "").split() |