summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMariano Lopez <mariano.lopez@linux.intel.com>2016-05-12 11:28:13 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-05-14 23:05:11 +0100
commitb372a828182b924a8118c6cf4c7b45a7a093704b (patch)
treea80234d0a6264eb60abae8f89461f739aa8def83
parentc5aa5246e0177e2a7c08891c690479d94cf04c0d (diff)
downloadpoky-b372a828182b924a8118c6cf4c7b45a7a093704b.tar.gz
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] (From OE-Core rev: 7d214b34e11dc57316ed5c1c7747c4601286f6d2) Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/lib/oe/package_manager.py140
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.
35def opkg_query(cmd_output): 35def opkg_query(cmd_output):
36 verregex = re.compile(' \([=<>]* [^ )]*\)') 36 verregex = re.compile(' \([=<>]* [^ )]*\)')
37 output = dict() 37 output = dict()
38 pkg = ""
39 arch = ""
40 ver = ""
38 filename = "" 41 filename = ""
39 dep = [] 42 dep = []
40 pkg = "" 43 pkgarch = ""
41 for line in cmd_output.splitlines(): 44 for line in cmd_output.splitlines():
42 line = line.rstrip() 45 line = line.rstrip()
43 if ':' in line: 46 if ':' in line:
@@ -47,8 +50,10 @@ def opkg_query(cmd_output):
47 arch = line.split(": ")[1] 50 arch = line.split(": ")[1]
48 elif line.startswith("Version: "): 51 elif line.startswith("Version: "):
49 ver = line.split(": ")[1] 52 ver = line.split(": ")[1]
50 elif line.startswith("File: "): 53 elif line.startswith("File: ") or line.startswith("Filename:"):
51 filename = line.split(": ")[1] 54 filename = line.split(": ")[1]
55 if "/" in filename:
56 filename = os.path.basename(filename)
52 elif line.startswith("Depends: "): 57 elif line.startswith("Depends: "):
53 depends = verregex.sub('', line.split(": ")[1]) 58 depends = verregex.sub('', line.split(": ")[1])
54 for depend in depends.split(", "): 59 for depend in depends.split(", "):
@@ -57,16 +62,23 @@ def opkg_query(cmd_output):
57 recommends = verregex.sub('', line.split(": ")[1]) 62 recommends = verregex.sub('', line.split(": ")[1])
58 for recommend in recommends.split(", "): 63 for recommend in recommends.split(", "):
59 dep.append("%s [REC]" % recommend) 64 dep.append("%s [REC]" % recommend)
60 else: 65 elif line.startswith("PackageArch: "):
66 pkgarch = line.split(": ")[1]
67
68 # When there is a blank line save the package information
69 elif not line:
61 # IPK doesn't include the filename 70 # IPK doesn't include the filename
62 if not filename: 71 if not filename:
63 filename = "%s_%s_%s.ipk" % (pkg, ver, arch) 72 filename = "%s_%s_%s.ipk" % (pkg, ver, arch)
64 if pkg: 73 if pkg:
65 output[pkg] = {"arch":arch, "ver":ver, 74 output[pkg] = {"arch":arch, "ver":ver,
66 "filename":filename, "deps": dep } 75 "filename":filename, "deps": dep, "pkgarch":pkgarch }
67 pkg = "" 76 pkg = ""
77 arch = ""
78 ver = ""
68 filename = "" 79 filename = ""
69 dep = [] 80 dep = []
81 pkgarch = ""
70 82
71 if pkg: 83 if pkg:
72 if not filename: 84 if not filename:
@@ -1397,7 +1409,70 @@ class RpmPM(PackageManager):
1397 bb.utils.remove(f, True) 1409 bb.utils.remove(f, True)
1398 1410
1399 1411
1400class OpkgPM(PackageManager): 1412class OpkgDpkgPM(PackageManager):
1413 """
1414 This is an abstract class. Do not instantiate this directly.
1415 """
1416 def __init__(self, d):
1417 super(OpkgDpkgPM, self).__init__(d)
1418
1419 """
1420 Returns a dictionary with the package info.
1421
1422 This method extracts the common parts for Opkg and Dpkg
1423 """
1424 def package_info(self, pkg, cmd):
1425
1426 try:
1427 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
1428 except subprocess.CalledProcessError as e:
1429 bb.fatal("Unable to list available packages. Command '%s' "
1430 "returned %d:\n%s" % (cmd, e.returncode, e.output))
1431 return opkg_query(output)
1432
1433 """
1434 Returns the path to a tmpdir where resides the contents of a package.
1435
1436 Deleting the tmpdir is responsability of the caller.
1437
1438 This method extracts the common parts for Opkg and Dpkg
1439 """
1440 def extract(self, pkg, pkg_path):
1441
1442 ar_cmd = bb.utils.which(os.getenv("PATH"), "ar")
1443 tar_cmd = bb.utils.which(os.getenv("PATH"), "tar")
1444
1445 if not os.path.isfile(pkg_path):
1446 bb.fatal("Unable to extract package for '%s'."
1447 "File %s doesn't exists" % (pkg, pkg_path))
1448
1449 tmp_dir = tempfile.mkdtemp()
1450 current_dir = os.getcwd()
1451 os.chdir(tmp_dir)
1452
1453 try:
1454 cmd = "%s x %s" % (ar_cmd, pkg_path)
1455 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
1456 cmd = "%s xf data.tar.*" % tar_cmd
1457 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
1458 except subprocess.CalledProcessError as e:
1459 bb.utils.remove(tmp_dir, recurse=True)
1460 bb.fatal("Unable to extract %s package. Command '%s' "
1461 "returned %d:\n%s" % (pkg_path, cmd, e.returncode, e.output))
1462 except OSError as e:
1463 bb.utils.remove(tmp_dir, recurse=True)
1464 bb.fatal("Unable to extract %s package. Command '%s' "
1465 "returned %d:\n%s at %s" % (pkg_path, cmd, e.errno, e.strerror, e.filename))
1466
1467 bb.note("Extracted %s to %s" % (pkg_path, tmp_dir))
1468 bb.utils.remove(os.path.join(tmp_dir, "debian-binary"))
1469 bb.utils.remove(os.path.join(tmp_dir, "control.tar.gz"))
1470 os.chdir(current_dir)
1471
1472 return tmp_dir
1473
1474
1475class OpkgPM(OpkgDpkgPM):
1401 def __init__(self, d, target_rootfs, config_file, archs, task_name='target'): 1476 def __init__(self, d, target_rootfs, config_file, archs, task_name='target'):
1402 super(OpkgPM, self).__init__(d) 1477 super(OpkgPM, self).__init__(d)
1403 1478
@@ -1732,8 +1807,34 @@ class OpkgPM(PackageManager):
1732 self.opkg_dir, 1807 self.opkg_dir,
1733 symlinks=True) 1808 symlinks=True)
1734 1809
1810 """
1811 Returns a dictionary with the package info.
1812 """
1813 def package_info(self, pkg):
1814 cmd = "%s %s info %s" % (self.opkg_cmd, self.opkg_args, pkg)
1815 return super(OpkgPM, self).package_info(pkg, cmd)
1816
1817 """
1818 Returns the path to a tmpdir where resides the contents of a package.
1819
1820 Deleting the tmpdir is responsability of the caller.
1821 """
1822 def extract(self, pkg):
1823 pkg_info = self.package_info(pkg)
1824 if not pkg_info:
1825 bb.fatal("Unable to get information for package '%s' while "
1826 "trying to extract the package." % pkg)
1827
1828 pkg_arch = pkg_info[pkg]["arch"]
1829 pkg_filename = pkg_info[pkg]["filename"]
1830 pkg_path = os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
1831
1832 tmp_dir = super(OpkgPM, self).extract(pkg, pkg_path)
1833 bb.utils.remove(os.path.join(tmp_dir, "data.tar.gz"))
1834
1835 return tmp_dir
1735 1836
1736class DpkgPM(PackageManager): 1837class DpkgPM(OpkgDpkgPM):
1737 def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None): 1838 def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None):
1738 super(DpkgPM, self).__init__(d) 1839 super(DpkgPM, self).__init__(d)
1739 self.target_rootfs = target_rootfs 1840 self.target_rootfs = target_rootfs
@@ -1744,6 +1845,7 @@ class DpkgPM(PackageManager):
1744 self.apt_conf_dir = apt_conf_dir 1845 self.apt_conf_dir = apt_conf_dir
1745 self.apt_conf_file = os.path.join(self.apt_conf_dir, "apt.conf") 1846 self.apt_conf_file = os.path.join(self.apt_conf_dir, "apt.conf")
1746 self.apt_get_cmd = bb.utils.which(os.getenv('PATH'), "apt-get") 1847 self.apt_get_cmd = bb.utils.which(os.getenv('PATH'), "apt-get")
1848 self.apt_cache_cmd = bb.utils.which(os.getenv('PATH'), "apt-cache")
1747 1849
1748 self.apt_args = d.getVar("APT_ARGS", True) 1850 self.apt_args = d.getVar("APT_ARGS", True)
1749 1851
@@ -2027,6 +2129,32 @@ class DpkgPM(PackageManager):
2027 def list_installed(self): 2129 def list_installed(self):
2028 return DpkgPkgsList(self.d, self.target_rootfs).list_pkgs() 2130 return DpkgPkgsList(self.d, self.target_rootfs).list_pkgs()
2029 2131
2132 """
2133 Returns a dictionary with the package info.
2134 """
2135 def package_info(self, pkg):
2136 cmd = "%s show %s" % (self.apt_cache_cmd, pkg)
2137 return super(DpkgPM, self).package_info(pkg, cmd)
2138
2139 """
2140 Returns the path to a tmpdir where resides the contents of a package.
2141
2142 Deleting the tmpdir is responsability of the caller.
2143 """
2144 def extract(self, pkg):
2145 pkg_info = self.package_info(pkg)
2146 if not pkg_info:
2147 bb.fatal("Unable to get information for package '%s' while "
2148 "trying to extract the package." % pkg)
2149
2150 pkg_arch = pkg_info[pkg]["pkgarch"]
2151 pkg_filename = pkg_info[pkg]["filename"]
2152 pkg_path = os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
2153
2154 tmp_dir = super(DpkgPM, self).extract(pkg, pkg_path)
2155 bb.utils.remove(os.path.join(tmp_dir, "data.tar.xz"))
2156
2157 return tmp_dir
2030 2158
2031def generate_index_files(d): 2159def generate_index_files(d):
2032 classes = d.getVar('PACKAGE_CLASSES', True).replace("package_", "").split() 2160 classes = d.getVar('PACKAGE_CLASSES', True).replace("package_", "").split()