More fixes.
This commit is contained in:
parent
aa2a3e47fa
commit
6b30479b97
9 changed files with 499 additions and 320 deletions
|
@ -23,7 +23,7 @@ from .buildsystem import NoBuildToolsFound, detect_buildsystems
|
||||||
from .resolver import (
|
from .resolver import (
|
||||||
ExplainResolver,
|
ExplainResolver,
|
||||||
AutoResolver,
|
AutoResolver,
|
||||||
NativeResolver,
|
native_resolvers,
|
||||||
MissingDependencies,
|
MissingDependencies,
|
||||||
)
|
)
|
||||||
from .resolver.apt import AptResolver
|
from .resolver.apt import AptResolver
|
||||||
|
@ -91,6 +91,9 @@ def main(): # noqa: C901
|
||||||
'--user', action='store_true', help='Install in local-user directories.')
|
'--user', action='store_true', help='Install in local-user directories.')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
if not args.subcommand:
|
||||||
|
parser.print_usage()
|
||||||
|
return 1
|
||||||
if args.verbose:
|
if args.verbose:
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
else:
|
else:
|
||||||
|
@ -109,7 +112,7 @@ def main(): # noqa: C901
|
||||||
elif args.resolve == "explain":
|
elif args.resolve == "explain":
|
||||||
resolver = ExplainResolver.from_session(session)
|
resolver = ExplainResolver.from_session(session)
|
||||||
elif args.resolve == "native":
|
elif args.resolve == "native":
|
||||||
resolver = NativeResolver.from_session(session)
|
resolver = native_resolvers(session)
|
||||||
elif args.resolver == "auto":
|
elif args.resolver == "auto":
|
||||||
resolver = AutoResolver.from_session(session)
|
resolver = AutoResolver.from_session(session)
|
||||||
os.chdir(args.directory)
|
os.chdir(args.directory)
|
||||||
|
@ -149,10 +152,10 @@ def main(): # noqa: C901
|
||||||
except MissingDependencies as e:
|
except MissingDependencies as e:
|
||||||
for req in e.requirements:
|
for req in e.requirements:
|
||||||
logging.info("Missing dependency (%s:%s)",
|
logging.info("Missing dependency (%s:%s)",
|
||||||
req.family, req.name)
|
req.family, req.package)
|
||||||
for resolver in [
|
for resolver in [
|
||||||
AptResolver.from_session(session),
|
AptResolver.from_session(session),
|
||||||
NativeResolver.from_session(session),
|
native_resolvers(session),
|
||||||
]:
|
]:
|
||||||
logging.info(" %s", resolver.explain([req]))
|
logging.info(" %s", resolver.explain([req]))
|
||||||
return 2
|
return 2
|
||||||
|
|
192
ognibuild/buildlog.py
Normal file
192
ognibuild/buildlog.py
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
# Copyright (C) 2020 Jelmer Vernooij <jelmer@jelmer.uk>
|
||||||
|
#
|
||||||
|
# This program 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 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
"""Convert problems found in the buildlog to upstream requirements.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from buildlog_consultant.common import (
|
||||||
|
MissingConfigStatusInput,
|
||||||
|
MissingPythonModule,
|
||||||
|
MissingPythonDistribution,
|
||||||
|
MissingCHeader,
|
||||||
|
MissingPkgConfig,
|
||||||
|
MissingCommand,
|
||||||
|
MissingFile,
|
||||||
|
MissingJavaScriptRuntime,
|
||||||
|
MissingSprocketsFile,
|
||||||
|
MissingGoPackage,
|
||||||
|
MissingPerlFile,
|
||||||
|
MissingPerlModule,
|
||||||
|
MissingXmlEntity,
|
||||||
|
MissingJDKFile,
|
||||||
|
MissingNodeModule,
|
||||||
|
MissingPhpClass,
|
||||||
|
MissingRubyGem,
|
||||||
|
MissingLibrary,
|
||||||
|
MissingJavaClass,
|
||||||
|
MissingCSharpCompiler,
|
||||||
|
MissingConfigure,
|
||||||
|
MissingAutomakeInput,
|
||||||
|
MissingRPackage,
|
||||||
|
MissingRubyFile,
|
||||||
|
MissingAutoconfMacro,
|
||||||
|
MissingValaPackage,
|
||||||
|
MissingXfceDependency,
|
||||||
|
MissingHaskellDependencies,
|
||||||
|
NeedPgBuildExtUpdateControl,
|
||||||
|
DhAddonLoadFailure,
|
||||||
|
MissingMavenArtifacts,
|
||||||
|
GnomeCommonMissing,
|
||||||
|
MissingGnomeCommonDependency,
|
||||||
|
)
|
||||||
|
|
||||||
|
from .fix_build import BuildFixer
|
||||||
|
from .requirements import (
|
||||||
|
BinaryRequirement,
|
||||||
|
PathRequirement,
|
||||||
|
PkgConfigRequirement,
|
||||||
|
CHeaderRequirement,
|
||||||
|
JavaScriptRuntimeRequirement,
|
||||||
|
ValaPackageRequirement,
|
||||||
|
RubyGemRequirement,
|
||||||
|
GoPackageRequirement,
|
||||||
|
DhAddonRequirement,
|
||||||
|
PhpClassRequirement,
|
||||||
|
RPackageRequirement,
|
||||||
|
NodePackageRequirement,
|
||||||
|
LibraryRequirement,
|
||||||
|
RubyFileRequirement,
|
||||||
|
XmlEntityRequirement,
|
||||||
|
SprocketsFileRequirement,
|
||||||
|
JavaClassRequirement,
|
||||||
|
HaskellPackageRequirement,
|
||||||
|
MavenArtifactRequirement,
|
||||||
|
GnomeCommonRequirement,
|
||||||
|
JDKFileRequirement,
|
||||||
|
PerlModuleRequirement,
|
||||||
|
PerlFileRequirement,
|
||||||
|
AutoconfMacroRequirement,
|
||||||
|
PythonModuleRequirement,
|
||||||
|
PythonPackageRequirement,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def problem_to_upstream_requirement(problem):
|
||||||
|
if isinstance(problem, MissingFile):
|
||||||
|
return PathRequirement(problem.path)
|
||||||
|
elif isinstance(problem, MissingCommand):
|
||||||
|
return BinaryRequirement(problem.command)
|
||||||
|
elif isinstance(problem, MissingPkgConfig):
|
||||||
|
return PkgConfigRequirement(
|
||||||
|
problem.module, problem.minimum_version)
|
||||||
|
elif isinstance(problem, MissingCHeader):
|
||||||
|
return CHeaderRequirement(problem.header)
|
||||||
|
elif isinstance(problem, MissingJavaScriptRuntime):
|
||||||
|
return JavaScriptRuntimeRequirement()
|
||||||
|
elif isinstance(problem, MissingRubyGem):
|
||||||
|
return RubyGemRequirement(problem.gem, problem.version)
|
||||||
|
elif isinstance(problem, MissingValaPackage):
|
||||||
|
return ValaPackageRequirement(problem.package)
|
||||||
|
elif isinstance(problem, MissingGoPackage):
|
||||||
|
return GoPackageRequirement(problem.package)
|
||||||
|
elif isinstance(problem, DhAddonLoadFailure):
|
||||||
|
return DhAddonRequirement(problem.path)
|
||||||
|
elif isinstance(problem, MissingPhpClass):
|
||||||
|
return PhpClassRequirement(problem.php_class)
|
||||||
|
elif isinstance(problem, MissingRPackage):
|
||||||
|
return RPackageRequirement(problem.package, problem.minimum_version)
|
||||||
|
elif isinstance(problem, MissingNodeModule):
|
||||||
|
return NodePackageRequirement(problem.module)
|
||||||
|
elif isinstance(problem, MissingLibrary):
|
||||||
|
return LibraryRequirement(problem.library)
|
||||||
|
elif isinstance(problem, MissingRubyFile):
|
||||||
|
return RubyFileRequirement(problem.filename)
|
||||||
|
elif isinstance(problem, MissingXmlEntity):
|
||||||
|
return XmlEntityRequirement(problem.url)
|
||||||
|
elif isinstance(problem, MissingSprocketsFile):
|
||||||
|
return SprocketsFileRequirement(problem.content_type, problem.name)
|
||||||
|
elif isinstance(problem, MissingJavaClass):
|
||||||
|
return JavaClassRequirement(problem.classname)
|
||||||
|
elif isinstance(problem, MissingHaskellDependencies):
|
||||||
|
# TODO(jelmer): Create multiple HaskellPackageRequirement objects?
|
||||||
|
return HaskellPackageRequirement(problem.package)
|
||||||
|
elif isinstance(problem, MissingMavenArtifacts):
|
||||||
|
# TODO(jelmer): Create multiple MavenArtifactRequirement objects?
|
||||||
|
return MavenArtifactRequirement(problem.artifacts)
|
||||||
|
elif isinstance(problem, MissingCSharpCompiler):
|
||||||
|
return BinaryRequirement('msc')
|
||||||
|
elif isinstance(problem, GnomeCommonMissing):
|
||||||
|
return GnomeCommonRequirement()
|
||||||
|
elif isinstance(problem, MissingJDKFile):
|
||||||
|
return JDKFileRequirement(problem.jdk_path, problem.filename)
|
||||||
|
elif isinstance(problem, MissingGnomeCommonDependency):
|
||||||
|
if problem.package == "glib-gettext":
|
||||||
|
return BinaryRequirement('glib-gettextize')
|
||||||
|
else:
|
||||||
|
logging.warning(
|
||||||
|
"No known command for gnome-common dependency %s",
|
||||||
|
problem.package)
|
||||||
|
return None
|
||||||
|
elif isinstance(problem, MissingXfceDependency):
|
||||||
|
if problem.package == "gtk-doc":
|
||||||
|
return BinaryRequirement("gtkdocize")
|
||||||
|
else:
|
||||||
|
logging.warning(
|
||||||
|
"No known command for xfce dependency %s",
|
||||||
|
problem.package)
|
||||||
|
return None
|
||||||
|
elif isinstance(problem, MissingPerlModule):
|
||||||
|
return PerlModuleRequirement(
|
||||||
|
module=problem.module,
|
||||||
|
filename=problem.filename,
|
||||||
|
inc=problem.inc)
|
||||||
|
elif isinstance(problem, MissingPerlFile):
|
||||||
|
return PerlFileRequirement(filename=problem.filename)
|
||||||
|
elif isinstance(problem, MissingAutoconfMacro):
|
||||||
|
return AutoconfMacroRequirement(problem.macro)
|
||||||
|
elif isinstance(problem, MissingPythonModule):
|
||||||
|
return PythonModuleRequirement(
|
||||||
|
problem.module,
|
||||||
|
python_version=problem.python_version,
|
||||||
|
minimum_version=problem.minimum_version)
|
||||||
|
elif isinstance(problem, MissingPythonDistribution):
|
||||||
|
return PythonPackageRequirement(
|
||||||
|
problem.module,
|
||||||
|
python_version=problem.python_version,
|
||||||
|
minimum_version=problem.minimum_version)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class UpstreamRequirementFixer(BuildFixer):
|
||||||
|
|
||||||
|
def __init__(self, resolver):
|
||||||
|
self.resolver = resolver
|
||||||
|
|
||||||
|
def can_fix(self, error):
|
||||||
|
req = problem_to_upstream_requirement(error)
|
||||||
|
return req is not None
|
||||||
|
|
||||||
|
def fix(self, error, context):
|
||||||
|
req = problem_to_upstream_requirement(error)
|
||||||
|
if req is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
package = self.resolver.resolve(req)
|
||||||
|
return context.add_dependency(package)
|
|
@ -182,17 +182,19 @@ class SetupPy(BuildSystem):
|
||||||
def get_declared_dependencies(self):
|
def get_declared_dependencies(self):
|
||||||
for require in self.result.get_requires():
|
for require in self.result.get_requires():
|
||||||
yield "build", PythonPackageRequirement(require)
|
yield "build", PythonPackageRequirement(require)
|
||||||
if self.result.install_requires:
|
# Not present for distutils-only packages
|
||||||
|
if getattr(self.result, 'install_requires', []):
|
||||||
for require in self.result.install_requires:
|
for require in self.result.install_requires:
|
||||||
yield "install", PythonPackageRequirement(require)
|
yield "install", PythonPackageRequirement(require)
|
||||||
if self.result.tests_require:
|
# Not present for distutils-only packages
|
||||||
|
if getattr(self.result, 'tests_require', []):
|
||||||
for require in self.result.tests_require:
|
for require in self.result.tests_require:
|
||||||
yield "test", PythonPackageRequirement(require)
|
yield "test", PythonPackageRequirement(require)
|
||||||
|
|
||||||
def get_declared_outputs(self):
|
def get_declared_outputs(self):
|
||||||
for script in self.result.scripts or []:
|
for script in self.result.scripts or []:
|
||||||
yield UpstreamOutput("binary", os.path.basename(script))
|
yield UpstreamOutput("binary", os.path.basename(script))
|
||||||
entry_points = self.result.entry_points or {}
|
entry_points = getattr(self.result, 'entry_points', None) or {}
|
||||||
for script in entry_points.get("console_scripts", []):
|
for script in entry_points.get("console_scripts", []):
|
||||||
yield UpstreamOutput("binary", script.split("=")[0])
|
yield UpstreamOutput("binary", script.split("=")[0])
|
||||||
for package in self.result.packages or []:
|
for package in self.result.packages or []:
|
||||||
|
|
|
@ -70,14 +70,9 @@ class AptManager(object):
|
||||||
|
|
||||||
def package_exists(self, package):
|
def package_exists(self, package):
|
||||||
if self._apt_cache is None:
|
if self._apt_cache is None:
|
||||||
import apt_pkg
|
import apt
|
||||||
|
self._apt_cache = apt.Cache(rootdir=self.session.location)
|
||||||
# TODO(jelmer): Load from self.session
|
return package in self._apt_cache
|
||||||
self._apt_cache = apt_pkg.Cache()
|
|
||||||
for p in self._apt_cache.packages:
|
|
||||||
if p.name == package:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_package_for_paths(self, paths, regex=False):
|
def get_package_for_paths(self, paths, regex=False):
|
||||||
logging.debug('Searching for packages containing %r', paths)
|
logging.debug('Searching for packages containing %r', paths)
|
||||||
|
@ -121,9 +116,11 @@ class RemoteAptContentsFileSearcher(FileSearcher):
|
||||||
def from_session(cls, session):
|
def from_session(cls, session):
|
||||||
logging.info('Loading apt contents information')
|
logging.info('Loading apt contents information')
|
||||||
# TODO(jelmer): what about sources.list.d?
|
# TODO(jelmer): what about sources.list.d?
|
||||||
with open(os.path.join(session.location, 'etc/apt/sources.list'), 'r') as f:
|
from aptsources.sourceslist import SourcesList
|
||||||
return cls.from_repositories(
|
sl = SourcesList()
|
||||||
f.readlines(),
|
sl.load(os.path.join(session.location, 'etc/apt/sources.list'))
|
||||||
|
return cls.from_sources_list(
|
||||||
|
sl,
|
||||||
cache_dir=os.path.join(session.location, 'var/lib/apt/lists'))
|
cache_dir=os.path.join(session.location, 'var/lib/apt/lists'))
|
||||||
|
|
||||||
def __setitem__(self, path, package):
|
def __setitem__(self, path, package):
|
||||||
|
@ -174,32 +171,31 @@ class RemoteAptContentsFileSearcher(FileSearcher):
|
||||||
self.load_url(url)
|
self.load_url(url)
|
||||||
except ContentsFileNotFound:
|
except ContentsFileNotFound:
|
||||||
if mandatory:
|
if mandatory:
|
||||||
raise
|
logging.warning(
|
||||||
|
'Unable to fetch contents file %s', url)
|
||||||
|
else:
|
||||||
logging.debug(
|
logging.debug(
|
||||||
'Unable to fetch optional contents file %s', url)
|
'Unable to fetch optional contents file %s', url)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_repositories(cls, sources, cache_dir=None):
|
def from_sources_list(cls, sl, cache_dir=None):
|
||||||
# TODO(jelmer): Use aptsources.sourceslist.SourcesList
|
# TODO(jelmer): Use aptsources.sourceslist.SourcesList
|
||||||
from .build import get_build_architecture
|
from .build import get_build_architecture
|
||||||
# TODO(jelmer): Verify signatures, etc.
|
# TODO(jelmer): Verify signatures, etc.
|
||||||
urls = []
|
urls = []
|
||||||
arches = [(get_build_architecture(), True), ("all", False)]
|
arches = [(get_build_architecture(), True), ("all", False)]
|
||||||
for source in sources:
|
for source in sl.list:
|
||||||
if not source.strip():
|
if source.invalid or source.disabled:
|
||||||
continue
|
continue
|
||||||
if source.strip().startswith('#'):
|
if source.type == 'deb-src':
|
||||||
continue
|
continue
|
||||||
parts = source.split(" ")
|
if source.type != 'deb':
|
||||||
if parts[0] == "deb-src":
|
|
||||||
continue
|
|
||||||
if parts[0] != "deb":
|
|
||||||
logging.warning("Invalid line in sources: %r", source)
|
logging.warning("Invalid line in sources: %r", source)
|
||||||
continue
|
continue
|
||||||
base_url = parts[1].strip().rstrip("/")
|
base_url = source.uri.rstrip('/')
|
||||||
name = parts[2].strip()
|
name = source.dist.rstrip('/')
|
||||||
components = [c.strip() for c in parts[3:]]
|
components = source.comps
|
||||||
if components:
|
if components:
|
||||||
dists_url = base_url + "/dists"
|
dists_url = base_url + "/dists"
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -63,81 +63,28 @@ from debmutate._rules import (
|
||||||
|
|
||||||
from breezy.plugins.debian.changelog import debcommit
|
from breezy.plugins.debian.changelog import debcommit
|
||||||
from buildlog_consultant import Problem
|
from buildlog_consultant import Problem
|
||||||
from buildlog_consultant.common import (
|
|
||||||
MissingConfigStatusInput,
|
|
||||||
MissingPythonModule,
|
|
||||||
MissingPythonDistribution,
|
|
||||||
MissingCHeader,
|
|
||||||
MissingPkgConfig,
|
|
||||||
MissingCommand,
|
|
||||||
MissingFile,
|
|
||||||
MissingJavaScriptRuntime,
|
|
||||||
MissingSprocketsFile,
|
|
||||||
MissingGoPackage,
|
|
||||||
MissingPerlFile,
|
|
||||||
MissingPerlModule,
|
|
||||||
MissingXmlEntity,
|
|
||||||
MissingJDKFile,
|
|
||||||
MissingNodeModule,
|
|
||||||
MissingPhpClass,
|
|
||||||
MissingRubyGem,
|
|
||||||
MissingLibrary,
|
|
||||||
MissingJavaClass,
|
|
||||||
MissingCSharpCompiler,
|
|
||||||
MissingConfigure,
|
|
||||||
MissingAutomakeInput,
|
|
||||||
MissingRPackage,
|
|
||||||
MissingRubyFile,
|
|
||||||
MissingAutoconfMacro,
|
|
||||||
MissingValaPackage,
|
|
||||||
MissingXfceDependency,
|
|
||||||
MissingHaskellDependencies,
|
|
||||||
NeedPgBuildExtUpdateControl,
|
|
||||||
DhAddonLoadFailure,
|
|
||||||
MissingMavenArtifacts,
|
|
||||||
GnomeCommonMissing,
|
|
||||||
MissingGnomeCommonDependency,
|
|
||||||
)
|
|
||||||
from buildlog_consultant.apt import (
|
from buildlog_consultant.apt import (
|
||||||
AptFetchFailure,
|
AptFetchFailure,
|
||||||
)
|
)
|
||||||
|
from buildlog_consultant.common import (
|
||||||
|
MissingConfigStatusInput,
|
||||||
|
MissingAutomakeInput,
|
||||||
|
MissingConfigure,
|
||||||
|
NeedPgBuildExtUpdateControl,
|
||||||
|
MissingPythonModule,
|
||||||
|
MissingPythonDistribution,
|
||||||
|
MissingPerlFile,
|
||||||
|
)
|
||||||
from buildlog_consultant.sbuild import (
|
from buildlog_consultant.sbuild import (
|
||||||
SbuildFailure,
|
SbuildFailure,
|
||||||
)
|
)
|
||||||
|
|
||||||
from ..fix_build import BuildFixer, SimpleBuildFixer, resolve_error, DependencyContext
|
from ..fix_build import BuildFixer, resolve_error, DependencyContext
|
||||||
|
from ..buildlog import UpstreamRequirementFixer
|
||||||
from ..resolver.apt import (
|
from ..resolver.apt import (
|
||||||
NoAptPackage,
|
NoAptPackage,
|
||||||
get_package_for_python_module,
|
get_package_for_python_module,
|
||||||
)
|
)
|
||||||
from ..requirements import (
|
|
||||||
BinaryRequirement,
|
|
||||||
PathRequirement,
|
|
||||||
PkgConfigRequirement,
|
|
||||||
CHeaderRequirement,
|
|
||||||
JavaScriptRuntimeRequirement,
|
|
||||||
ValaPackageRequirement,
|
|
||||||
RubyGemRequirement,
|
|
||||||
GoPackageRequirement,
|
|
||||||
DhAddonRequirement,
|
|
||||||
PhpClassRequirement,
|
|
||||||
RPackageRequirement,
|
|
||||||
NodePackageRequirement,
|
|
||||||
LibraryRequirement,
|
|
||||||
RubyFileRequirement,
|
|
||||||
XmlEntityRequirement,
|
|
||||||
SprocketsFileRequirement,
|
|
||||||
JavaClassRequirement,
|
|
||||||
HaskellPackageRequirement,
|
|
||||||
MavenArtifactRequirement,
|
|
||||||
GnomeCommonRequirement,
|
|
||||||
JDKFileRequirement,
|
|
||||||
PerlModuleRequirement,
|
|
||||||
PerlFileRequirement,
|
|
||||||
AutoconfMacroRequirement,
|
|
||||||
PythonModuleRequirement,
|
|
||||||
PythonPackageRequirement,
|
|
||||||
)
|
|
||||||
from .build import attempt_build, DEFAULT_BUILDER
|
from .build import attempt_build, DEFAULT_BUILDER
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,111 +384,6 @@ def fix_missing_python_module(error, context):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def problem_to_upstream_requirement(problem):
|
|
||||||
if isinstance(problem, MissingFile):
|
|
||||||
return PathRequirement(problem.path)
|
|
||||||
elif isinstance(problem, MissingCommand):
|
|
||||||
return BinaryRequirement(problem.command)
|
|
||||||
elif isinstance(problem, MissingPkgConfig):
|
|
||||||
return PkgConfigRequirement(
|
|
||||||
problem.module, problem.minimum_version)
|
|
||||||
elif isinstance(problem, MissingCHeader):
|
|
||||||
return CHeaderRequirement(problem.header)
|
|
||||||
elif isinstance(problem, MissingJavaScriptRuntime):
|
|
||||||
return JavaScriptRuntimeRequirement()
|
|
||||||
elif isinstance(problem, MissingRubyGem):
|
|
||||||
return RubyGemRequirement(problem.gem, problem.version)
|
|
||||||
elif isinstance(problem, MissingValaPackage):
|
|
||||||
return ValaPackageRequirement(problem.package)
|
|
||||||
elif isinstance(problem, MissingGoPackage):
|
|
||||||
return GoPackageRequirement(problem.package)
|
|
||||||
elif isinstance(problem, DhAddonLoadFailure):
|
|
||||||
return DhAddonRequirement(problem.path)
|
|
||||||
elif isinstance(problem, MissingPhpClass):
|
|
||||||
return PhpClassRequirement(problem.php_class)
|
|
||||||
elif isinstance(problem, MissingRPackage):
|
|
||||||
return RPackageRequirement(problem.package, problem.minimum_version)
|
|
||||||
elif isinstance(problem, MissingNodeModule):
|
|
||||||
return NodePackageRequirement(problem.module)
|
|
||||||
elif isinstance(problem, MissingLibrary):
|
|
||||||
return LibraryRequirement(problem.library)
|
|
||||||
elif isinstance(problem, MissingRubyFile):
|
|
||||||
return RubyFileRequirement(problem.filename)
|
|
||||||
elif isinstance(problem, MissingXmlEntity):
|
|
||||||
return XmlEntityRequirement(problem.url)
|
|
||||||
elif isinstance(problem, MissingSprocketsFile):
|
|
||||||
return SprocketsFileRequirement(problem.content_type, problem.name)
|
|
||||||
elif isinstance(problem, MissingJavaClass):
|
|
||||||
return JavaClassRequirement(problem.classname)
|
|
||||||
elif isinstance(problem, MissingHaskellDependencies):
|
|
||||||
# TODO(jelmer): Create multiple HaskellPackageRequirement objects?
|
|
||||||
return HaskellPackageRequirement(problem.package)
|
|
||||||
elif isinstance(problem, MissingMavenArtifacts):
|
|
||||||
# TODO(jelmer): Create multiple MavenArtifactRequirement objects?
|
|
||||||
return MavenArtifactRequirement(problem.artifacts)
|
|
||||||
elif isinstance(problem, MissingCSharpCompiler):
|
|
||||||
return BinaryRequirement('msc')
|
|
||||||
elif isinstance(problem, GnomeCommonMissing):
|
|
||||||
return GnomeCommonRequirement()
|
|
||||||
elif isinstance(problem, MissingJDKFile):
|
|
||||||
return JDKFileRequirement(problem.jdk_path, problem.filename)
|
|
||||||
elif isinstance(problem, MissingGnomeCommonDependency):
|
|
||||||
if problem.package == "glib-gettext":
|
|
||||||
return BinaryRequirement('glib-gettextize')
|
|
||||||
else:
|
|
||||||
logging.warning(
|
|
||||||
"No known command for gnome-common dependency %s",
|
|
||||||
problem.package)
|
|
||||||
return None
|
|
||||||
elif isinstance(problem, MissingXfceDependency):
|
|
||||||
if problem.package == "gtk-doc":
|
|
||||||
return BinaryRequirement("gtkdocize")
|
|
||||||
else:
|
|
||||||
logging.warning(
|
|
||||||
"No known command for xfce dependency %s",
|
|
||||||
problem.package)
|
|
||||||
return None
|
|
||||||
elif isinstance(problem, MissingPerlModule):
|
|
||||||
return PerlModuleRequirement(
|
|
||||||
module=problem.module,
|
|
||||||
filename=problem.filename,
|
|
||||||
inc=problem.inc)
|
|
||||||
elif isinstance(problem, MissingPerlFile):
|
|
||||||
return PerlFileRequirement(filename=problem.filename)
|
|
||||||
elif isinstance(problem, MissingAutoconfMacro):
|
|
||||||
return AutoconfMacroRequirement(problem.macro)
|
|
||||||
elif isinstance(problem, MissingPythonModule):
|
|
||||||
return PythonModuleRequirement(
|
|
||||||
problem.module,
|
|
||||||
python_version=problem.python_version,
|
|
||||||
minimum_version=problem.minimum_version)
|
|
||||||
elif isinstance(problem, MissingPythonDistribution):
|
|
||||||
return PythonPackageRequirement(
|
|
||||||
problem.module,
|
|
||||||
python_version=problem.python_version,
|
|
||||||
minimum_version=problem.minimum_version)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class UpstreamRequirementFixer(BuildFixer):
|
|
||||||
|
|
||||||
def can_fix(self, error):
|
|
||||||
req = problem_to_upstream_requirement(error)
|
|
||||||
return req is not None
|
|
||||||
|
|
||||||
def fix(self, error, context):
|
|
||||||
req = problem_to_upstream_requirement(error)
|
|
||||||
if req is None:
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
package = context.resolver.resolve(req)
|
|
||||||
except NoAptPackage:
|
|
||||||
return False
|
|
||||||
return context.add_dependency(package)
|
|
||||||
|
|
||||||
|
|
||||||
def retry_apt_failure(error, context):
|
def retry_apt_failure(error, context):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -635,26 +477,39 @@ def fix_missing_makefile_pl(error, context):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
VERSIONED_PACKAGE_FIXERS: List[BuildFixer] = [
|
class SimpleBuildFixer(BuildFixer):
|
||||||
|
|
||||||
|
def __init__(self, problem_cls, fn):
|
||||||
|
self._problem_cls = problem_cls
|
||||||
|
self._fn = fn
|
||||||
|
|
||||||
|
def can_fix(self, problem):
|
||||||
|
return isinstance(problem, self._problem_cls)
|
||||||
|
|
||||||
|
def _fix(self, problem, context):
|
||||||
|
return self._fn(problem, context)
|
||||||
|
|
||||||
|
|
||||||
|
def versioned_package_fixers():
|
||||||
|
return [
|
||||||
SimpleBuildFixer(
|
SimpleBuildFixer(
|
||||||
NeedPgBuildExtUpdateControl, run_pgbuildext_updatecontrol),
|
NeedPgBuildExtUpdateControl, run_pgbuildext_updatecontrol),
|
||||||
SimpleBuildFixer(MissingConfigure, fix_missing_configure),
|
SimpleBuildFixer(MissingConfigure, fix_missing_configure),
|
||||||
SimpleBuildFixer(MissingAutomakeInput, fix_missing_automake_input),
|
SimpleBuildFixer(MissingAutomakeInput, fix_missing_automake_input),
|
||||||
SimpleBuildFixer(MissingConfigStatusInput, fix_missing_config_status_input),
|
SimpleBuildFixer(MissingConfigStatusInput, fix_missing_config_status_input),
|
||||||
]
|
SimpleBuildFixer(MissingPerlFile, fix_missing_makefile_pl),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
APT_FIXERS: List[BuildFixer] = [
|
def apt_fixers(apt) -> List[BuildFixer]:
|
||||||
|
from ..resolver.apt import AptResolver
|
||||||
|
resolver = AptResolver(apt)
|
||||||
|
return [
|
||||||
SimpleBuildFixer(MissingPythonModule, fix_missing_python_module),
|
SimpleBuildFixer(MissingPythonModule, fix_missing_python_module),
|
||||||
SimpleBuildFixer(MissingPythonDistribution, fix_missing_python_distribution),
|
SimpleBuildFixer(MissingPythonDistribution, fix_missing_python_distribution),
|
||||||
SimpleBuildFixer(AptFetchFailure, retry_apt_failure),
|
SimpleBuildFixer(AptFetchFailure, retry_apt_failure),
|
||||||
UpstreamRequirementFixer(),
|
UpstreamRequirementFixer(resolver),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
GENERIC_FIXERS: List[BuildFixer] = [
|
|
||||||
SimpleBuildFixer(MissingPerlFile, fix_missing_makefile_pl),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def build_incrementally(
|
def build_incrementally(
|
||||||
|
@ -720,7 +575,7 @@ def build_incrementally(
|
||||||
raise
|
raise
|
||||||
try:
|
try:
|
||||||
if not resolve_error(
|
if not resolve_error(
|
||||||
e.error, context, VERSIONED_PACKAGE_FIXERS + APT_FIXERS + GENERIC_FIXERS
|
e.error, context, versioned_package_fixers() + apt_fixers(apt)
|
||||||
):
|
):
|
||||||
logging.warning("Failed to resolve error %r. Giving up.", e.error)
|
logging.warning("Failed to resolve error %r. Giving up.", e.error)
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -47,19 +47,6 @@ class BuildFixer(object):
|
||||||
return self._fix(problem, context)
|
return self._fix(problem, context)
|
||||||
|
|
||||||
|
|
||||||
class SimpleBuildFixer(BuildFixer):
|
|
||||||
|
|
||||||
def __init__(self, problem_cls, fn):
|
|
||||||
self._problem_cls = problem_cls
|
|
||||||
self._fn = fn
|
|
||||||
|
|
||||||
def can_fix(self, problem):
|
|
||||||
return isinstance(problem, self._problem_cls)
|
|
||||||
|
|
||||||
def _fix(self, problem, context):
|
|
||||||
return self._fn(problem, context)
|
|
||||||
|
|
||||||
|
|
||||||
class DependencyContext(object):
|
class DependencyContext(object):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -71,8 +58,6 @@ class DependencyContext(object):
|
||||||
):
|
):
|
||||||
self.tree = tree
|
self.tree = tree
|
||||||
self.apt = apt
|
self.apt = apt
|
||||||
from .resolver.apt import AptResolver
|
|
||||||
self.resolver = AptResolver(apt)
|
|
||||||
self.subpath = subpath
|
self.subpath = subpath
|
||||||
self.committer = committer
|
self.committer = committer
|
||||||
self.update_changelog = update_changelog
|
self.update_changelog = update_changelog
|
||||||
|
@ -94,47 +79,23 @@ class SchrootDependencyContext(DependencyContext):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def fix_perl_module_from_cpan(error, context):
|
def generic_install_fixers(session):
|
||||||
# TODO(jelmer): Specify -T to skip tests?
|
from .buildlog import UpstreamRequirementFixer
|
||||||
context.session.check_call(
|
from .resolver import CPANResolver, PypiResolver, NpmResolver
|
||||||
["cpan", "-i", error.module], user="root", env={"PERL_MM_USE_DEFAULT": "1"}
|
return [
|
||||||
)
|
UpstreamRequirementFixer(CPANResolver(session)),
|
||||||
return True
|
UpstreamRequirementFixer(PypiResolver(session)),
|
||||||
|
UpstreamRequirementFixer(NpmResolver(session)),
|
||||||
|
]
|
||||||
NPM_COMMAND_PACKAGES = {
|
|
||||||
"del-cli": "del-cli",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def fix_npm_missing_command(error, context):
|
|
||||||
try:
|
|
||||||
package = NPM_COMMAND_PACKAGES[error.command]
|
|
||||||
except KeyError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
context.session.check_call(["npm", "-g", "install", package])
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def fix_python_package_from_pip(error, context):
|
|
||||||
context.session.check_call(["pip", "install", error.distribution])
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
GENERIC_INSTALL_FIXERS: List[BuildFixer] = [
|
|
||||||
SimpleBuildFixer(MissingPerlModule, fix_perl_module_from_cpan),
|
|
||||||
SimpleBuildFixer(MissingPythonDistribution, fix_python_package_from_pip),
|
|
||||||
SimpleBuildFixer(MissingCommand, fix_npm_missing_command),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def run_with_build_fixer(
|
def run_with_build_fixer(
|
||||||
session: Session, args: List[str],
|
session: Session, args: List[str],
|
||||||
fixers: Optional[List[BuildFixer]] = None):
|
fixers: Optional[List[BuildFixer]] = None):
|
||||||
if fixers is None:
|
if fixers is None:
|
||||||
from .debian.fix_build import APT_FIXERS
|
from .debian.fix_build import apt_fixers
|
||||||
fixers = GENERIC_INSTALL_FIXERS + APT_FIXERS
|
from .resolver.apt import AptResolver
|
||||||
|
fixers = generic_install_fixers(session) + apt_fixers(AptResolver.from_session(session))
|
||||||
logging.info("Running %r", args)
|
logging.info("Running %r", args)
|
||||||
fixed_errors = []
|
fixed_errors = []
|
||||||
while True:
|
while True:
|
||||||
|
|
|
@ -34,20 +34,109 @@ class Resolver(object):
|
||||||
raise NotImplementedError(self.met)
|
raise NotImplementedError(self.met)
|
||||||
|
|
||||||
|
|
||||||
class NativeResolver(Resolver):
|
class CPANResolver(object):
|
||||||
|
|
||||||
def __init__(self, session):
|
def __init__(self, session):
|
||||||
self.session = session
|
self.session = session
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_session(cls, session):
|
|
||||||
return cls(session)
|
|
||||||
|
|
||||||
def install(self, requirements):
|
def install(self, requirements):
|
||||||
raise NotImplementedError(self.install)
|
from ..requirements import PerlModuleRequirement
|
||||||
|
missing = []
|
||||||
|
for requirement in requirements:
|
||||||
|
if not isinstance(requirement, PerlModuleRequirement):
|
||||||
|
missing.append(requirement)
|
||||||
|
continue
|
||||||
|
# TODO(jelmer): Specify -T to skip tests?
|
||||||
|
self.session.check_call(
|
||||||
|
["cpan", "-i", requirement.module],
|
||||||
|
user="root", env={"PERL_MM_USE_DEFAULT": "1"}
|
||||||
|
)
|
||||||
|
if missing:
|
||||||
|
raise MissingDependencies(missing)
|
||||||
|
|
||||||
def explain(self, requirements):
|
def explain(self, requirements):
|
||||||
raise NotImplementedError(self.explain)
|
raise NotImplementedError(self.explain)
|
||||||
|
|
||||||
|
def met(self, requirement):
|
||||||
|
raise NotImplementedError(self.met)
|
||||||
|
|
||||||
|
|
||||||
|
class PypiResolver(object):
|
||||||
|
|
||||||
|
def __init__(self, session):
|
||||||
|
self.session = session
|
||||||
|
|
||||||
|
def install(self, requirements):
|
||||||
|
from ..requirements import PythonPackageRequirement
|
||||||
|
missing = []
|
||||||
|
for requirement in requirements:
|
||||||
|
if not isinstance(requirement, PythonPackageRequirement):
|
||||||
|
missing.append(requirement)
|
||||||
|
continue
|
||||||
|
self.session.check_call(["pip", "install", requirement.package])
|
||||||
|
if missing:
|
||||||
|
raise MissingDependencies(missing)
|
||||||
|
|
||||||
|
def explain(self, requirements):
|
||||||
|
raise NotImplementedError(self.explain)
|
||||||
|
|
||||||
|
def met(self, requirement):
|
||||||
|
raise NotImplementedError(self.met)
|
||||||
|
|
||||||
|
|
||||||
|
NPM_COMMAND_PACKAGES = {
|
||||||
|
"del-cli": "del-cli",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class NpmResolver(object):
|
||||||
|
|
||||||
|
def __init__(self, session):
|
||||||
|
self.session = session
|
||||||
|
|
||||||
|
def install(self, requirements):
|
||||||
|
from ..requirements import NodePackageRequirement
|
||||||
|
missing = []
|
||||||
|
for requirement in requirements:
|
||||||
|
if not isinstance(requirement, NodePackageRequirement):
|
||||||
|
missing.append(requirement)
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
package = NPM_COMMAND_PACKAGES[requirement.command]
|
||||||
|
except KeyError:
|
||||||
|
missing.append(requirement)
|
||||||
|
continue
|
||||||
|
self.session.check_call(["npm", "-g", "install", package])
|
||||||
|
if missing:
|
||||||
|
raise MissingDependencies(missing)
|
||||||
|
|
||||||
|
def explain(self, requirements):
|
||||||
|
raise NotImplementedError(self.explain)
|
||||||
|
|
||||||
|
def met(self, requirement):
|
||||||
|
raise NotImplementedError(self.met)
|
||||||
|
|
||||||
|
|
||||||
|
class StackedResolver(Resolver):
|
||||||
|
def __init__(self, subs):
|
||||||
|
self.subs = subs
|
||||||
|
|
||||||
|
def install(self, requirements):
|
||||||
|
for sub in self.subs:
|
||||||
|
try:
|
||||||
|
sub.install(requirements)
|
||||||
|
except MissingDependencies as e:
|
||||||
|
requirements = e.requirements
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def native_resolvers(session):
|
||||||
|
return StackedResolver([
|
||||||
|
CPANResolver(session),
|
||||||
|
PypiResolver(session),
|
||||||
|
NpmResolver(session)])
|
||||||
|
|
||||||
|
|
||||||
class ExplainResolver(Resolver):
|
class ExplainResolver(Resolver):
|
||||||
def __init__(self, session):
|
def __init__(self, session):
|
||||||
|
|
|
@ -21,7 +21,7 @@ import posixpath
|
||||||
|
|
||||||
from ..debian.apt import AptManager
|
from ..debian.apt import AptManager
|
||||||
|
|
||||||
from . import Resolver
|
from . import Resolver, MissingDependencies
|
||||||
from ..requirements import (
|
from ..requirements import (
|
||||||
BinaryRequirement,
|
BinaryRequirement,
|
||||||
CHeaderRequirement,
|
CHeaderRequirement,
|
||||||
|
@ -57,24 +57,35 @@ class NoAptPackage(Exception):
|
||||||
"""No apt package."""
|
"""No apt package."""
|
||||||
|
|
||||||
|
|
||||||
|
class AptRequirement(object):
|
||||||
|
|
||||||
|
def __init__(self, package, minimum_version=None):
|
||||||
|
self.package = package
|
||||||
|
self.minimum_version = minimum_version
|
||||||
|
|
||||||
|
|
||||||
def get_package_for_python_package(apt_mgr, package, python_version, minimum_version=None):
|
def get_package_for_python_package(apt_mgr, package, python_version, minimum_version=None):
|
||||||
if python_version == "pypy":
|
if python_version == "pypy":
|
||||||
return apt_mgr.get_package_for_paths(
|
pkg_name = apt_mgr.get_package_for_paths(
|
||||||
["/usr/lib/pypy/dist-packages/%s-.*.egg-info/PKG-INFO" % package],
|
["/usr/lib/pypy/dist-packages/%s-.*.egg-info/PKG-INFO" % package],
|
||||||
regex=True)
|
regex=True)
|
||||||
elif python_version == "cpython2":
|
elif python_version == "cpython2":
|
||||||
return apt_mgr.get_package_for_paths(
|
pkg_name = apt_mgr.get_package_for_paths(
|
||||||
["/usr/lib/python2\\.[0-9]/dist-packages/%s-.*.egg-info/PKG-INFO" % package],
|
["/usr/lib/python2\\.[0-9]/dist-packages/%s-.*.egg-info/PKG-INFO" % package],
|
||||||
regex=True)
|
regex=True)
|
||||||
elif python_version == "cpython3":
|
elif python_version == "cpython3":
|
||||||
return apt_mgr.get_package_for_paths(
|
pkg_name = apt_mgr.get_package_for_paths(
|
||||||
["/usr/lib/python3/dist-packages/%s-.*.egg-info/PKG-INFO" % package],
|
["/usr/lib/python3/dist-packages/%s-.*.egg-info/PKG-INFO" % package],
|
||||||
regex=True)
|
regex=True)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
# TODO(jelmer): Dealing with epoch, etc?
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name, minimum_version)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_package_for_python_module(apt_mgr, module, python_version):
|
def get_package_for_python_module(apt_mgr, module, python_version, minimum_version):
|
||||||
if python_version == "python3":
|
if python_version == "python3":
|
||||||
paths = [
|
paths = [
|
||||||
posixpath.join(
|
posixpath.join(
|
||||||
|
@ -127,7 +138,10 @@ def get_package_for_python_module(apt_mgr, module, python_version):
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
raise AssertionError("unknown python version %r" % python_version)
|
raise AssertionError("unknown python version %r" % python_version)
|
||||||
return apt_mgr.get_package_for_paths(paths, regex=True)
|
pkg_name = apt_mgr.get_package_for_paths(paths, regex=True)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name, minimum_version=minimum_version)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_binary_req(apt_mgr, req):
|
def resolve_binary_req(apt_mgr, req):
|
||||||
|
@ -138,7 +152,10 @@ def resolve_binary_req(apt_mgr, req):
|
||||||
posixpath.join(dirname, req.binary_name)
|
posixpath.join(dirname, req.binary_name)
|
||||||
for dirname in ["/usr/bin", "/bin"]
|
for dirname in ["/usr/bin", "/bin"]
|
||||||
]
|
]
|
||||||
return apt_mgr.get_package_for_paths(paths)
|
pkg_name = apt_mgr.get_package_for_paths(paths)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_pkg_config_req(apt_mgr, req):
|
def resolve_pkg_config_req(apt_mgr, req):
|
||||||
|
@ -151,11 +168,16 @@ def resolve_pkg_config_req(apt_mgr, req):
|
||||||
[posixpath.join("/usr/lib", ".*", "pkgconfig", req.module + ".pc")],
|
[posixpath.join("/usr/lib", ".*", "pkgconfig", req.module + ".pc")],
|
||||||
regex=True,
|
regex=True,
|
||||||
minimum_version=req.minimum_version)
|
minimum_version=req.minimum_version)
|
||||||
return package
|
if package is not None:
|
||||||
|
return AptRequirement(package)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_path_req(apt_mgr, req):
|
def resolve_path_req(apt_mgr, req):
|
||||||
return apt_mgr.get_package_for_paths([req.path])
|
package = apt_mgr.get_package_for_paths([req.path])
|
||||||
|
if package is not None:
|
||||||
|
return AptRequirement(package)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_c_header_req(apt_mgr, req):
|
def resolve_c_header_req(apt_mgr, req):
|
||||||
|
@ -166,17 +188,25 @@ def resolve_c_header_req(apt_mgr, req):
|
||||||
package = apt_mgr.get_package_for_paths(
|
package = apt_mgr.get_package_for_paths(
|
||||||
[posixpath.join("/usr/include", ".*", req.header)], regex=True
|
[posixpath.join("/usr/include", ".*", req.header)], regex=True
|
||||||
)
|
)
|
||||||
return package
|
if package is None:
|
||||||
|
return None
|
||||||
|
return AptRequirement(package)
|
||||||
|
|
||||||
|
|
||||||
def resolve_js_runtime_req(apt_mgr, req):
|
def resolve_js_runtime_req(apt_mgr, req):
|
||||||
return apt_mgr.get_package_for_paths(
|
package = apt_mgr.get_package_for_paths(
|
||||||
["/usr/bin/node", "/usr/bin/duk"], regex=False)
|
["/usr/bin/node", "/usr/bin/duk"], regex=False)
|
||||||
|
if package is not None:
|
||||||
|
return AptRequirement(package)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_vala_package_req(apt_mgr, req):
|
def resolve_vala_package_req(apt_mgr, req):
|
||||||
path = "/usr/share/vala-[0-9.]+/vapi/%s.vapi" % req.package
|
path = "/usr/share/vala-[0-9.]+/vapi/%s.vapi" % req.package
|
||||||
return apt_mgr.get_package_for_paths([path], regex=True)
|
package = apt_mgr.get_package_for_paths([path], regex=True)
|
||||||
|
if package is not None:
|
||||||
|
return AptRequirement(package)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_ruby_gem_req(apt_mgr, req):
|
def resolve_ruby_gem_req(apt_mgr, req):
|
||||||
|
@ -186,30 +216,45 @@ def resolve_ruby_gem_req(apt_mgr, req):
|
||||||
"specifications/%s-.*\\.gemspec" % req.gem
|
"specifications/%s-.*\\.gemspec" % req.gem
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
return apt_mgr.get_package_for_paths(
|
package = apt_mgr.get_package_for_paths(
|
||||||
paths, regex=True, minimum_version=req.minimum_version)
|
paths, regex=True)
|
||||||
|
if package is not None:
|
||||||
|
return AptRequirement(package, minimum_version=req.minimum_version)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_go_package_req(apt_mgr, req):
|
def resolve_go_package_req(apt_mgr, req):
|
||||||
return apt_mgr.get_package_for_paths(
|
package = apt_mgr.get_package_for_paths(
|
||||||
[posixpath.join("/usr/share/gocode/src", req.package, ".*")],
|
[posixpath.join("/usr/share/gocode/src", req.package, ".*")],
|
||||||
regex=True
|
regex=True
|
||||||
)
|
)
|
||||||
|
if package is not None:
|
||||||
|
return AptRequirement(package)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_dh_addon_req(apt_mgr, req):
|
def resolve_dh_addon_req(apt_mgr, req):
|
||||||
paths = [posixpath.join("/usr/share/perl5", req.path)]
|
paths = [posixpath.join("/usr/share/perl5", req.path)]
|
||||||
return apt_mgr.get_package_for_paths(paths)
|
package = apt_mgr.get_package_for_paths(paths)
|
||||||
|
if package is not None:
|
||||||
|
return AptRequirement(package)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_php_class_req(apt_mgr, req):
|
def resolve_php_class_req(apt_mgr, req):
|
||||||
path = "/usr/share/php/%s.php" % req.php_class.replace("\\", "/")
|
path = "/usr/share/php/%s.php" % req.php_class.replace("\\", "/")
|
||||||
return apt_mgr.get_package_for_paths([path])
|
package = apt_mgr.get_package_for_paths([path])
|
||||||
|
if package is not None:
|
||||||
|
return AptRequirement(package)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_r_package_req(apt_mgr, req):
|
def resolve_r_package_req(apt_mgr, req):
|
||||||
paths = [posixpath.join("/usr/lib/R/site-library/.*/R/%s$" % req.package)]
|
paths = [posixpath.join("/usr/lib/R/site-library/.*/R/%s$" % req.package)]
|
||||||
return apt_mgr.get_package_for_paths(paths, regex=True)
|
package = apt_mgr.get_package_for_paths(paths, regex=True)
|
||||||
|
if package is not None:
|
||||||
|
return AptRequirement(package)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_node_package_req(apt_mgr, req):
|
def resolve_node_package_req(apt_mgr, req):
|
||||||
|
@ -218,7 +263,10 @@ def resolve_node_package_req(apt_mgr, req):
|
||||||
"/usr/lib/nodejs/%s/package.json" % req.package,
|
"/usr/lib/nodejs/%s/package.json" % req.package,
|
||||||
"/usr/share/nodejs/%s/package.json" % req.package,
|
"/usr/share/nodejs/%s/package.json" % req.package,
|
||||||
]
|
]
|
||||||
return apt_mgr.get_package_for_paths(paths, regex=True)
|
pkg_name = apt_mgr.get_package_for_paths(paths, regex=True)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_library_req(apt_mgr, req):
|
def resolve_library_req(apt_mgr, req):
|
||||||
|
@ -228,21 +276,27 @@ def resolve_library_req(apt_mgr, req):
|
||||||
posixpath.join("/usr/lib/lib%s.a$" % req.library),
|
posixpath.join("/usr/lib/lib%s.a$" % req.library),
|
||||||
posixpath.join("/usr/lib/.*/lib%s.a$" % req.library),
|
posixpath.join("/usr/lib/.*/lib%s.a$" % req.library),
|
||||||
]
|
]
|
||||||
return apt_mgr.get_package_for_paths(paths, regex=True)
|
pkg_name = apt_mgr.get_package_for_paths(paths, regex=True)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_ruby_file_req(apt_mgr, req):
|
def resolve_ruby_file_req(apt_mgr, req):
|
||||||
paths = [posixpath.join("/usr/lib/ruby/vendor_ruby/%s.rb" % req.filename)]
|
paths = [posixpath.join("/usr/lib/ruby/vendor_ruby/%s.rb" % req.filename)]
|
||||||
package = apt_mgr.get_package_for_paths(paths)
|
package = apt_mgr.get_package_for_paths(paths)
|
||||||
if package is not None:
|
if package is not None:
|
||||||
return package
|
return AptRequirement(package)
|
||||||
paths = [
|
paths = [
|
||||||
posixpath.join(
|
posixpath.join(
|
||||||
r"/usr/share/rubygems-integration/all/gems/([^/]+)/"
|
r"/usr/share/rubygems-integration/all/gems/([^/]+)/"
|
||||||
"lib/%s.rb" % req.filename
|
"lib/%s.rb" % req.filename
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
return apt_mgr.get_package_for_paths(paths, regex=True)
|
pkg_name = apt_mgr.get_package_for_paths(paths, regex=True)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_xml_entity_req(apt_mgr, req):
|
def resolve_xml_entity_req(apt_mgr, req):
|
||||||
|
@ -258,7 +312,10 @@ def resolve_xml_entity_req(apt_mgr, req):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return apt_mgr.get_package_for_paths([search_path], regex=False)
|
pkg_name = apt_mgr.get_package_for_paths([search_path], regex=False)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_sprockets_file_req(apt_mgr, req):
|
def resolve_sprockets_file_req(apt_mgr, req):
|
||||||
|
@ -267,7 +324,10 @@ def resolve_sprockets_file_req(apt_mgr, req):
|
||||||
else:
|
else:
|
||||||
logging.warning("unable to handle content type %s", req.content_type)
|
logging.warning("unable to handle content type %s", req.content_type)
|
||||||
return None
|
return None
|
||||||
return apt_mgr.get_package_for_paths([path], regex=True)
|
pkg_name = apt_mgr.get_package_for_paths([path], regex=True)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_java_class_req(apt_mgr, req):
|
def resolve_java_class_req(apt_mgr, req):
|
||||||
|
@ -285,12 +345,15 @@ def resolve_java_class_req(apt_mgr, req):
|
||||||
if package is None:
|
if package is None:
|
||||||
logging.warning("no package for files in %r", classpath)
|
logging.warning("no package for files in %r", classpath)
|
||||||
return None
|
return None
|
||||||
return package
|
return AptRequirement(package)
|
||||||
|
|
||||||
|
|
||||||
def resolve_haskell_package_req(apt_mgr, req):
|
def resolve_haskell_package_req(apt_mgr, req):
|
||||||
path = "/var/lib/ghc/package.conf.d/%s-.*.conf" % req.deps[0][0]
|
path = "/var/lib/ghc/package.conf.d/%s-.*.conf" % req.deps[0][0]
|
||||||
return apt_mgr.get_package_for_paths([path], regex=True)
|
pkg_name = apt_mgr.get_package_for_paths([path], regex=True)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_maven_artifact_req(apt_mgr, req):
|
def resolve_maven_artifact_req(apt_mgr, req):
|
||||||
|
@ -319,16 +382,22 @@ def resolve_maven_artifact_req(apt_mgr, req):
|
||||||
"%s-%s.%s" % (artifact_id, version, kind),
|
"%s-%s.%s" % (artifact_id, version, kind),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
return apt_mgr.get_package_for_paths(paths, regex=regex)
|
pkg_name = apt_mgr.get_package_for_paths(paths, regex=regex)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_gnome_common_req(apt_mgr, req):
|
def resolve_gnome_common_req(apt_mgr, req):
|
||||||
return 'gnome-common'
|
return AptRequirement('gnome-common')
|
||||||
|
|
||||||
|
|
||||||
def resolve_jdk_file_req(apt_mgr, req):
|
def resolve_jdk_file_req(apt_mgr, req):
|
||||||
path = req.jdk_path + ".*/" + req.filename
|
path = req.jdk_path + ".*/" + req.filename
|
||||||
return apt_mgr.get_package_for_paths([path], regex=True)
|
pkg_name = apt_mgr.get_package_for_paths([path], regex=True)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_perl_module_req(apt_mgr, req):
|
def resolve_perl_module_req(apt_mgr, req):
|
||||||
|
@ -344,11 +413,17 @@ def resolve_perl_module_req(apt_mgr, req):
|
||||||
paths = [req.filename]
|
paths = [req.filename]
|
||||||
else:
|
else:
|
||||||
paths = [posixpath.join(inc, req.filename) for inc in req.inc]
|
paths = [posixpath.join(inc, req.filename) for inc in req.inc]
|
||||||
return apt_mgr.get_package_for_paths(paths, regex=False)
|
pkg_name = apt_mgr.get_package_for_paths(paths, regex=False)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_perl_file_req(apt_mgr, req):
|
def resolve_perl_file_req(apt_mgr, req):
|
||||||
return apt_mgr.get_package_for_paths([req.filename], regex=False)
|
pkg_name = apt_mgr.get_package_for_paths([req.filename], regex=False)
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _find_aclocal_fun(macro):
|
def _find_aclocal_fun(macro):
|
||||||
|
@ -370,7 +445,10 @@ def resolve_autoconf_macro_req(apt_mgr, req):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logging.info("No local m4 file found defining %s", req.macro)
|
logging.info("No local m4 file found defining %s", req.macro)
|
||||||
return None
|
return None
|
||||||
return apt_mgr.get_package_for_paths([path])
|
pkg_name = apt_mgr.get_package_for_paths([path])
|
||||||
|
if pkg_name is not None:
|
||||||
|
return AptRequirement(pkg_name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve_python_module_req(apt_mgr, req):
|
def resolve_python_module_req(apt_mgr, req):
|
||||||
|
@ -421,14 +499,7 @@ APT_REQUIREMENT_RESOLVERS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class AptRequirement(object):
|
def resolve_requirement_apt(apt_mgr, req: UpstreamRequirement) -> AptRequirement:
|
||||||
|
|
||||||
def __init__(self, package, minimum_version=None):
|
|
||||||
self.package = package
|
|
||||||
self.minimum_version = minimum_version
|
|
||||||
|
|
||||||
|
|
||||||
def resolve_requirement_apt(apt_mgr, req: UpstreamRequirement):
|
|
||||||
for rr_class, rr_fn in APT_REQUIREMENT_RESOLVERS:
|
for rr_class, rr_fn in APT_REQUIREMENT_RESOLVERS:
|
||||||
if isinstance(req, rr_class):
|
if isinstance(req, rr_class):
|
||||||
deb_req = rr_fn(apt_mgr, req)
|
deb_req = rr_fn(apt_mgr, req)
|
||||||
|
@ -456,7 +527,17 @@ class AptResolver(Resolver):
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
missing.append(req)
|
missing.append(req)
|
||||||
if missing:
|
if missing:
|
||||||
self.apt.install([self.resolve(m) for m in missing])
|
still_missing = []
|
||||||
|
apt_requirements = []
|
||||||
|
for m in missing:
|
||||||
|
try:
|
||||||
|
apt_requirements.append(self.resolve(m))
|
||||||
|
except NoAptPackage:
|
||||||
|
still_missing.append(m)
|
||||||
|
self.apt.install(
|
||||||
|
[req.package for req in apt_requirements])
|
||||||
|
if still_missing:
|
||||||
|
raise MissingDependencies(still_missing)
|
||||||
|
|
||||||
def explain(self, requirements):
|
def explain(self, requirements):
|
||||||
raise NotImplementedError(self.explain)
|
raise NotImplementedError(self.explain)
|
||||||
|
|
|
@ -34,8 +34,8 @@ from ..debian import apt
|
||||||
from ..debian.apt import AptManager
|
from ..debian.apt import AptManager
|
||||||
from ..debian.fix_build import (
|
from ..debian.fix_build import (
|
||||||
resolve_error,
|
resolve_error,
|
||||||
VERSIONED_PACKAGE_FIXERS,
|
versioned_package_fixers,
|
||||||
APT_FIXERS,
|
apt_fixers,
|
||||||
BuildDependencyContext,
|
BuildDependencyContext,
|
||||||
)
|
)
|
||||||
from breezy.tests import TestCaseWithTransport
|
from breezy.tests import TestCaseWithTransport
|
||||||
|
@ -95,10 +95,10 @@ blah (0.1) UNRELEASED; urgency=medium
|
||||||
self.tree,
|
self.tree,
|
||||||
apt,
|
apt,
|
||||||
subpath="",
|
subpath="",
|
||||||
committer="Janitor <janitor@jelmer.uk>",
|
committer="ognibuild <ognibuild@jelmer.uk>",
|
||||||
update_changelog=True,
|
update_changelog=True,
|
||||||
)
|
)
|
||||||
return resolve_error(error, context, VERSIONED_PACKAGE_FIXERS + APT_FIXERS)
|
return resolve_error(error, context, versioned_package_fixers() + apt_fixers(apt))
|
||||||
|
|
||||||
def get_build_deps(self):
|
def get_build_deps(self):
|
||||||
with open(self.tree.abspath("debian/control"), "r") as f:
|
with open(self.tree.abspath("debian/control"), "r") as f:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue