diff options
| -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. | |||
| 35 | def opkg_query(cmd_output): | 35 | def 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 | ||
| 1400 | class OpkgPM(PackageManager): | 1412 | class 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 | |||
| 1475 | class 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 | ||
| 1736 | class DpkgPM(PackageManager): | 1837 | class 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 | ||
| 2031 | def generate_index_files(d): | 2159 | def generate_index_files(d): |
| 2032 | classes = d.getVar('PACKAGE_CLASSES', True).replace("package_", "").split() | 2160 | classes = d.getVar('PACKAGE_CLASSES', True).replace("package_", "").split() |
