diff options
| -rw-r--r-- | meta/lib/oe/package_manager/__init__.py | 78 | ||||
| -rw-r--r-- | meta/lib/oe/package_manager/deb/__init__.py | 26 | ||||
| -rw-r--r-- | meta/lib/oe/package_manager/ipk/__init__.py | 20 | ||||
| -rw-r--r-- | meta/lib/oe/package_manager/rpm/__init__.py | 8 | ||||
| -rwxr-xr-x | scripts/oe-pkgdata-util | 14 |
5 files changed, 111 insertions, 35 deletions
diff --git a/meta/lib/oe/package_manager/__init__.py b/meta/lib/oe/package_manager/__init__.py index 88bc5ab195..b9a4218939 100644 --- a/meta/lib/oe/package_manager/__init__.py +++ b/meta/lib/oe/package_manager/__init__.py | |||
| @@ -32,7 +32,7 @@ def create_index(arg): | |||
| 32 | 32 | ||
| 33 | def opkg_query(cmd_output): | 33 | def opkg_query(cmd_output): |
| 34 | """ | 34 | """ |
| 35 | This method parse the output from the package managerand return | 35 | This method parse the output from the package manager and return |
| 36 | a dictionary with the information of the packages. This is used | 36 | a dictionary with the information of the packages. This is used |
| 37 | when the packages are in deb or ipk format. | 37 | when the packages are in deb or ipk format. |
| 38 | """ | 38 | """ |
| @@ -369,40 +369,48 @@ class PackageManager(object, metaclass=ABCMeta): | |||
| 369 | if globs: | 369 | if globs: |
| 370 | # we need to write the list of installed packages to a file because the | 370 | # we need to write the list of installed packages to a file because the |
| 371 | # oe-pkgdata-util reads it from a file | 371 | # oe-pkgdata-util reads it from a file |
| 372 | with tempfile.NamedTemporaryFile(mode="w+", prefix="installed-pkgs") as installed_pkgs: | 372 | with tempfile.NamedTemporaryFile(mode="w+", prefix="all-pkgs") as all_pkgs: |
| 373 | pkgs = self.list_installed() | 373 | with tempfile.NamedTemporaryFile(mode="w+", prefix="installed-pkgs") as installed_pkgs: |
| 374 | 374 | pkgs = self.list_installed() | |
| 375 | provided_pkgs = set() | 375 | |
| 376 | for pkg in pkgs.values(): | 376 | provided_pkgs = set() |
| 377 | provided_pkgs |= set(pkg.get('provs', [])) | 377 | for pkg in pkgs.values(): |
| 378 | 378 | provided_pkgs |= set(pkg.get('provs', [])) | |
| 379 | output = oe.utils.format_pkg_list(pkgs, "arch") | 379 | |
| 380 | installed_pkgs.write(output) | 380 | output = oe.utils.format_pkg_list(pkgs, "arch") |
| 381 | installed_pkgs.flush() | 381 | installed_pkgs.write(output) |
| 382 | 382 | installed_pkgs.flush() | |
| 383 | cmd = ["oe-pkgdata-util", | 383 | |
| 384 | "-p", self.d.getVar('PKGDATA_DIR'), "glob", installed_pkgs.name, | 384 | cmd = ["oe-pkgdata-util", |
| 385 | globs] | 385 | "-p", self.d.getVar('PKGDATA_DIR'), "glob", |
| 386 | exclude = self.d.getVar('PACKAGE_EXCLUDE_COMPLEMENTARY') | 386 | installed_pkgs.name, globs] |
| 387 | if exclude: | 387 | |
| 388 | cmd.extend(['--exclude=' + '|'.join(exclude.split())]) | 388 | if hasattr(self, "list_all"): |
| 389 | try: | 389 | output_allpkg = self.list_all() |
| 390 | bb.note('Running %s' % cmd) | 390 | all_pkgs.write(output_allpkg) |
| 391 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 391 | all_pkgs.flush() |
| 392 | stdout, stderr = proc.communicate() | 392 | cmd.extend(["--allpkgs=%s" % all_pkgs.name]) |
| 393 | if stderr: bb.note(stderr.decode("utf-8")) | 393 | |
| 394 | complementary_pkgs = stdout.decode("utf-8") | 394 | exclude = self.d.getVar('PACKAGE_EXCLUDE_COMPLEMENTARY') |
| 395 | complementary_pkgs = set(complementary_pkgs.split()) | 395 | if exclude: |
| 396 | skip_pkgs = sorted(complementary_pkgs & provided_pkgs) | 396 | cmd.extend(['--exclude=' + '|'.join(exclude.split())]) |
| 397 | install_pkgs = sorted(complementary_pkgs - provided_pkgs) | 397 | try: |
| 398 | bb.note("Installing complementary packages ... %s (skipped already provided packages %s)" % ( | 398 | bb.note('Running %s' % cmd) |
| 399 | ' '.join(install_pkgs), | 399 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 400 | ' '.join(skip_pkgs))) | 400 | stdout, stderr = proc.communicate() |
| 401 | self.install(install_pkgs, hard_depends_only=True) | 401 | if stderr: bb.note(stderr.decode("utf-8")) |
| 402 | except subprocess.CalledProcessError as e: | 402 | complementary_pkgs = stdout.decode("utf-8") |
| 403 | bb.fatal("Could not compute complementary packages list. Command " | 403 | complementary_pkgs = set(complementary_pkgs.split()) |
| 404 | "'%s' returned %d:\n%s" % | 404 | skip_pkgs = sorted(complementary_pkgs & provided_pkgs) |
| 405 | (' '.join(cmd), e.returncode, e.output.decode("utf-8"))) | 405 | install_pkgs = sorted(complementary_pkgs - provided_pkgs) |
| 406 | bb.note("Installing complementary packages ... %s (skipped already provided packages %s)" % ( | ||
| 407 | ' '.join(install_pkgs), | ||
| 408 | ' '.join(skip_pkgs))) | ||
| 409 | self.install(install_pkgs, hard_depends_only=True) | ||
| 410 | except subprocess.CalledProcessError as e: | ||
| 411 | bb.fatal("Could not compute complementary packages list. Command " | ||
| 412 | "'%s' returned %d:\n%s" % | ||
| 413 | (' '.join(cmd), e.returncode, e.output.decode("utf-8"))) | ||
| 406 | 414 | ||
| 407 | if self.d.getVar('IMAGE_LOCALES_ARCHIVE') == '1': | 415 | if self.d.getVar('IMAGE_LOCALES_ARCHIVE') == '1': |
| 408 | target_arch = self.d.getVar('TARGET_ARCH') | 416 | target_arch = self.d.getVar('TARGET_ARCH') |
diff --git a/meta/lib/oe/package_manager/deb/__init__.py b/meta/lib/oe/package_manager/deb/__init__.py index eb48f3f982..0f74e1322f 100644 --- a/meta/lib/oe/package_manager/deb/__init__.py +++ b/meta/lib/oe/package_manager/deb/__init__.py | |||
| @@ -112,6 +112,29 @@ class PMPkgsList(PkgsList): | |||
| 112 | 112 | ||
| 113 | return opkg_query(cmd_output) | 113 | return opkg_query(cmd_output) |
| 114 | 114 | ||
| 115 | def list_all_pkgs(self, apt_conf_file=None): | ||
| 116 | if not apt_conf_file: | ||
| 117 | apt_conf_file = self.d.expand("${APTCONF_TARGET}/apt/apt.conf") | ||
| 118 | os.environ['APT_CONFIG'] = apt_conf_file | ||
| 119 | |||
| 120 | cmd = [bb.utils.which(os.getenv('PATH'), "apt"), "list"] | ||
| 121 | |||
| 122 | try: | ||
| 123 | cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).strip().decode("utf-8") | ||
| 124 | except subprocess.CalledProcessError as e: | ||
| 125 | bb.fatal("Cannot get the all packages list. Command '%s' " | ||
| 126 | "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8"))) | ||
| 127 | |||
| 128 | all_pkgs_lines = [] | ||
| 129 | for line in cmd_output.splitlines(): | ||
| 130 | line_parts = line.split() | ||
| 131 | # the valid lines takes the format of something like "findutils-locale-ga/unknown 4.10.0-r0 amd64" | ||
| 132 | if len(line_parts) != 3: | ||
| 133 | continue | ||
| 134 | line_parts[0] = line_parts[0].split('/')[0] | ||
| 135 | new_line = ' '.join(line_parts) | ||
| 136 | all_pkgs_lines.append(new_line) | ||
| 137 | return "\n".join(all_pkgs_lines) | ||
| 115 | 138 | ||
| 116 | class DpkgPM(OpkgDpkgPM): | 139 | class DpkgPM(OpkgDpkgPM): |
| 117 | def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None, deb_repo_workdir="oe-rootfs-repo", filterbydependencies=True): | 140 | def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None, deb_repo_workdir="oe-rootfs-repo", filterbydependencies=True): |
| @@ -436,6 +459,9 @@ class DpkgPM(OpkgDpkgPM): | |||
| 436 | def list_installed(self): | 459 | def list_installed(self): |
| 437 | return PMPkgsList(self.d, self.target_rootfs).list_pkgs() | 460 | return PMPkgsList(self.d, self.target_rootfs).list_pkgs() |
| 438 | 461 | ||
| 462 | def list_all(self): | ||
| 463 | return PMPkgsList(self.d, self.target_rootfs).list_all_pkgs(apt_conf_file=self.apt_conf_file) | ||
| 464 | |||
| 439 | def package_info(self, pkg): | 465 | def package_info(self, pkg): |
| 440 | """ | 466 | """ |
| 441 | Returns a dictionary with the package info. | 467 | Returns a dictionary with the package info. |
diff --git a/meta/lib/oe/package_manager/ipk/__init__.py b/meta/lib/oe/package_manager/ipk/__init__.py index 4794f31f88..2f330ec4f0 100644 --- a/meta/lib/oe/package_manager/ipk/__init__.py +++ b/meta/lib/oe/package_manager/ipk/__init__.py | |||
| @@ -90,6 +90,23 @@ class PMPkgsList(PkgsList): | |||
| 90 | 90 | ||
| 91 | return opkg_query(cmd_output) | 91 | return opkg_query(cmd_output) |
| 92 | 92 | ||
| 93 | def list_all_pkgs(self, format=None): | ||
| 94 | cmd = "%s %s list" % (self.opkg_cmd, self.opkg_args) | ||
| 95 | |||
| 96 | # opkg returns success even when it printed some | ||
| 97 | # "Collected errors:" report to stderr. Mixing stderr into | ||
| 98 | # stdout then leads to random failures later on when | ||
| 99 | # parsing the output. To avoid this we need to collect both | ||
| 100 | # output streams separately and check for empty stderr. | ||
| 101 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) | ||
| 102 | cmd_output, cmd_stderr = p.communicate() | ||
| 103 | cmd_output = cmd_output.decode("utf-8") | ||
| 104 | cmd_stderr = cmd_stderr.decode("utf-8") | ||
| 105 | if p.returncode or cmd_stderr: | ||
| 106 | bb.fatal("Cannot get all packages list. Command '%s' " | ||
| 107 | "returned %d and stderr:\n%s" % (cmd, p.returncode, cmd_stderr)) | ||
| 108 | |||
| 109 | return cmd_output | ||
| 93 | 110 | ||
| 94 | class OpkgPM(OpkgDpkgPM): | 111 | class OpkgPM(OpkgDpkgPM): |
| 95 | def __init__(self, d, target_rootfs, config_file, archs, task_name='target', ipk_repo_workdir="oe-rootfs-repo", filterbydependencies=True, prepare_index=True): | 112 | def __init__(self, d, target_rootfs, config_file, archs, task_name='target', ipk_repo_workdir="oe-rootfs-repo", filterbydependencies=True, prepare_index=True): |
| @@ -364,6 +381,9 @@ class OpkgPM(OpkgDpkgPM): | |||
| 364 | def list_installed(self): | 381 | def list_installed(self): |
| 365 | return PMPkgsList(self.d, self.target_rootfs).list_pkgs() | 382 | return PMPkgsList(self.d, self.target_rootfs).list_pkgs() |
| 366 | 383 | ||
| 384 | def list_all(self): | ||
| 385 | return PMPkgsList(self.d, self.target_rootfs).list_all_pkgs() | ||
| 386 | |||
| 367 | def dummy_install(self, pkgs): | 387 | def dummy_install(self, pkgs): |
| 368 | """ | 388 | """ |
| 369 | The following function dummy installs pkgs and returns the log of output. | 389 | The following function dummy installs pkgs and returns the log of output. |
diff --git a/meta/lib/oe/package_manager/rpm/__init__.py b/meta/lib/oe/package_manager/rpm/__init__.py index 20e6cb8744..a51057650a 100644 --- a/meta/lib/oe/package_manager/rpm/__init__.py +++ b/meta/lib/oe/package_manager/rpm/__init__.py | |||
| @@ -275,6 +275,14 @@ class RpmPM(PackageManager): | |||
| 275 | elif os.path.isfile(source_dir): | 275 | elif os.path.isfile(source_dir): |
| 276 | shutil.copy2(source_dir, target_dir) | 276 | shutil.copy2(source_dir, target_dir) |
| 277 | 277 | ||
| 278 | def list_all(self): | ||
| 279 | output = self._invoke_dnf(["repoquery", "--all", "--queryformat", "Packages: %{name} %{arch} %{version}"], print_output = False) | ||
| 280 | all_pkgs_lines = [] | ||
| 281 | for line in output.splitlines(): | ||
| 282 | if line.startswith("Packages: "): | ||
| 283 | all_pkgs_lines.append(line.replace("Packages: ", "")) | ||
| 284 | return "\n".join(all_pkgs_lines) | ||
| 285 | |||
| 278 | def list_installed(self): | 286 | def list_installed(self): |
| 279 | output = self._invoke_dnf(["repoquery", "--installed", "--queryformat", "Package: %{name} %{arch} %{version} %{name}-%{version}-%{release}.%{arch}.rpm\nDependencies:\n%{requires}\nRecommendations:\n%{recommends}\nDependenciesEndHere:\n"], | 287 | output = self._invoke_dnf(["repoquery", "--installed", "--queryformat", "Package: %{name} %{arch} %{version} %{name}-%{version}-%{release}.%{arch}.rpm\nDependencies:\n%{requires}\nRecommendations:\n%{recommends}\nDependenciesEndHere:\n"], |
| 280 | print_output = False) | 288 | print_output = False) |
diff --git a/scripts/oe-pkgdata-util b/scripts/oe-pkgdata-util index 44ae40549a..5b7cd768a4 100755 --- a/scripts/oe-pkgdata-util +++ b/scripts/oe-pkgdata-util | |||
| @@ -51,6 +51,15 @@ def glob(args): | |||
| 51 | 51 | ||
| 52 | skippedpkgs = set() | 52 | skippedpkgs = set() |
| 53 | mappedpkgs = set() | 53 | mappedpkgs = set() |
| 54 | allpkgs = set() | ||
| 55 | if args.allpkgs: | ||
| 56 | with open(args.allpkgs, 'r') as f: | ||
| 57 | for line in f: | ||
| 58 | fields = line.rstrip().split() | ||
| 59 | if not fields: | ||
| 60 | continue | ||
| 61 | else: | ||
| 62 | allpkgs.add(fields[0]) | ||
| 54 | with open(args.pkglistfile, 'r') as f: | 63 | with open(args.pkglistfile, 'r') as f: |
| 55 | for line in f: | 64 | for line in f: |
| 56 | fields = line.rstrip().split() | 65 | fields = line.rstrip().split() |
| @@ -136,6 +145,10 @@ def glob(args): | |||
| 136 | logger.debug("%s is not a valid package!" % (pkg)) | 145 | logger.debug("%s is not a valid package!" % (pkg)) |
| 137 | break | 146 | break |
| 138 | 147 | ||
| 148 | if args.allpkgs: | ||
| 149 | if mappedpkg not in allpkgs: | ||
| 150 | continue | ||
| 151 | |||
| 139 | if mappedpkg: | 152 | if mappedpkg: |
| 140 | logger.debug("%s (%s) -> %s" % (pkg, g, mappedpkg)) | 153 | logger.debug("%s (%s) -> %s" % (pkg, g, mappedpkg)) |
| 141 | mappedpkgs.add(mappedpkg) | 154 | mappedpkgs.add(mappedpkg) |
| @@ -592,6 +605,7 @@ def main(): | |||
| 592 | parser_glob.add_argument('pkglistfile', help='File listing packages (one package name per line)') | 605 | parser_glob.add_argument('pkglistfile', help='File listing packages (one package name per line)') |
| 593 | parser_glob.add_argument('glob', nargs="+", help='Glob expression for package names, e.g. *-dev') | 606 | parser_glob.add_argument('glob', nargs="+", help='Glob expression for package names, e.g. *-dev') |
| 594 | parser_glob.add_argument('-x', '--exclude', help='Exclude packages matching specified regex from the glob operation') | 607 | parser_glob.add_argument('-x', '--exclude', help='Exclude packages matching specified regex from the glob operation') |
| 608 | parser_glob.add_argument('-a', '--allpkgs', help='File listing all available packages (one package name per line)') | ||
| 595 | parser_glob.set_defaults(func=glob) | 609 | parser_glob.set_defaults(func=glob) |
| 596 | 610 | ||
| 597 | 611 | ||
