""" Copyright 2018 Oliver Smith This file is part of pmbootstrap. pmbootstrap is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. pmbootstrap is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with pmbootstrap. If not, see . """ import logging import pmb.chroot import pmb.chroot.apk import pmb.parse.apkindex def recurse_error_message(pkgname, in_aports, in_apkindexes): ret = "Could not find package '" + pkgname + "'" if in_aports: ret += " in the aports folder" if in_apkindexes: ret += " and could not find it" if in_apkindexes: ret += " in any APKINDEX" return ret + "." def recurse(args, pkgnames, arch=None, in_apkindexes=True, in_aports=True, strict=False): """ Find all dependencies of the given pkgnames. :param in_apkindexes: look through all APKINDEX files (with the specified arch) :param in_aports: look through the aports folder :param strict: raise RuntimeError, when a dependency can not be found. """ logging.debug("Calculate depends of packages " + str(pkgnames) + ", arch: " + arch) logging.verbose("Search in_aports: " + str(in_aports) + ", in_apkindexes: " + str(in_apkindexes)) # Sanity check if not in_apkindexes and not in_aports: raise RuntimeError("Set at least one of in_apkindexes or in_aports to" " True.") # Iterate over todo-list until is is empty todo = list(pkgnames) ret = [] while len(todo): # Skip already passed entries pkgname_depend = todo.pop(0) if pkgname_depend in ret: continue # Get depends and pkgname from aports depends = None pkgname = None version = None if in_aports: aport = pmb.build.find_aport(args, pkgname_depend, False) if aport: apkbuild = pmb.parse.apkbuild(args, aport + "/APKBUILD") depends = apkbuild["depends"] version = apkbuild["pkgver"] + "-r" + apkbuild["pkgrel"] logging.verbose(pkgname_depend + ": " + version + " found in " + aport) if pkgname_depend in apkbuild["subpackages"]: pkgname = pkgname_depend else: pkgname = apkbuild["pkgname"] # Get depends and pkgname from APKINDEX if in_apkindexes: index_data = pmb.parse.apkindex.read_any_index(args, pkgname_depend, arch) if index_data: # The binary package's depends override the aport's depends in # case it has the same or a higher version. Binary packages have # sonames in their dependencies, which we need to detect # breakage (#893). outdated = (version and pmb.parse.version.compare(version, index_data["version"]) == 1) if not outdated: if version: logging.verbose(pkgname_depend + ": binary package is" " up to date, using binary dependencies" " instead of the ones from the aport") depends = index_data["depends"] pkgname = index_data["pkgname"] # Nothing found if pkgname is None and strict: logging.info("NOTE: Run 'pmbootstrap pkgrel_bump --auto' to mark" " packages with outdated dependencies for rebuild." " This will most likely fix this issue (soname" " bump?).") logging.info("NOTE: More dependency calculation logging with" " 'pmbootstrap -v'.") raise RuntimeError( recurse_error_message( pkgname_depend, in_aports, in_apkindexes)) # Append to todo/ret (unless it is a duplicate) if pkgname != pkgname_depend: logging.verbose(pkgname_depend + ": provided by '" + pkgname + "'") if pkgname in ret: logging.verbose(pkgname + ": already found") else: logging.verbose(pkgname + ": depends on: " + ",".join(depends)) if depends: todo += depends ret.append(pkgname) return ret