From 713a624b0038f8bc67457d44bdfd6564a1f9b077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jelmer=20Vernoo=C4=B3?= Date: Mon, 8 Feb 2021 20:48:23 +0000 Subject: [PATCH] More work on resolvers. --- ognibuild/__main__.py | 44 ++++++++++++++++++++++++++++++++++++++++--- ognibuild/resolver.py | 39 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/ognibuild/__main__.py b/ognibuild/__main__.py index b0a330b..7dff0e3 100644 --- a/ognibuild/__main__.py +++ b/ognibuild/__main__.py @@ -18,14 +18,30 @@ import logging import os import sys +from . import UpstreamPackage from .buildsystem import NoBuildToolsFound from .build import run_build from .clean import run_clean from .dist import run_dist from .install import run_install +from .resolver import ( + AptResolver, + ExplainResolver, + AutoResolver, + NativeResolver, + MissingDependencies, + ) from .test import run_test +def install_declared_requirements(resolver, requirements, subcommand): + missing = [] + for req in requirements: + # TODO(jelmer): Look at stage + missing.append(UpstreamPackage(req.package.family, req.package.name)) + resolver.install(missing) + + def main(): import argparse @@ -41,6 +57,10 @@ def main(): '--resolve', choices=['explain', 'apt', 'native'], default='apt', help='What to do about missing dependencies') + parser.add_argument( + '--ignore-declared-dependencies', + action='store_true', + help='Ignore declared dependencies, follow build errors only') args = parser.parse_args() if args.schroot: from .session.schroot import SchrootSession @@ -52,16 +72,25 @@ def main(): session = PlainSession() with session: if args.resolve == 'apt': - from .resolver import AptResolver resolver = AptResolver.from_session(session) elif args.resolve == 'explain': - from .resolver import ExplainResolver resolver = ExplainResolver.from_session(session) elif args.resolve == 'native': - from .resolver import NativeResolver resolver = NativeResolver.from_session(session) + elif args.resolver == 'auto': + resolver = AutoResolver.from_session(session) os.chdir(args.directory) try: + if not args.ignore_declared_dependencies: + from upstream_ontologist.guess import get_upstream_info + buildsystem, requirements, metadata = get_upstream_info( + path=args.directory, + trust_package=True, + net_access=True, + consult_external_directory=True, + check=True) + install_declared_requirements( + resolver, requirements, args.subcommand) if args.subcommand == 'dist': run_dist(session=session, resolver=resolver) if args.subcommand == 'build': @@ -75,6 +104,15 @@ def main(): except NoBuildToolsFound: logging.info("No build tools found.") return 1 + except MissingDependencies as e: + for req in e.requirements: + note('Missing dependency (%s:%s)' % ( + req.family, req.name)) + for resolver in [ + AptResolver.from_session(session), + NativeResolver.from_session(session)]: + note(' %s' % (resolver.explain([req]), )) + return 2 return 0 diff --git a/ognibuild/resolver.py b/ognibuild/resolver.py index 288e9d7..dffb263 100644 --- a/ognibuild/resolver.py +++ b/ognibuild/resolver.py @@ -16,6 +16,12 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +class MissingDependencies(Exception): + + def __init__(self, reqs): + self.requirements = reqs + + class Resolver(object): def install(self, requirements): @@ -36,17 +42,31 @@ class AptResolver(Resolver): return cls(AptManager(session)) def install(self, requirements): - self.apt.install(list(self.resolve(requirements))) + missing = [] + for req in requirements: + pps = list(self._possible_paths(req)) + if (not pps or + not any(self.apt.session.exists(p) for p in pps)): + missing.append(req) + if missing: + self.apt.install(list(self.resolve(missing))) def explain(self, requirements): raise NotImplementedError(self.explain) + def _possible_paths(self, req): + if req.family == 'binary': + yield '/usr/bin/%s' % req.name + else: + return + def resolve(self, requirements): for req in requirements: if req.family == 'python3': yield 'python3-%s' % req.name else: - yield self.apt.find_file('/usr/bin/%s' % req.name) + path = list(self._possible_paths(req)) + raise NotImplementedError class NativeResolver(Resolver): @@ -67,6 +87,21 @@ class NativeResolver(Resolver): class ExplainResolver(Resolver): + def __init__(self, session): + self.session = session + + @classmethod + def from_session(cls, session): + return cls(session) + + def install(self, requirements): + raise MissingDependencies(requirements) + + +class AutoResolver(Resolver): + """Automatically find out the most appropriate way to instal dependencies. + """ + def __init__(self, session): self.session = session