Fix style.
This commit is contained in:
parent
7b3b171134
commit
3d914f5b4e
21 changed files with 754 additions and 524 deletions
|
@ -41,7 +41,11 @@ class UnidentifiedError(Exception):
|
|||
|
||||
def __repr__(self):
|
||||
return "<%s(%r, %r, ..., secondary=%r)>" % (
|
||||
type(self).__name__, self.retcode, self.argv, self.secondary)
|
||||
type(self).__name__,
|
||||
self.retcode,
|
||||
self.argv,
|
||||
self.secondary,
|
||||
)
|
||||
|
||||
|
||||
def shebang_binary(p):
|
||||
|
|
|
@ -20,7 +20,12 @@ import os
|
|||
import shlex
|
||||
import sys
|
||||
from . import UnidentifiedError, DetailedFailure
|
||||
from .buildlog import InstallFixer, ExplainInstallFixer, ExplainInstall, install_missing_reqs
|
||||
from .buildlog import (
|
||||
InstallFixer,
|
||||
ExplainInstallFixer,
|
||||
ExplainInstall,
|
||||
install_missing_reqs,
|
||||
)
|
||||
from .buildsystem import NoBuildToolsFound, detect_buildsystems
|
||||
from .resolver import (
|
||||
auto_resolver,
|
||||
|
@ -34,8 +39,7 @@ def display_explain_commands(commands):
|
|||
for command, reqs in commands:
|
||||
if isinstance(command, list):
|
||||
command = shlex.join(command)
|
||||
logging.info(
|
||||
' %s (to install %s)', command, ', '.join(map(str, reqs)))
|
||||
logging.info(" %s (to install %s)", command, ", ".join(map(str, reqs)))
|
||||
|
||||
|
||||
def get_necessary_declared_requirements(resolver, requirements, stages):
|
||||
|
@ -46,7 +50,9 @@ def get_necessary_declared_requirements(resolver, requirements, stages):
|
|||
return missing
|
||||
|
||||
|
||||
def install_necessary_declared_requirements(session, resolver, fixers, buildsystems, stages, explain=False):
|
||||
def install_necessary_declared_requirements(
|
||||
session, resolver, fixers, buildsystems, stages, explain=False
|
||||
):
|
||||
relevant = []
|
||||
declared_reqs = []
|
||||
for buildsystem in buildsystems:
|
||||
|
@ -153,8 +159,7 @@ def main(): # noqa: C901
|
|||
logging.info("Using requirement resolver: %s", resolver)
|
||||
try:
|
||||
bss = list(detect_buildsystems(args.directory))
|
||||
logging.info(
|
||||
"Detected buildsystems: %s", ', '.join(map(str, bss)))
|
||||
logging.info("Detected buildsystems: %s", ", ".join(map(str, bss)))
|
||||
fixers = determine_fixers(session, resolver, explain=args.explain)
|
||||
if not args.ignore_declared_dependencies:
|
||||
stages = STAGE_MAP[args.subcommand]
|
||||
|
@ -162,7 +167,8 @@ def main(): # noqa: C901
|
|||
logging.info("Checking that declared requirements are present")
|
||||
try:
|
||||
install_necessary_declared_requirements(
|
||||
session, resolver, fixers, bss, stages, explain=args.explain)
|
||||
session, resolver, fixers, bss, stages, explain=args.explain
|
||||
)
|
||||
except ExplainInstall as e:
|
||||
display_explain_commands(e.commands)
|
||||
return 1
|
||||
|
@ -170,8 +176,11 @@ def main(): # noqa: C901
|
|||
from .dist import run_dist
|
||||
|
||||
run_dist(
|
||||
session=session, buildsystems=bss, resolver=resolver, fixers=fixers,
|
||||
target_directory='.'
|
||||
session=session,
|
||||
buildsystems=bss,
|
||||
resolver=resolver,
|
||||
fixers=fixers,
|
||||
target_directory=".",
|
||||
)
|
||||
if args.subcommand == "build":
|
||||
from .build import run_build
|
||||
|
|
|
@ -141,11 +141,12 @@ def problem_to_upstream_requirement(problem): # noqa: C901
|
|||
elif isinstance(problem, MissingJavaClass):
|
||||
return JavaClassRequirement(problem.classname)
|
||||
elif isinstance(problem, MissingHaskellDependencies):
|
||||
return [HaskellPackageRequirement.from_string(dep)
|
||||
for dep in problem.deps]
|
||||
return [HaskellPackageRequirement.from_string(dep) for dep in problem.deps]
|
||||
elif isinstance(problem, MissingMavenArtifacts):
|
||||
return [MavenArtifactRequirement.from_str(artifact)
|
||||
for artifact in problem.artifacts]
|
||||
return [
|
||||
MavenArtifactRequirement.from_str(artifact)
|
||||
for artifact in problem.artifacts
|
||||
]
|
||||
elif isinstance(problem, MissingCSharpCompiler):
|
||||
return BinaryRequirement("msc")
|
||||
elif isinstance(problem, GnomeCommonMissing):
|
||||
|
@ -236,7 +237,6 @@ class InstallFixer(BuildFixer):
|
|||
|
||||
|
||||
class ExplainInstall(Exception):
|
||||
|
||||
def __init__(self, commands):
|
||||
self.commands = commands
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ from .requirements import (
|
|||
GoRequirement,
|
||||
GoPackageRequirement,
|
||||
)
|
||||
from .fix_build import run_with_build_fixers, run_detecting_problems
|
||||
from .fix_build import run_with_build_fixers
|
||||
from .session import which
|
||||
|
||||
|
||||
|
@ -75,7 +75,9 @@ class BuildSystem(object):
|
|||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def dist(self, session, resolver, fixers, target_directory: str, quiet=False) -> str:
|
||||
def dist(
|
||||
self, session, resolver, fixers, target_directory: str, quiet=False
|
||||
) -> str:
|
||||
raise NotImplementedError(self.dist)
|
||||
|
||||
def test(self, session, resolver, fixers):
|
||||
|
@ -103,11 +105,12 @@ class BuildSystem(object):
|
|||
|
||||
def xmlparse_simplify_namespaces(path, namespaces):
|
||||
import xml.etree.ElementTree as ET
|
||||
namespaces = ['{%s}' % ns for ns in namespaces]
|
||||
|
||||
namespaces = ["{%s}" % ns for ns in namespaces]
|
||||
tree = ET.iterparse(path)
|
||||
for _, el in tree:
|
||||
for namespace in namespaces:
|
||||
el.tag = el.tag.replace(namespace, '')
|
||||
el.tag = el.tag.replace(namespace, "")
|
||||
return tree.root
|
||||
|
||||
|
||||
|
@ -123,7 +126,7 @@ class Pear(BuildSystem):
|
|||
|
||||
def dist(self, session, resolver, fixers, target_directory: str, quiet=False):
|
||||
self.setup(resolver)
|
||||
with DistCatcher([session.external_path('.')]) as dc:
|
||||
with DistCatcher([session.external_path(".")]) as dc:
|
||||
run_with_build_fixers(session, ["pear", "package"], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
|
||||
|
@ -146,28 +149,34 @@ class Pear(BuildSystem):
|
|||
def get_declared_dependencies(self, session, fixers=None):
|
||||
path = os.path.join(self.path, "package.xml")
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
try:
|
||||
root = xmlparse_simplify_namespaces(path, [
|
||||
'http://pear.php.net/dtd/package-2.0',
|
||||
'http://pear.php.net/dtd/package-2.1'])
|
||||
root = xmlparse_simplify_namespaces(
|
||||
path,
|
||||
[
|
||||
"http://pear.php.net/dtd/package-2.0",
|
||||
"http://pear.php.net/dtd/package-2.1",
|
||||
],
|
||||
)
|
||||
except ET.ParseError as e:
|
||||
logging.warning('Unable to parse package.xml: %s', e)
|
||||
logging.warning("Unable to parse package.xml: %s", e)
|
||||
return
|
||||
assert root.tag == 'package', 'root tag is %r' % root.tag
|
||||
dependencies_tag = root.find('dependencies')
|
||||
assert root.tag == "package", "root tag is %r" % root.tag
|
||||
dependencies_tag = root.find("dependencies")
|
||||
if dependencies_tag is not None:
|
||||
required_tag = root.find('dependencies')
|
||||
required_tag = root.find("dependencies")
|
||||
if required_tag is not None:
|
||||
for package_tag in root.findall('package'):
|
||||
name = package_tag.find('name').text
|
||||
min_tag = package_tag.find('min')
|
||||
max_tag = package_tag.find('max')
|
||||
channel_tag = package_tag.find('channel')
|
||||
for package_tag in root.findall("package"):
|
||||
name = package_tag.find("name").text
|
||||
min_tag = package_tag.find("min")
|
||||
max_tag = package_tag.find("max")
|
||||
channel_tag = package_tag.find("channel")
|
||||
yield "core", PhpPackageRequirement(
|
||||
name,
|
||||
channel=(channel_tag.text if channel_tag else None),
|
||||
min_version=(min_tag.text if min_tag else None),
|
||||
max_version=(max_tag.text if max_tag else None))
|
||||
max_version=(max_tag.text if max_tag else None),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def probe(cls, path):
|
||||
|
@ -179,6 +188,7 @@ class Pear(BuildSystem):
|
|||
# run_setup, but setting __name__
|
||||
# Imported from Python's distutils.core, Copyright (C) PSF
|
||||
|
||||
|
||||
def run_setup(script_name, script_args=None, stop_after="run"):
|
||||
from distutils import core
|
||||
import sys
|
||||
|
@ -260,11 +270,11 @@ with open(%(output_path)s, 'w') as f:
|
|||
class SetupPy(BuildSystem):
|
||||
|
||||
name = "setup.py"
|
||||
DEFAULT_PYTHON = 'python3'
|
||||
DEFAULT_PYTHON = "python3"
|
||||
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
if os.path.exists(os.path.join(self.path, 'setup.py')):
|
||||
if os.path.exists(os.path.join(self.path, "setup.py")):
|
||||
self.has_setup_py = True
|
||||
else:
|
||||
self.has_setup_py = False
|
||||
|
@ -280,7 +290,9 @@ class SetupPy(BuildSystem):
|
|||
self.pyproject = None
|
||||
self.build_backend = None
|
||||
else:
|
||||
self.build_backend = self.pyproject.get("build-system", {}).get('build-backend')
|
||||
self.build_backend = self.pyproject.get("build-system", {}).get(
|
||||
"build-backend"
|
||||
)
|
||||
|
||||
def load_toml(self):
|
||||
import toml
|
||||
|
@ -290,7 +302,8 @@ class SetupPy(BuildSystem):
|
|||
|
||||
def load_setup_cfg(self):
|
||||
from setuptools.config import read_configuration
|
||||
p = os.path.join(self.path, 'setup.cfg')
|
||||
|
||||
p = os.path.join(self.path, "setup.cfg")
|
||||
if os.path.exists(p):
|
||||
return read_configuration(p)
|
||||
raise FileNotFoundError(p)
|
||||
|
@ -304,7 +317,7 @@ class SetupPy(BuildSystem):
|
|||
return self._extract_setup_in_session(session, fixers)
|
||||
|
||||
def _extract_setup_direct(self):
|
||||
p = os.path.join(self.path, 'setup.py')
|
||||
p = os.path.join(self.path, "setup.py")
|
||||
try:
|
||||
d = run_setup(os.path.abspath(p), stop_after="init")
|
||||
except RuntimeError as e:
|
||||
|
@ -313,37 +326,42 @@ class SetupPy(BuildSystem):
|
|||
if d is None:
|
||||
logging.warning(
|
||||
"'distutils.core.setup()' was never called -- "
|
||||
"perhaps '%s' is not a Distutils setup script?" % os.path.basename(p))
|
||||
"perhaps '%s' is not a Distutils setup script?" % os.path.basename(p)
|
||||
)
|
||||
return None
|
||||
|
||||
return {
|
||||
'name': d.name,
|
||||
'setup_requires': getattr(d, "setup_requires", []),
|
||||
'install_requires': getattr(d, "install_requires", []),
|
||||
'tests_require': getattr(d, "tests_require", []) or [],
|
||||
'scripts': getattr(d, "scripts", []),
|
||||
'entry_points': getattr(d, "entry_points", None) or {},
|
||||
'packages': getattr(d, "packages", []),
|
||||
'requires': d.get_requires() or [],
|
||||
"name": d.name,
|
||||
"setup_requires": getattr(d, "setup_requires", []),
|
||||
"install_requires": getattr(d, "install_requires", []),
|
||||
"tests_require": getattr(d, "tests_require", []) or [],
|
||||
"scripts": getattr(d, "scripts", []),
|
||||
"entry_points": getattr(d, "entry_points", None) or {},
|
||||
"packages": getattr(d, "packages", []),
|
||||
"requires": d.get_requires() or [],
|
||||
}
|
||||
|
||||
def _extract_setup_in_session(self, session, fixers=None):
|
||||
import tempfile
|
||||
import json
|
||||
|
||||
interpreter = shebang_binary(os.path.join(self.path, "setup.py"))
|
||||
if interpreter is None:
|
||||
interpreter = self.DEFAULT_PYTHON
|
||||
output_f = tempfile.NamedTemporaryFile(
|
||||
dir=os.path.join(session.location, 'tmp'), mode='w+t')
|
||||
dir=os.path.join(session.location, "tmp"), mode="w+t"
|
||||
)
|
||||
with output_f:
|
||||
# TODO(jelmer): Perhaps run this in session, so we can install
|
||||
# missing dependencies?
|
||||
argv = [interpreter, "-c",
|
||||
_setup_wrapper
|
||||
.replace('%(script_name)s', '"setup.py"')
|
||||
.replace('%(output_path)s',
|
||||
'"/' + os.path.relpath(output_f.name, session.location) +
|
||||
'"')]
|
||||
argv = [
|
||||
interpreter,
|
||||
"-c",
|
||||
_setup_wrapper.replace("%(script_name)s", '"setup.py"').replace(
|
||||
"%(output_path)s",
|
||||
'"/' + os.path.relpath(output_f.name, session.location) + '"',
|
||||
),
|
||||
]
|
||||
try:
|
||||
if fixers is not None:
|
||||
run_with_build_fixers(session, argv, fixers)
|
||||
|
@ -359,15 +377,17 @@ class SetupPy(BuildSystem):
|
|||
return "%s(%r)" % (type(self).__name__, self.path)
|
||||
|
||||
def test(self, session, resolver, fixers):
|
||||
if os.path.exists(os.path.join(self.path, 'tox.ini')):
|
||||
run_with_build_fixers(session, ['tox'], fixers)
|
||||
if os.path.exists(os.path.join(self.path, "tox.ini")):
|
||||
run_with_build_fixers(session, ["tox"], fixers)
|
||||
elif self.pyproject:
|
||||
run_with_build_fixers(session, [self.DEFAULT_PYTHON, "-m", "pep517.check", "."], fixers)
|
||||
run_with_build_fixers(
|
||||
session, [self.DEFAULT_PYTHON, "-m", "pep517.check", "."], fixers
|
||||
)
|
||||
elif self.has_setup_py:
|
||||
# Pre-emptively insall setuptools, since distutils doesn't provide
|
||||
# a 'test' subcommand and some packages fall back to distutils
|
||||
# if setuptools is not available.
|
||||
resolver.install([PythonPackageRequirement('setuptools')])
|
||||
resolver.install([PythonPackageRequirement("setuptools")])
|
||||
self._run_setup(session, resolver, ["test"], fixers)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
@ -386,13 +406,17 @@ class SetupPy(BuildSystem):
|
|||
preargs.append("--quiet")
|
||||
# Preemptively install setuptools since some packages fail in
|
||||
# some way without it.
|
||||
resolver.install([PythonPackageRequirement('setuptools')])
|
||||
with DistCatcher([session.external_path('dist')]) as dc:
|
||||
resolver.install([PythonPackageRequirement("setuptools")])
|
||||
with DistCatcher([session.external_path("dist")]) as dc:
|
||||
self._run_setup(session, resolver, preargs + ["sdist"], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
elif self.pyproject:
|
||||
with DistCatcher([session.external_path('dist')]) as dc:
|
||||
run_with_build_fixers(session, [self.DEFAULT_PYTHON, "-m", "pep517.build", "--source", "."], fixers)
|
||||
with DistCatcher([session.external_path("dist")]) as dc:
|
||||
run_with_build_fixers(
|
||||
session,
|
||||
[self.DEFAULT_PYTHON, "-m", "pep517.build", "--source", "."],
|
||||
fixers,
|
||||
)
|
||||
return dc.copy_single(target_directory)
|
||||
raise AssertionError("no setup.py or pyproject.toml")
|
||||
|
||||
|
@ -413,79 +437,83 @@ class SetupPy(BuildSystem):
|
|||
|
||||
def _run_setup(self, session, resolver, args, fixers):
|
||||
from .buildlog import install_missing_reqs
|
||||
|
||||
# Install the setup_requires beforehand, since otherwise
|
||||
# setuptools might fetch eggs instead of our preferred resolver.
|
||||
install_missing_reqs(session, resolver, list(self._setup_requires()))
|
||||
interpreter = shebang_binary(os.path.join(self.path, 'setup.py'))
|
||||
interpreter = shebang_binary(os.path.join(self.path, "setup.py"))
|
||||
if interpreter is None:
|
||||
interpreter = self.DEFAULT_PYTHON
|
||||
argv = [interpreter, "./setup.py"] + args
|
||||
env = {}
|
||||
# Inherit SETUPTOOLS_SCM_PRETEND_VERSION from the current environment
|
||||
if 'SETUPTOOLS_SCM_PRETEND_VERSION' in os.environ:
|
||||
env['SETUPTOOLS_SCM_PRETEND_VERSION'] = (
|
||||
os.environ['SETUPTOOLS_SCM_PRETEND_VERSION'])
|
||||
if "SETUPTOOLS_SCM_PRETEND_VERSION" in os.environ:
|
||||
env["SETUPTOOLS_SCM_PRETEND_VERSION"] = os.environ[
|
||||
"SETUPTOOLS_SCM_PRETEND_VERSION"
|
||||
]
|
||||
run_with_build_fixers(session, argv, fixers, env=env)
|
||||
|
||||
def _setup_requires(self):
|
||||
if self.pyproject:
|
||||
if "build-system" in self.pyproject:
|
||||
for require in self.pyproject['build-system'].get("requires", []):
|
||||
for require in self.pyproject["build-system"].get("requires", []):
|
||||
yield PythonPackageRequirement.from_requirement_str(require)
|
||||
if self.config:
|
||||
options = self.config.get('options', {})
|
||||
for require in options.get('setup_requires', []):
|
||||
options = self.config.get("options", {})
|
||||
for require in options.get("setup_requires", []):
|
||||
yield PythonPackageRequirement.from_requirement_str(require)
|
||||
|
||||
def get_declared_dependencies(self, session, fixers=None):
|
||||
distribution = self._extract_setup(session, fixers)
|
||||
if distribution is not None:
|
||||
for require in distribution['requires']:
|
||||
for require in distribution["requires"]:
|
||||
yield "core", PythonPackageRequirement.from_requirement_str(require)
|
||||
# Not present for distutils-only packages
|
||||
for require in distribution['setup_requires']:
|
||||
for require in distribution["setup_requires"]:
|
||||
yield "build", PythonPackageRequirement.from_requirement_str(require)
|
||||
# Not present for distutils-only packages
|
||||
for require in distribution['install_requires']:
|
||||
for require in distribution["install_requires"]:
|
||||
yield "core", PythonPackageRequirement.from_requirement_str(require)
|
||||
# Not present for distutils-only packages
|
||||
for require in distribution['tests_require']:
|
||||
for require in distribution["tests_require"]:
|
||||
yield "test", PythonPackageRequirement.from_requirement_str(require)
|
||||
if self.pyproject:
|
||||
if "build-system" in self.pyproject:
|
||||
for require in self.pyproject['build-system'].get("requires", []):
|
||||
yield "build", PythonPackageRequirement.from_requirement_str(require)
|
||||
for require in self.pyproject["build-system"].get("requires", []):
|
||||
yield "build", PythonPackageRequirement.from_requirement_str(
|
||||
require
|
||||
)
|
||||
if self.config:
|
||||
options = self.config.get('options', {})
|
||||
for require in options.get('setup_requires', []):
|
||||
options = self.config.get("options", {})
|
||||
for require in options.get("setup_requires", []):
|
||||
yield "build", PythonPackageRequirement.from_requirement_str(require)
|
||||
for require in options.get('install_requires', []):
|
||||
for require in options.get("install_requires", []):
|
||||
yield "core", PythonPackageRequirement.from_requirement_str(require)
|
||||
|
||||
def get_declared_outputs(self, session, fixers=None):
|
||||
distribution = self._extract_setup(session, fixers)
|
||||
all_packages = set()
|
||||
if distribution is not None:
|
||||
for script in distribution['scripts']:
|
||||
for script in distribution["scripts"]:
|
||||
yield BinaryOutput(os.path.basename(script))
|
||||
for script in distribution["entry_points"].get("console_scripts", []):
|
||||
yield BinaryOutput(script.split("=")[0])
|
||||
all_packages.update(distribution['packages'])
|
||||
all_packages.update(distribution["packages"])
|
||||
if self.config:
|
||||
options = self.config.get('options', {})
|
||||
all_packages.update(options.get('packages', []))
|
||||
for script in options.get('scripts', []):
|
||||
options = self.config.get("options", {})
|
||||
all_packages.update(options.get("packages", []))
|
||||
for script in options.get("scripts", []):
|
||||
yield BinaryOutput(os.path.basename(script))
|
||||
for script in options.get("entry_points", {}).get("console_scripts", []):
|
||||
yield BinaryOutput(script.split("=")[0])
|
||||
|
||||
packages = set()
|
||||
for package in sorted(all_packages):
|
||||
pts = package.split('.')
|
||||
pts = package.split(".")
|
||||
b = []
|
||||
for e in pts:
|
||||
b.append(e)
|
||||
if '.'.join(b) in packages:
|
||||
if ".".join(b) in packages:
|
||||
break
|
||||
else:
|
||||
packages.add(package)
|
||||
|
@ -521,12 +549,12 @@ class Octave(BuildSystem):
|
|||
return False
|
||||
# Urgh, isn't there a better way to see if this is an octave package?
|
||||
for entry in os.scandir(path):
|
||||
if entry.name.endswith('.m'):
|
||||
if entry.name.endswith(".m"):
|
||||
return True
|
||||
if not entry.is_dir():
|
||||
continue
|
||||
for subentry in os.scandir(entry.path):
|
||||
if subentry.name.endswith('.m'):
|
||||
if subentry.name.endswith(".m"):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -537,17 +565,19 @@ class Octave(BuildSystem):
|
|||
return cls(path)
|
||||
|
||||
def _read_description(self):
|
||||
path = os.path.join(self.path, 'DESCRIPTION')
|
||||
path = os.path.join(self.path, "DESCRIPTION")
|
||||
from email.parser import BytesParser
|
||||
with open(path, 'rb') as f:
|
||||
|
||||
with open(path, "rb") as f:
|
||||
return BytesParser().parse(f)
|
||||
|
||||
def get_declared_dependencies(self, session, fixers=None):
|
||||
def parse_list(t):
|
||||
return [s.strip() for s in t.split(',') if s.strip()]
|
||||
return [s.strip() for s in t.split(",") if s.strip()]
|
||||
|
||||
description = self._read_description()
|
||||
if 'Depends' in description:
|
||||
for s in parse_list(description['Depends']):
|
||||
if "Depends" in description:
|
||||
for s in parse_list(description["Depends"]):
|
||||
yield "build", OctavePackageRequirement.from_str(s)
|
||||
|
||||
|
||||
|
@ -564,14 +594,14 @@ class Gradle(BuildSystem):
|
|||
|
||||
@classmethod
|
||||
def exists(cls, path):
|
||||
return (
|
||||
os.path.exists(os.path.join(path, "build.gradle")) or
|
||||
os.path.exists(os.path.join(path, "build.gradle.kts")))
|
||||
return os.path.exists(os.path.join(path, "build.gradle")) or os.path.exists(
|
||||
os.path.join(path, "build.gradle.kts")
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_path(cls, path):
|
||||
if os.path.exists(os.path.join(path, "gradlew")):
|
||||
return cls(path, './gradlew')
|
||||
return cls(path, "./gradlew")
|
||||
return cls(path)
|
||||
|
||||
@classmethod
|
||||
|
@ -581,44 +611,50 @@ class Gradle(BuildSystem):
|
|||
return cls.from_path(path)
|
||||
|
||||
def setup(self, resolver):
|
||||
if not self.executable.startswith('./'):
|
||||
if not self.executable.startswith("./"):
|
||||
resolver.install([BinaryRequirement(self.executable)])
|
||||
|
||||
def _run(self, session, resolver, task, args, fixers):
|
||||
self.setup(resolver)
|
||||
argv = []
|
||||
if self.executable.startswith('./') and (
|
||||
not os.access(os.path.join(self.path, self.executable), os.X_OK)):
|
||||
argv.append('sh')
|
||||
if self.executable.startswith("./") and (
|
||||
not os.access(os.path.join(self.path, self.executable), os.X_OK)
|
||||
):
|
||||
argv.append("sh")
|
||||
argv.extend([self.executable, task])
|
||||
argv.extend(args)
|
||||
try:
|
||||
run_with_build_fixers(session, argv, fixers)
|
||||
except UnidentifiedError as e:
|
||||
if any([re.match(
|
||||
r"Task '" + task + "' not found in root project '.*'\.",
|
||||
line) for line in e.lines]):
|
||||
if any(
|
||||
[
|
||||
re.match(
|
||||
r"Task '" + task + r"' not found in root project '.*'\.", line
|
||||
)
|
||||
for line in e.lines
|
||||
]
|
||||
):
|
||||
raise NotImplementedError
|
||||
raise
|
||||
|
||||
def clean(self, session, resolver, fixers):
|
||||
self._run(session, resolver, 'clean', [], fixers)
|
||||
self._run(session, resolver, "clean", [], fixers)
|
||||
|
||||
def build(self, session, resolver, fixers):
|
||||
self._run(session, resolver, 'build', [], fixers)
|
||||
self._run(session, resolver, "build", [], fixers)
|
||||
|
||||
def test(self, session, resolver, fixers):
|
||||
self._run(session, resolver, 'test', [], fixers)
|
||||
self._run(session, resolver, "test", [], fixers)
|
||||
|
||||
def dist(self, session, resolver, fixers, target_directory, quiet=False):
|
||||
with DistCatcher([session.external_path('.')]) as dc:
|
||||
self._run(session, resolver, 'distTar', [], fixers)
|
||||
with DistCatcher([session.external_path(".")]) as dc:
|
||||
self._run(session, resolver, "distTar", [], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
|
||||
def install(self, session, resolver, fixers, install_target):
|
||||
raise NotImplementedError
|
||||
# TODO(jelmer): installDist just creates files under build/install/...
|
||||
self._run(session, resolver, 'installDist', [], fixers)
|
||||
self._run(session, resolver, "installDist", [], fixers)
|
||||
|
||||
|
||||
class R(BuildSystem):
|
||||
|
@ -638,7 +674,7 @@ class R(BuildSystem):
|
|||
|
||||
def dist(self, session, resolver, fixers, target_directory, quiet=False):
|
||||
r_path = guaranteed_which(session, resolver, "R")
|
||||
with DistCatcher([session.external_path('.')]) as dc:
|
||||
with DistCatcher([session.external_path(".")]) as dc:
|
||||
run_with_build_fixers(session, [r_path, "CMD", "build", "."], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
|
||||
|
@ -652,34 +688,37 @@ class R(BuildSystem):
|
|||
|
||||
@classmethod
|
||||
def probe(cls, path):
|
||||
if (os.path.exists(os.path.join(path, 'DESCRIPTION')) and
|
||||
os.path.exists(os.path.join(path, 'NAMESPACE'))):
|
||||
if os.path.exists(os.path.join(path, "DESCRIPTION")) and os.path.exists(
|
||||
os.path.join(path, "NAMESPACE")
|
||||
):
|
||||
return cls(path)
|
||||
|
||||
def _read_description(self):
|
||||
path = os.path.join(self.path, 'DESCRIPTION')
|
||||
path = os.path.join(self.path, "DESCRIPTION")
|
||||
from email.parser import BytesParser
|
||||
with open(path, 'rb') as f:
|
||||
|
||||
with open(path, "rb") as f:
|
||||
return BytesParser().parse(f)
|
||||
|
||||
def get_declared_dependencies(self, session, fixers=None):
|
||||
def parse_list(t):
|
||||
return [s.strip() for s in t.split(',') if s.strip()]
|
||||
return [s.strip() for s in t.split(",") if s.strip()]
|
||||
|
||||
description = self._read_description()
|
||||
if 'Suggests' in description:
|
||||
for s in parse_list(description['Suggests']):
|
||||
if "Suggests" in description:
|
||||
for s in parse_list(description["Suggests"]):
|
||||
yield "build", RPackageRequirement.from_str(s)
|
||||
if 'Depends' in description:
|
||||
for s in parse_list(description['Depends']):
|
||||
if "Depends" in description:
|
||||
for s in parse_list(description["Depends"]):
|
||||
yield "build", RPackageRequirement.from_str(s)
|
||||
if 'Imports' in description:
|
||||
for s in parse_list(description['Imports']):
|
||||
if "Imports" in description:
|
||||
for s in parse_list(description["Imports"]):
|
||||
yield "build", RPackageRequirement.from_str(s)
|
||||
|
||||
def get_declared_outputs(self, session, fixers=None):
|
||||
description = self._read_description()
|
||||
if 'Package' in description:
|
||||
yield RPackageOutput(description['Package'])
|
||||
if "Package" in description:
|
||||
yield RPackageOutput(description["Package"])
|
||||
|
||||
|
||||
class Meson(BuildSystem):
|
||||
|
@ -693,8 +732,8 @@ class Meson(BuildSystem):
|
|||
return "%s(%r)" % (type(self).__name__, self.path)
|
||||
|
||||
def _setup(self, session, fixers):
|
||||
if not session.exists('build'):
|
||||
session.check_call(['mkdir', 'build'])
|
||||
if not session.exists("build"):
|
||||
session.check_call(["mkdir", "build"])
|
||||
run_with_build_fixers(session, ["meson", "setup", "build"], fixers)
|
||||
|
||||
def clean(self, session, resolver, fixers):
|
||||
|
@ -707,7 +746,7 @@ class Meson(BuildSystem):
|
|||
|
||||
def dist(self, session, resolver, fixers, target_directory, quiet=False):
|
||||
self._setup(session, fixers)
|
||||
with DistCatcher([session.external_path('build/meson-dist')]) as dc:
|
||||
with DistCatcher([session.external_path("build/meson-dist")]) as dc:
|
||||
run_with_build_fixers(session, ["ninja", "-C", "build", "dist"], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
|
||||
|
@ -742,7 +781,7 @@ class Npm(BuildSystem):
|
|||
return "%s(%r)" % (type(self).__name__, self.path)
|
||||
|
||||
def get_declared_dependencies(self, session, fixers=None):
|
||||
if 'dependencies' in self.package:
|
||||
if "dependencies" in self.package:
|
||||
for name, unused_version in self.package["dependencies"].items():
|
||||
# TODO(jelmer): Look at version
|
||||
yield "core", NodePackageRequirement(name)
|
||||
|
@ -756,13 +795,13 @@ class Npm(BuildSystem):
|
|||
|
||||
def dist(self, session, resolver, fixers, target_directory, quiet=False):
|
||||
self.setup(resolver)
|
||||
with DistCatcher([session.external_path('.')]) as dc:
|
||||
with DistCatcher([session.external_path(".")]) as dc:
|
||||
run_with_build_fixers(session, ["npm", "pack"], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
|
||||
def test(self, session, resolver, fixers):
|
||||
self.setup(resolver)
|
||||
test_script = self.package['scripts'].get('test')
|
||||
test_script = self.package["scripts"].get("test")
|
||||
if test_script:
|
||||
run_with_build_fixers(session, shlex.split(test_script), fixers)
|
||||
else:
|
||||
|
@ -770,7 +809,7 @@ class Npm(BuildSystem):
|
|||
|
||||
def build(self, session, resolver, fixers):
|
||||
self.setup(resolver)
|
||||
build_script = self.package['scripts'].get('build')
|
||||
build_script = self.package["scripts"].get("build")
|
||||
if build_script:
|
||||
run_with_build_fixers(session, shlex.split(build_script), fixers)
|
||||
else:
|
||||
|
@ -778,7 +817,7 @@ class Npm(BuildSystem):
|
|||
|
||||
def clean(self, session, resolver, fixers):
|
||||
self.setup(resolver)
|
||||
clean_script = self.package['scripts'].get('clean')
|
||||
clean_script = self.package["scripts"].get("clean")
|
||||
if clean_script:
|
||||
run_with_build_fixers(session, shlex.split(clean_script), fixers)
|
||||
else:
|
||||
|
@ -803,7 +842,7 @@ class Waf(BuildSystem):
|
|||
|
||||
def dist(self, session, resolver, fixers, target_directory, quiet=False):
|
||||
self.setup(session, resolver, fixers)
|
||||
with DistCatcher.default(session.external_path('.')) as dc:
|
||||
with DistCatcher.default(session.external_path(".")) as dc:
|
||||
run_with_build_fixers(session, ["./waf", "dist"], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
|
||||
|
@ -835,13 +874,15 @@ class Gem(BuildSystem):
|
|||
]
|
||||
if len(gemfiles) > 1:
|
||||
logging.warning("More than one gemfile. Trying the first?")
|
||||
with DistCatcher.default(session.external_path('.')) as dc:
|
||||
with DistCatcher.default(session.external_path(".")) as dc:
|
||||
run_with_build_fixers(session, ["gem2tgz", gemfiles[0]], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
|
||||
@classmethod
|
||||
def probe(cls, path):
|
||||
gemfiles = [entry.path for entry in os.scandir(path) if entry.name.endswith(".gem")]
|
||||
gemfiles = [
|
||||
entry.path for entry in os.scandir(path) if entry.name.endswith(".gem")
|
||||
]
|
||||
if gemfiles:
|
||||
return cls(gemfiles[0])
|
||||
|
||||
|
@ -881,13 +922,13 @@ class DistZilla(BuildSystem):
|
|||
self.setup(resolver)
|
||||
if self.name == "dist-inkt":
|
||||
resolver.install([PerlModuleRequirement(self.dist_inkt_class)])
|
||||
with DistCatcher.default(session.external_path('.')) as dc:
|
||||
with DistCatcher.default(session.external_path(".")) as dc:
|
||||
run_with_build_fixers(session, ["distinkt-dist"], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
else:
|
||||
# Default to invoking Dist::Zilla
|
||||
resolver.install([PerlModuleRequirement("Dist::Zilla")])
|
||||
with DistCatcher.default(session.external_path('.')) as dc:
|
||||
with DistCatcher.default(session.external_path(".")) as dc:
|
||||
run_with_build_fixers(session, ["dzil", "build", "--tgz"], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
|
||||
|
@ -939,13 +980,13 @@ class RunTests(BuildSystem):
|
|||
|
||||
|
||||
def _read_cpanfile(session, args, kind, fixers):
|
||||
for line in run_with_build_fixers(session, ['cpanfile-dump'] + args, fixers):
|
||||
for line in run_with_build_fixers(session, ["cpanfile-dump"] + args, fixers):
|
||||
yield kind, PerlModuleRequirement(line)
|
||||
|
||||
|
||||
def _declared_deps_from_cpanfile(session, fixers):
|
||||
yield from _read_cpanfile(session, ['--configure', '--build'], 'build', fixers)
|
||||
yield from _read_cpanfile(session, ['--test'], 'test', fixers)
|
||||
yield from _read_cpanfile(session, ["--configure", "--build"], "build", fixers)
|
||||
yield from _read_cpanfile(session, ["--test"], "test", fixers)
|
||||
|
||||
|
||||
class Make(BuildSystem):
|
||||
|
@ -989,7 +1030,9 @@ class Make(BuildSystem):
|
|||
if not makefile_exists() and session.exists("configure"):
|
||||
run_with_build_fixers(session, ["./configure"], fixers)
|
||||
|
||||
if not makefile_exists() and any([n.name.endswith('.pro') for n in session.scandir(".")]):
|
||||
if not makefile_exists() and any(
|
||||
[n.name.endswith(".pro") for n in session.scandir(".")]
|
||||
):
|
||||
run_with_build_fixers(session, ["qmake"], fixers)
|
||||
|
||||
def build(self, session, resolver, fixers):
|
||||
|
@ -1010,7 +1053,7 @@ class Make(BuildSystem):
|
|||
|
||||
def dist(self, session, resolver, fixers, target_directory, quiet=False):
|
||||
self.setup(session, resolver, fixers)
|
||||
with DistCatcher.default(session.external_path('.')) as dc:
|
||||
with DistCatcher.default(session.external_path(".")) as dc:
|
||||
try:
|
||||
run_with_build_fixers(session, ["make", "dist"], fixers)
|
||||
except UnidentifiedError as e:
|
||||
|
@ -1106,7 +1149,7 @@ class Make(BuildSystem):
|
|||
return cls(path)
|
||||
for n in os.scandir(path):
|
||||
# qmake
|
||||
if n.name.endswith('.pro'):
|
||||
if n.name.endswith(".pro"):
|
||||
return cls(path)
|
||||
|
||||
|
||||
|
@ -1133,8 +1176,9 @@ class Cargo(BuildSystem):
|
|||
# TODO(jelmer): Look at details['version']
|
||||
yield "build", CargoCrateRequirement(
|
||||
name,
|
||||
features=details.get('features', []),
|
||||
version=details.get("version"))
|
||||
features=details.get("features", []),
|
||||
version=details.get("version"),
|
||||
)
|
||||
|
||||
def test(self, session, resolver, fixers):
|
||||
run_with_build_fixers(session, ["cargo", "test"], fixers)
|
||||
|
@ -1157,19 +1201,20 @@ def _parse_go_mod(f):
|
|||
line = f.readline()
|
||||
if not line:
|
||||
return line
|
||||
return line.split('//')[0] + '\n'
|
||||
return line.split("//")[0] + "\n"
|
||||
|
||||
line = readline()
|
||||
while line:
|
||||
parts = line.strip().split(' ')
|
||||
if not parts or parts == ['']:
|
||||
parts = line.strip().split(" ")
|
||||
if not parts or parts == [""]:
|
||||
continue
|
||||
if len(parts) == 2 and parts[1] == '(':
|
||||
if len(parts) == 2 and parts[1] == "(":
|
||||
line = readline()
|
||||
while line.strip() != ')':
|
||||
yield [parts[0]] + list(line.strip().split(' '))
|
||||
while line.strip() != ")":
|
||||
yield [parts[0]] + list(line.strip().split(" "))
|
||||
line = readline()
|
||||
if not line:
|
||||
raise AssertionError('list of %s interrupted?' % parts[0])
|
||||
raise AssertionError("list of %s interrupted?" % parts[0])
|
||||
else:
|
||||
yield parts
|
||||
line = readline()
|
||||
|
@ -1199,31 +1244,30 @@ class Golang(BuildSystem):
|
|||
session.check_call(["go", "clean"])
|
||||
|
||||
def get_declared_dependencies(self, session, fixers=None):
|
||||
go_mod_path = os.path.join(self.path, 'go.mod')
|
||||
go_mod_path = os.path.join(self.path, "go.mod")
|
||||
if os.path.exists(go_mod_path):
|
||||
with open(go_mod_path, 'r') as f:
|
||||
with open(go_mod_path, "r") as f:
|
||||
for parts in _parse_go_mod(f):
|
||||
if parts[0] == 'go':
|
||||
if parts[0] == "go":
|
||||
yield "build", GoRequirement(parts[1])
|
||||
elif parts[0] == 'require':
|
||||
elif parts[0] == "require":
|
||||
yield "build", GoPackageRequirement(
|
||||
parts[1], parts[2].lstrip('v') if len(parts) > 2 else None)
|
||||
elif parts[0] == 'exclude':
|
||||
parts[1], parts[2].lstrip("v") if len(parts) > 2 else None
|
||||
)
|
||||
elif parts[0] == "exclude":
|
||||
pass # TODO(jelmer): Create conflicts?
|
||||
elif parts[0] == 'replace':
|
||||
elif parts[0] == "replace":
|
||||
pass # TODO(jelmer): do.. something?
|
||||
elif parts[0] == 'module':
|
||||
elif parts[0] == "module":
|
||||
pass
|
||||
else:
|
||||
logging.warning(
|
||||
'Unknown directive %s in go.mod',
|
||||
parts[0])
|
||||
logging.warning("Unknown directive %s in go.mod", parts[0])
|
||||
|
||||
@classmethod
|
||||
def probe(cls, path):
|
||||
if os.path.exists(os.path.join(path, 'go.mod')):
|
||||
if os.path.exists(os.path.join(path, "go.mod")):
|
||||
return Golang(path)
|
||||
if os.path.exists(os.path.join(path, 'go.sum')):
|
||||
if os.path.exists(os.path.join(path, "go.sum")):
|
||||
return Golang(path)
|
||||
for entry in os.scandir(path):
|
||||
if entry.name.endswith(".go"):
|
||||
|
@ -1266,20 +1310,23 @@ class Maven(BuildSystem):
|
|||
|
||||
def get_declared_dependencies(self, session, fixers=None):
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
try:
|
||||
root = xmlparse_simplify_namespaces(self.path,
|
||||
['http://maven.apache.org/POM/4.0.0'])
|
||||
root = xmlparse_simplify_namespaces(
|
||||
self.path, ["http://maven.apache.org/POM/4.0.0"]
|
||||
)
|
||||
except ET.ParseError as e:
|
||||
logging.warning('Unable to parse package.xml: %s', e)
|
||||
logging.warning("Unable to parse package.xml: %s", e)
|
||||
return
|
||||
assert root.tag == 'project', 'root tag is %r' % root.tag
|
||||
deps_tag = root.find('dependencies')
|
||||
assert root.tag == "project", "root tag is %r" % root.tag
|
||||
deps_tag = root.find("dependencies")
|
||||
if deps_tag:
|
||||
for dep in deps_tag.findall('dependency'):
|
||||
for dep in deps_tag.findall("dependency"):
|
||||
yield "core", MavenArtifactRequirement(
|
||||
dep.find('groupId').text,
|
||||
dep.find('artifactId').text,
|
||||
dep.find('version').text)
|
||||
dep.find("groupId").text,
|
||||
dep.find("artifactId").text,
|
||||
dep.find("version").text,
|
||||
)
|
||||
|
||||
|
||||
class Cabal(BuildSystem):
|
||||
|
@ -1310,9 +1357,12 @@ class Cabal(BuildSystem):
|
|||
self._run(session, ["test"], fixers)
|
||||
|
||||
def dist(self, session, resolver, fixers, target_directory, quiet=False):
|
||||
with DistCatcher([
|
||||
session.external_path('dist-newstyle/sdist'),
|
||||
session.external_path('dist')]) as dc:
|
||||
with DistCatcher(
|
||||
[
|
||||
session.external_path("dist-newstyle/sdist"),
|
||||
session.external_path("dist"),
|
||||
]
|
||||
) as dc:
|
||||
self._run(session, ["sdist"], fixers)
|
||||
return dc.copy_single(target_directory)
|
||||
|
||||
|
@ -1377,23 +1427,38 @@ class PerlBuildTiny(BuildSystem):
|
|||
|
||||
|
||||
BUILDSYSTEM_CLSES = [
|
||||
Pear, SetupPy, Npm, Waf, Cargo, Meson, Cabal, Gradle, Maven,
|
||||
DistZilla, Gem, PerlBuildTiny, Golang, R, Octave,
|
||||
Pear,
|
||||
SetupPy,
|
||||
Npm,
|
||||
Waf,
|
||||
Cargo,
|
||||
Meson,
|
||||
Cabal,
|
||||
Gradle,
|
||||
Maven,
|
||||
DistZilla,
|
||||
Gem,
|
||||
PerlBuildTiny,
|
||||
Golang,
|
||||
R,
|
||||
Octave,
|
||||
# Make is intentionally at the end of the list.
|
||||
Make, Composer, RunTests]
|
||||
Make,
|
||||
Composer,
|
||||
RunTests,
|
||||
]
|
||||
|
||||
|
||||
def scan_buildsystems(path):
|
||||
"""Detect build systems."""
|
||||
ret = []
|
||||
ret.extend([('.', bs) for bs in detect_buildsystems(path)])
|
||||
ret.extend([(".", bs) for bs in detect_buildsystems(path)])
|
||||
|
||||
if not ret:
|
||||
# Nothing found. Try the next level?
|
||||
for entry in os.scandir(path):
|
||||
if entry.is_dir():
|
||||
ret.extend(
|
||||
[(entry.name, bs) for bs in detect_buildsystems(entry.path)])
|
||||
ret.extend([(entry.name, bs) for bs in detect_buildsystems(entry.path)])
|
||||
|
||||
return ret
|
||||
|
||||
|
|
|
@ -26,10 +26,17 @@ from buildlog_consultant.apt import (
|
|||
|
||||
from .. import DetailedFailure, UnidentifiedError
|
||||
from ..session import Session, run_with_tee, get_user
|
||||
from .file_search import FileSearcher, AptCachedContentsFileSearcher, GENERATED_FILE_SEARCHER, get_packages_for_paths
|
||||
from .file_search import (
|
||||
FileSearcher,
|
||||
AptCachedContentsFileSearcher,
|
||||
GENERATED_FILE_SEARCHER,
|
||||
get_packages_for_paths,
|
||||
)
|
||||
|
||||
|
||||
def run_apt(session: Session, args: List[str], prefix: Optional[List[str]] = None) -> None:
|
||||
def run_apt(
|
||||
session: Session, args: List[str], prefix: Optional[List[str]] = None
|
||||
) -> None:
|
||||
"""Run apt."""
|
||||
if prefix is None:
|
||||
prefix = []
|
||||
|
@ -84,7 +91,9 @@ class AptManager(object):
|
|||
def get_packages_for_paths(self, paths, regex=False, case_insensitive=False):
|
||||
logging.debug("Searching for packages containing %r", paths)
|
||||
# TODO(jelmer): Make sure we use whatever is configured in self.session
|
||||
return get_packages_for_paths(paths, self.searchers(), regex=regex, case_insensitive=case_insensitive)
|
||||
return get_packages_for_paths(
|
||||
paths, self.searchers(), regex=regex, case_insensitive=case_insensitive
|
||||
)
|
||||
|
||||
def missing(self, packages):
|
||||
root = getattr(self.session, "location", "/")
|
||||
|
|
|
@ -33,7 +33,6 @@ import sys
|
|||
from debian.changelog import Changelog
|
||||
from debmutate.changelog import get_maintainer, format_datetime
|
||||
|
||||
from breezy import osutils
|
||||
from breezy.mutabletree import MutableTree
|
||||
from breezy.plugins.debian.builder import BuildFailedError
|
||||
from breezy.tree import Tree
|
||||
|
|
|
@ -22,7 +22,6 @@ import logging
|
|||
|
||||
|
||||
class BuildDependencyTieBreaker(object):
|
||||
|
||||
def __init__(self, rootdir):
|
||||
self.rootdir = rootdir
|
||||
self._counts = None
|
||||
|
@ -37,8 +36,9 @@ class BuildDependencyTieBreaker(object):
|
|||
def _count(self):
|
||||
counts = {}
|
||||
import apt_pkg
|
||||
|
||||
apt_pkg.init()
|
||||
apt_pkg.config.set('Dir', self.rootdir)
|
||||
apt_pkg.config.set("Dir", self.rootdir)
|
||||
apt_cache = apt_pkg.SourceRecords()
|
||||
apt_cache.restart()
|
||||
while apt_cache.step():
|
||||
|
@ -65,17 +65,20 @@ class BuildDependencyTieBreaker(object):
|
|||
return None
|
||||
top = max(by_count.items(), key=lambda k: k[1])
|
||||
logging.info(
|
||||
'Breaking tie between %r to %r based on build-depends count',
|
||||
[repr(r) for r in reqs], top[0])
|
||||
"Breaking tie between %r to %r based on build-depends count",
|
||||
[repr(r) for r in reqs],
|
||||
top[0],
|
||||
)
|
||||
return top[0]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
from ..resolver.apt import AptRequirement
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('req', nargs='+')
|
||||
parser.add_argument("req", nargs="+")
|
||||
args = parser.parse_args()
|
||||
reqs = [AptRequirement.from_str(req) for req in args.req]
|
||||
tie_breaker = BuildDependencyTieBreaker('/')
|
||||
tie_breaker = BuildDependencyTieBreaker("/")
|
||||
print(tie_breaker(reqs))
|
||||
|
|
|
@ -21,7 +21,7 @@ from datetime import datetime
|
|||
from debian.deb822 import Release
|
||||
import os
|
||||
import re
|
||||
from typing import Iterator, List, Optional, Set
|
||||
from typing import Iterator, List
|
||||
import logging
|
||||
|
||||
|
||||
|
@ -29,7 +29,9 @@ from .. import USER_AGENT
|
|||
|
||||
|
||||
class FileSearcher(object):
|
||||
def search_files(self, path: str, regex: bool = False, case_insensitive: bool = False) -> Iterator[str]:
|
||||
def search_files(
|
||||
self, path: str, regex: bool = False, case_insensitive: bool = False
|
||||
) -> Iterator[str]:
|
||||
raise NotImplementedError(self.search_files)
|
||||
|
||||
|
||||
|
@ -66,14 +68,16 @@ def contents_urls_from_sources_entry(source, arches, load_url):
|
|||
try:
|
||||
response = load_url(release_url)
|
||||
except FileNotFoundError as e:
|
||||
logging.warning('Unable to download %s or %s: %s', inrelease_url, release_url, e)
|
||||
logging.warning(
|
||||
"Unable to download %s or %s: %s", inrelease_url, release_url, e
|
||||
)
|
||||
return
|
||||
|
||||
existing_names = {}
|
||||
release = Release(response.read())
|
||||
for hn in ['MD5Sum', 'SHA1Sum', 'SHA256Sum']:
|
||||
for hn in ["MD5Sum", "SHA1Sum", "SHA256Sum"]:
|
||||
for entry in release.get(hn, []):
|
||||
existing_names[os.path.splitext(entry['name'])[0]] = entry['name']
|
||||
existing_names[os.path.splitext(entry["name"])[0]] = entry["name"]
|
||||
|
||||
contents_files = set()
|
||||
if components:
|
||||
|
@ -117,8 +121,7 @@ def load_direct_url(url):
|
|||
|
||||
for ext in [".xz", ".gz", ""]:
|
||||
try:
|
||||
request = Request(
|
||||
url + ext, headers={"User-Agent": USER_AGENT})
|
||||
request = Request(url + ext, headers={"User-Agent": USER_AGENT})
|
||||
response = urlopen(request)
|
||||
except HTTPError as e:
|
||||
if e.status == 404:
|
||||
|
@ -141,16 +144,17 @@ def load_url_with_cache(url, cache_dirs):
|
|||
|
||||
def load_apt_cache_file(url, cache_dir):
|
||||
fn = apt_pkg.uri_to_filename(url)
|
||||
for ext in ['.xz', '.gz', '.lz4', '']:
|
||||
for ext in [".xz", ".gz", ".lz4", ""]:
|
||||
p = os.path.join(cache_dir, fn + ext)
|
||||
if not os.path.exists(p):
|
||||
continue
|
||||
# return os.popen('/usr/lib/apt/apt-helper cat-file %s' % p)
|
||||
logging.debug("Loading cached contents file %s", p)
|
||||
if ext == '.lz4':
|
||||
if ext == ".lz4":
|
||||
import lz4.frame
|
||||
|
||||
return lz4.frame.open(p, mode="rb")
|
||||
return _unwrap(open(p, 'rb'), ext)
|
||||
return _unwrap(open(p, "rb"), ext)
|
||||
raise FileNotFoundError(url)
|
||||
|
||||
|
||||
|
@ -174,14 +178,15 @@ class AptCachedContentsFileSearcher(FileSearcher):
|
|||
sl.load("/etc/apt/sources.list")
|
||||
|
||||
from .build import get_build_architecture
|
||||
|
||||
cache_dirs = set(["/var/lib/apt/lists"])
|
||||
|
||||
def load_url(url):
|
||||
return load_url_with_cache(url, cache_dirs)
|
||||
|
||||
urls = list(
|
||||
contents_urls_from_sourceslist(
|
||||
sl, get_build_architecture(), load_url))
|
||||
contents_urls_from_sourceslist(sl, get_build_architecture(), load_url)
|
||||
)
|
||||
self._load_urls(urls, cache_dirs, load_url)
|
||||
|
||||
def load_from_session(self, session):
|
||||
|
@ -193,16 +198,19 @@ class AptCachedContentsFileSearcher(FileSearcher):
|
|||
|
||||
from .build import get_build_architecture
|
||||
|
||||
cache_dirs = set([
|
||||
cache_dirs = set(
|
||||
[
|
||||
os.path.join(session.location, "var/lib/apt/lists"),
|
||||
"/var/lib/apt/lists",
|
||||
])
|
||||
]
|
||||
)
|
||||
|
||||
def load_url(url):
|
||||
return load_url_with_cache(url, cache_dirs)
|
||||
|
||||
urls = list(
|
||||
contents_urls_from_sourceslist(sl, get_build_architecture(), load_url))
|
||||
contents_urls_from_sourceslist(sl, get_build_architecture(), load_url)
|
||||
)
|
||||
self._load_urls(urls, cache_dirs, load_url)
|
||||
|
||||
def _load_urls(self, urls, cache_dirs, load_url):
|
||||
|
@ -217,7 +225,7 @@ class AptCachedContentsFileSearcher(FileSearcher):
|
|||
self._db[path] = package
|
||||
|
||||
def search_files(self, path, regex=False, case_insensitive=False):
|
||||
path = path.lstrip('/').encode('utf-8', 'surrogateescape')
|
||||
path = path.lstrip("/").encode("utf-8", "surrogateescape")
|
||||
if case_insensitive and not regex:
|
||||
regex = True
|
||||
path = re.escape(path)
|
||||
|
@ -230,12 +238,12 @@ class AptCachedContentsFileSearcher(FileSearcher):
|
|||
for p, rest in self._db.items():
|
||||
if c.match(p):
|
||||
pkg = rest.split(b"/")[-1]
|
||||
ret.append((p, pkg.decode('utf-8')))
|
||||
ret.append((p, pkg.decode("utf-8")))
|
||||
for p, pkg in sorted(ret):
|
||||
yield pkg
|
||||
else:
|
||||
try:
|
||||
yield self._db[path].split(b"/")[-1].decode('utf-8')
|
||||
yield self._db[path].split(b"/")[-1].decode("utf-8")
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
@ -243,7 +251,7 @@ class AptCachedContentsFileSearcher(FileSearcher):
|
|||
start_time = datetime.now()
|
||||
for path, rest in read_contents_file(f.readlines()):
|
||||
self[path] = rest
|
||||
logging.debug('Read %s in %s', url, datetime.now() - start_time)
|
||||
logging.debug("Read %s in %s", url, datetime.now() - start_time)
|
||||
|
||||
|
||||
class GeneratedFileSearcher(FileSearcher):
|
||||
|
@ -257,12 +265,14 @@ class GeneratedFileSearcher(FileSearcher):
|
|||
return self
|
||||
|
||||
def load_from_path(self, path):
|
||||
with open(path, 'r') as f:
|
||||
with open(path, "r") as f:
|
||||
for line in f:
|
||||
(path, pkg) = line.strip().split(None, 1)
|
||||
self._db[path] = pkg
|
||||
|
||||
def search_files(self, path: str, regex: bool = False, case_insensitive: bool = False) -> Iterator[str]:
|
||||
def search_files(
|
||||
self, path: str, regex: bool = False, case_insensitive: bool = False
|
||||
) -> Iterator[str]:
|
||||
for p, pkg in sorted(self._db.items()):
|
||||
if regex:
|
||||
flags = 0
|
||||
|
@ -294,13 +304,17 @@ GENERATED_FILE_SEARCHER = GeneratedFileSearcher(
|
|||
|
||||
|
||||
def get_packages_for_paths(
|
||||
paths: List[str], searchers: List[FileSearcher], regex: bool = False,
|
||||
case_insensitive: bool = False
|
||||
paths: List[str],
|
||||
searchers: List[FileSearcher],
|
||||
regex: bool = False,
|
||||
case_insensitive: bool = False,
|
||||
) -> List[str]:
|
||||
candidates: List[str] = list()
|
||||
for path in paths:
|
||||
for searcher in searchers:
|
||||
for pkg in searcher.search_files(path, regex=regex, case_insensitive=case_insensitive):
|
||||
for pkg in searcher.search_files(
|
||||
path, regex=regex, case_insensitive=case_insensitive
|
||||
):
|
||||
if pkg not in candidates:
|
||||
candidates.append(pkg)
|
||||
return candidates
|
||||
|
@ -308,10 +322,11 @@ def get_packages_for_paths(
|
|||
|
||||
def main(argv):
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('path', help='Path to search for.', type=str, nargs='*')
|
||||
parser.add_argument('--regex', '-x', help='Search for regex.', action='store_true')
|
||||
parser.add_argument('--debug', action='store_true')
|
||||
parser.add_argument("path", help="Path to search for.", type=str, nargs="*")
|
||||
parser.add_argument("--regex", "-x", help="Search for regex.", action="store_true")
|
||||
parser.add_argument("--debug", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.debug:
|
||||
|
@ -328,6 +343,7 @@ def main(argv):
|
|||
print(package)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
sys.exit(main(sys.argv))
|
||||
|
|
|
@ -19,13 +19,12 @@ __all__ = [
|
|||
"build_incrementally",
|
||||
]
|
||||
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from typing import List, Set, Optional, Type, Tuple
|
||||
from typing import List, Set, Optional, Type
|
||||
|
||||
from debian.deb822 import (
|
||||
Deb822,
|
||||
|
@ -33,7 +32,6 @@ from debian.deb822 import (
|
|||
)
|
||||
|
||||
from breezy.commit import PointlessCommit
|
||||
from breezy.mutabletree import MutableTree
|
||||
from breezy.tree import Tree
|
||||
from debmutate.changelog import ChangelogEditor
|
||||
from debmutate.control import (
|
||||
|
@ -54,18 +52,20 @@ from debmutate.reformatting import (
|
|||
try:
|
||||
from breezy.workspace import reset_tree
|
||||
except ImportError: # breezy < 3.2
|
||||
|
||||
def delete_items(deletables, dry_run=False):
|
||||
"""Delete files in the deletables iterable"""
|
||||
import errno
|
||||
import shutil
|
||||
|
||||
def onerror(function, path, excinfo):
|
||||
"""Show warning for errors seen by rmtree.
|
||||
"""
|
||||
"""Show warning for errors seen by rmtree."""
|
||||
# Handle only permission error while removing files.
|
||||
# Other errors are re-raised.
|
||||
if function is not os.remove or excinfo[1].errno != errno.EACCES:
|
||||
raise
|
||||
logging.warning('unable to remove %s' % path)
|
||||
logging.warning("unable to remove %s" % path)
|
||||
|
||||
for path, subp in deletables:
|
||||
if os.path.isdir(path):
|
||||
shutil.rmtree(path, onerror=onerror)
|
||||
|
@ -78,13 +78,18 @@ except ImportError: # breezy < 3.2
|
|||
raise e
|
||||
logging.warning('unable to remove "%s": %s.', path, e.strerror)
|
||||
|
||||
def reset_tree(local_tree, subpath=''):
|
||||
def reset_tree(local_tree, subpath=""):
|
||||
from breezy.transform import revert
|
||||
from breezy.clean_tree import iter_deletables
|
||||
revert(local_tree, local_tree.branch.basis_tree(),
|
||||
[subpath] if subpath not in ('.', '') else None)
|
||||
deletables = list(iter_deletables(
|
||||
local_tree, unknown=True, ignored=False, detritus=False))
|
||||
|
||||
revert(
|
||||
local_tree,
|
||||
local_tree.branch.basis_tree(),
|
||||
[subpath] if subpath not in (".", "") else None,
|
||||
)
|
||||
deletables = list(
|
||||
iter_deletables(local_tree, unknown=True, ignored=False, detritus=False)
|
||||
)
|
||||
delete_items(deletables)
|
||||
|
||||
|
||||
|
@ -103,8 +108,6 @@ from buildlog_consultant.common import (
|
|||
MissingAutomakeInput,
|
||||
MissingConfigure,
|
||||
NeedPgBuildExtUpdateControl,
|
||||
MissingPythonModule,
|
||||
MissingPythonDistribution,
|
||||
MissingPerlFile,
|
||||
)
|
||||
from buildlog_consultant.sbuild import (
|
||||
|
@ -130,8 +133,9 @@ class CircularDependency(Exception):
|
|||
|
||||
|
||||
class DebianPackagingContext(object):
|
||||
|
||||
def __init__(self, tree, subpath, committer, update_changelog, commit_reporter=None):
|
||||
def __init__(
|
||||
self, tree, subpath, committer, update_changelog, commit_reporter=None
|
||||
):
|
||||
self.tree = tree
|
||||
self.subpath = subpath
|
||||
self.committer = committer
|
||||
|
@ -144,14 +148,18 @@ class DebianPackagingContext(object):
|
|||
with self.tree.lock_write():
|
||||
try:
|
||||
if update_changelog:
|
||||
cl_path = self.tree.abspath(os.path.join(self.subpath, "debian/changelog"))
|
||||
cl_path = self.tree.abspath(
|
||||
os.path.join(self.subpath, "debian/changelog")
|
||||
)
|
||||
with ChangelogEditor(cl_path) as editor:
|
||||
editor.add_entry([summary])
|
||||
debcommit(self.tree, committer=self.committer, subpath=self.subpath)
|
||||
else:
|
||||
self.tree.commit(
|
||||
message=summary, committer=self.committer, specific_files=[self.subpath],
|
||||
reporter=self.commit_reporter
|
||||
message=summary,
|
||||
committer=self.committer,
|
||||
specific_files=[self.subpath],
|
||||
reporter=self.commit_reporter,
|
||||
)
|
||||
except PointlessCommit:
|
||||
return False
|
||||
|
@ -160,7 +168,6 @@ class DebianPackagingContext(object):
|
|||
|
||||
|
||||
class PackageDependencyFixer(BuildFixer):
|
||||
|
||||
def __init__(self, context, apt_resolver):
|
||||
self.apt_resolver = apt_resolver
|
||||
self.context = context
|
||||
|
@ -203,7 +210,7 @@ def add_dependency(context, phase, requirement: AptRequirement):
|
|||
elif phase[0] == "build":
|
||||
return add_build_dependency(context, requirement)
|
||||
else:
|
||||
logging.warning('Unknown phase %r', phase)
|
||||
logging.warning("Unknown phase %r", phase)
|
||||
return False
|
||||
|
||||
|
||||
|
@ -239,7 +246,9 @@ def add_test_dependency(context, testname, requirement):
|
|||
if not isinstance(requirement, AptRequirement):
|
||||
raise TypeError(requirement)
|
||||
|
||||
tests_control_path = os.path.join(context.tree.abspath(context.subpath), "debian/tests/control")
|
||||
tests_control_path = os.path.join(
|
||||
context.tree.abspath(context.subpath), "debian/tests/control"
|
||||
)
|
||||
|
||||
try:
|
||||
with Deb822Editor(path=tests_control_path) as updater:
|
||||
|
@ -293,18 +302,22 @@ def python_tie_breaker(tree, subpath, reqs):
|
|||
return None
|
||||
|
||||
def same(pkg, python_version):
|
||||
if pkg.startswith(python_version + '-'):
|
||||
if pkg.startswith(python_version + "-"):
|
||||
return True
|
||||
if pkg.startswith('lib%s-' % python_version):
|
||||
if pkg.startswith("lib%s-" % python_version):
|
||||
return True
|
||||
return False
|
||||
|
||||
for python_version in targeted:
|
||||
for req in reqs:
|
||||
if any(same(name, python_version) for name in req.package_names()):
|
||||
logging.info(
|
||||
'Breaking tie between %r to %r, since package already '
|
||||
'has %r build-dependencies', [str(req) for req in reqs],
|
||||
str(req), python_version)
|
||||
"Breaking tie between %r to %r, since package already "
|
||||
"has %r build-dependencies",
|
||||
[str(req) for req in reqs],
|
||||
str(req),
|
||||
python_version,
|
||||
)
|
||||
return req
|
||||
return None
|
||||
|
||||
|
@ -327,7 +340,9 @@ def enable_dh_autoreconf(context, phase):
|
|||
return dh_invoke_add_with(line, b"autoreconf")
|
||||
|
||||
if update_rules(command_line_cb=add_with_autoreconf):
|
||||
return add_dependency(context, phase, AptRequirement.simple("dh-autoreconf"))
|
||||
return add_dependency(
|
||||
context, phase, AptRequirement.simple("dh-autoreconf")
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
|
@ -385,10 +400,12 @@ class PgBuildExtOutOfDateControlFixer(BuildFixer):
|
|||
logging.info("Running 'pg_buildext updatecontrol'")
|
||||
self.session.check_call(["pg_buildext", "updatecontrol"])
|
||||
shutil.copy(
|
||||
self.session.external_path('debian/control'),
|
||||
context.tree.abspath(os.path.join(context.subpath, 'debian/control')))
|
||||
self.session.external_path("debian/control"),
|
||||
context.tree.abspath(os.path.join(context.subpath, "debian/control")),
|
||||
)
|
||||
return self.context.commit(
|
||||
"Run 'pgbuildext updatecontrol'.", update_changelog=False)
|
||||
"Run 'pgbuildext updatecontrol'.", update_changelog=False
|
||||
)
|
||||
|
||||
|
||||
def fix_missing_makefile_pl(error, phase, context):
|
||||
|
@ -410,7 +427,10 @@ class SimpleBuildFixer(BuildFixer):
|
|||
|
||||
def __repr__(self):
|
||||
return "%s(%s, %s)" % (
|
||||
type(self).__name__, self._problem_cls.__name__, self._fn.__name__)
|
||||
type(self).__name__,
|
||||
self._problem_cls.__name__,
|
||||
self._fn.__name__,
|
||||
)
|
||||
|
||||
def can_fix(self, problem: Problem):
|
||||
return isinstance(problem, self._problem_cls)
|
||||
|
@ -428,7 +448,10 @@ class DependencyBuildFixer(BuildFixer):
|
|||
|
||||
def __repr__(self):
|
||||
return "%s(%s, %s)" % (
|
||||
type(self).__name__, self._problem_cls.__name__, self._fn.__name__)
|
||||
type(self).__name__,
|
||||
self._problem_cls.__name__,
|
||||
self._fn.__name__,
|
||||
)
|
||||
|
||||
def can_fix(self, problem: Problem):
|
||||
return isinstance(problem, self._problem_cls)
|
||||
|
@ -441,8 +464,12 @@ def versioned_package_fixers(session, packaging_context):
|
|||
return [
|
||||
PgBuildExtOutOfDateControlFixer(packaging_context, session),
|
||||
SimpleBuildFixer(packaging_context, MissingConfigure, fix_missing_configure),
|
||||
SimpleBuildFixer(packaging_context, MissingAutomakeInput, fix_missing_automake_input),
|
||||
SimpleBuildFixer(packaging_context, MissingConfigStatusInput, fix_missing_config_status_input),
|
||||
SimpleBuildFixer(
|
||||
packaging_context, MissingAutomakeInput, fix_missing_automake_input
|
||||
),
|
||||
SimpleBuildFixer(
|
||||
packaging_context, MissingConfigStatusInput, fix_missing_config_status_input
|
||||
),
|
||||
SimpleBuildFixer(packaging_context, MissingPerlFile, fix_missing_makefile_pl),
|
||||
]
|
||||
|
||||
|
@ -451,6 +478,7 @@ def apt_fixers(apt, packaging_context) -> List[BuildFixer]:
|
|||
from ..resolver.apt import AptResolver
|
||||
from .udd import popcon_tie_breaker
|
||||
from .build_deps import BuildDependencyTieBreaker
|
||||
|
||||
apt_tie_breakers = [
|
||||
partial(python_tie_breaker, packaging_context.tree, packaging_context.subpath),
|
||||
BuildDependencyTieBreaker.from_session(apt.session),
|
||||
|
@ -458,7 +486,9 @@ def apt_fixers(apt, packaging_context) -> List[BuildFixer]:
|
|||
]
|
||||
resolver = AptResolver(apt, apt_tie_breakers)
|
||||
return [
|
||||
DependencyBuildFixer(packaging_context, apt, AptFetchFailure, retry_apt_failure),
|
||||
DependencyBuildFixer(
|
||||
packaging_context, apt, AptFetchFailure, retry_apt_failure
|
||||
),
|
||||
PackageDependencyFixer(packaging_context, resolver),
|
||||
]
|
||||
|
||||
|
@ -479,9 +509,11 @@ def build_incrementally(
|
|||
):
|
||||
fixed_errors = []
|
||||
packaging_context = DebianPackagingContext(
|
||||
local_tree, subpath, committer, update_changelog)
|
||||
fixers = (versioned_package_fixers(apt.session, packaging_context) +
|
||||
apt_fixers(apt, packaging_context))
|
||||
local_tree, subpath, committer, update_changelog
|
||||
)
|
||||
fixers = versioned_package_fixers(apt.session, packaging_context) + apt_fixers(
|
||||
apt, packaging_context
|
||||
)
|
||||
logging.info("Using fixers: %r", fixers)
|
||||
while True:
|
||||
try:
|
||||
|
@ -534,11 +566,8 @@ def build_incrementally(
|
|||
):
|
||||
i += 1
|
||||
target_path = os.path.join(output_directory, "build.log.%d" % i)
|
||||
os.rename(
|
||||
os.path.join(output_directory, "build.log"),
|
||||
target_path
|
||||
)
|
||||
logging.debug('Storing build log at %s', target_path)
|
||||
os.rename(os.path.join(output_directory, "build.log"), target_path)
|
||||
logging.debug("Storing build log at %s", target_path)
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
|
@ -577,19 +606,13 @@ def main(argv=None):
|
|||
help="force updating of the changelog",
|
||||
default=None,
|
||||
)
|
||||
parser.add_argument(
|
||||
'--schroot',
|
||||
type=str,
|
||||
help='chroot to use.')
|
||||
parser.add_argument(
|
||||
'--verbose',
|
||||
action='store_true',
|
||||
help='Be verbose')
|
||||
parser.add_argument("--schroot", type=str, help="chroot to use.")
|
||||
parser.add_argument("--verbose", action="store_true", help="Be verbose")
|
||||
|
||||
args = parser.parse_args()
|
||||
from breezy.workingtree import WorkingTree
|
||||
import breezy.git
|
||||
import breezy.bzr
|
||||
import breezy.git # noqa: F401
|
||||
import breezy.bzr # noqa: F401
|
||||
from .apt import AptManager
|
||||
from ..session.plain import PlainSession
|
||||
from ..session.schroot import SchrootSession
|
||||
|
@ -632,15 +655,15 @@ def main(argv=None):
|
|||
)
|
||||
except SbuildFailure as e:
|
||||
if e.phase is None:
|
||||
phase = 'unknown phase'
|
||||
phase = "unknown phase"
|
||||
elif len(e.phase) == 1:
|
||||
phase = e.phase[0]
|
||||
else:
|
||||
phase = '%s (%s)' % (e.phase[0], e.phase[1])
|
||||
phase = "%s (%s)" % (e.phase[0], e.phase[1])
|
||||
if e.error:
|
||||
logging.fatal('Error during %s: %s', phase, e.error)
|
||||
logging.fatal("Error during %s: %s", phase, e.error)
|
||||
else:
|
||||
logging.fatal('Error during %s: %s', phase, e.description)
|
||||
logging.fatal("Error during %s: %s", phase, e.description)
|
||||
return 1
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import logging
|
|||
|
||||
|
||||
class UDD(object):
|
||||
|
||||
def connect(self):
|
||||
import psycopg2
|
||||
|
||||
|
@ -36,8 +35,9 @@ class UDD(object):
|
|||
def get_most_popular(self, packages):
|
||||
cursor = self._conn.cursor()
|
||||
cursor.execute(
|
||||
'SELECT package FROM popcon WHERE package IN %s ORDER BY insts DESC LIMIT 1',
|
||||
(tuple(packages), ))
|
||||
"SELECT package FROM popcon WHERE package IN %s ORDER BY insts DESC LIMIT 1",
|
||||
(tuple(packages),),
|
||||
)
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
|
||||
|
@ -47,15 +47,14 @@ def popcon_tie_breaker(candidates):
|
|||
try:
|
||||
from .udd import UDD
|
||||
except ModuleNotFoundError:
|
||||
logging.warning('Unable to import UDD, not ranking by popcon')
|
||||
logging.warning("Unable to import UDD, not ranking by popcon")
|
||||
return sorted(candidates, key=len)[0]
|
||||
udd = UDD()
|
||||
udd.connect()
|
||||
names = {list(c.package_names())[0]: c for c in candidates}
|
||||
winner = udd.get_most_popular(list(names.keys()))
|
||||
if winner is None:
|
||||
logging.warning(
|
||||
'No relevant popcon information found, not ranking by popcon')
|
||||
logging.warning("No relevant popcon information found, not ranking by popcon")
|
||||
return None
|
||||
logging.info('Picked winner using popcon')
|
||||
logging.info("Picked winner using popcon")
|
||||
return names[winner]
|
||||
|
|
|
@ -16,16 +16,15 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
__all__ = [
|
||||
'UnidentifiedError',
|
||||
'DetailedFailure',
|
||||
'create_dist',
|
||||
'create_dist_schroot',
|
||||
"UnidentifiedError",
|
||||
"DetailedFailure",
|
||||
"create_dist",
|
||||
"create_dist_schroot",
|
||||
]
|
||||
|
||||
import errno
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from typing import Optional, List
|
||||
|
||||
|
@ -54,7 +53,8 @@ def run_dist(session, buildsystems, resolver, fixers, target_directory, quiet=Fa
|
|||
|
||||
for buildsystem in buildsystems:
|
||||
filename = buildsystem.dist(
|
||||
session, resolver, fixers, target_directory, quiet=quiet)
|
||||
session, resolver, fixers, target_directory, quiet=quiet
|
||||
)
|
||||
return filename
|
||||
|
||||
raise NoBuildToolsFound()
|
||||
|
@ -66,20 +66,23 @@ def create_dist(
|
|||
target_dir: str,
|
||||
include_controldir: bool = True,
|
||||
subdir: Optional[str] = None,
|
||||
cleanup: bool = False
|
||||
cleanup: bool = False,
|
||||
) -> Optional[str]:
|
||||
from .buildsystem import detect_buildsystems
|
||||
from .buildlog import InstallFixer
|
||||
from .fix_build import BuildFixer
|
||||
from .fixers import (
|
||||
GitIdentityFixer, SecretGpgKeyFixer,
|
||||
UnexpandedAutoconfMacroFixer, )
|
||||
GitIdentityFixer,
|
||||
SecretGpgKeyFixer,
|
||||
UnexpandedAutoconfMacroFixer,
|
||||
)
|
||||
|
||||
if subdir is None:
|
||||
subdir = "package"
|
||||
try:
|
||||
export_directory, reldir = session.setup_from_vcs(
|
||||
tree, include_controldir=include_controldir, subdir=subdir)
|
||||
tree, include_controldir=include_controldir, subdir=subdir
|
||||
)
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOSPC:
|
||||
raise DetailedFailure(1, ["mkdtemp"], NoSpaceOnDevice())
|
||||
|
@ -94,8 +97,7 @@ def create_dist(
|
|||
|
||||
if session.is_temporary:
|
||||
# Only muck about with temporary sessions
|
||||
fixers.extend([
|
||||
GitIdentityFixer(session), SecretGpgKeyFixer(session)])
|
||||
fixers.extend([GitIdentityFixer(session), SecretGpgKeyFixer(session)])
|
||||
|
||||
session.chdir(reldir)
|
||||
return run_dist(session, buildsystems, resolver, fixers, target_dir)
|
||||
|
@ -109,7 +111,7 @@ def create_dist_schroot(
|
|||
packaging_subpath: Optional[str] = None,
|
||||
include_controldir: bool = True,
|
||||
subdir: Optional[str] = None,
|
||||
cleanup: bool = False
|
||||
cleanup: bool = False,
|
||||
) -> Optional[str]:
|
||||
with SchrootSession(chroot) as session:
|
||||
if packaging_tree is not None:
|
||||
|
@ -117,10 +119,13 @@ def create_dist_schroot(
|
|||
|
||||
satisfy_build_deps(session, packaging_tree, packaging_subpath)
|
||||
return create_dist(
|
||||
session, tree, target_dir,
|
||||
session,
|
||||
tree,
|
||||
target_dir,
|
||||
include_controldir=include_controldir,
|
||||
subdir=subdir,
|
||||
cleanup=cleanup)
|
||||
cleanup=cleanup,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -151,8 +156,8 @@ if __name__ == "__main__":
|
|||
)
|
||||
parser.add_argument("--verbose", action="store_true", help="Be verbose")
|
||||
parser.add_argument(
|
||||
'--include-controldir', action='store_true',
|
||||
help='Clone rather than export.')
|
||||
"--include-controldir", action="store_true", help="Clone rather than export."
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
@ -185,15 +190,17 @@ if __name__ == "__main__":
|
|||
logging.info("No build tools found, falling back to simple export.")
|
||||
export(tree, "dist.tar.gz", "tgz", None)
|
||||
except NotImplementedError:
|
||||
logging.info("Build system does not support dist tarball creation, "
|
||||
"falling back to simple export.")
|
||||
logging.info(
|
||||
"Build system does not support dist tarball creation, "
|
||||
"falling back to simple export."
|
||||
)
|
||||
export(tree, "dist.tar.gz", "tgz", None)
|
||||
except UnidentifiedError as e:
|
||||
logging.fatal('Unidentified error: %r', e.lines)
|
||||
logging.fatal("Unidentified error: %r", e.lines)
|
||||
except DetailedFailure as e:
|
||||
logging.fatal('Identified error during dist creation: %s', e.error)
|
||||
logging.fatal("Identified error during dist creation: %s", e.error)
|
||||
except DistNoTarball:
|
||||
logging.fatal('dist operation did not create a tarball')
|
||||
logging.fatal("dist operation did not create a tarball")
|
||||
else:
|
||||
logging.info("Created %s", ret)
|
||||
sys.exit(0)
|
||||
|
|
|
@ -53,17 +53,17 @@ class DistCatcher(object):
|
|||
|
||||
@classmethod
|
||||
def default(cls, directory):
|
||||
return cls([
|
||||
os.path.join(directory, 'dist'),
|
||||
directory,
|
||||
os.path.join(directory, '..')])
|
||||
return cls(
|
||||
[os.path.join(directory, "dist"), directory, os.path.join(directory, "..")]
|
||||
)
|
||||
|
||||
def __enter__(self):
|
||||
self.existing_files = {}
|
||||
for directory in self.directories:
|
||||
try:
|
||||
self.existing_files[directory] = {
|
||||
entry.name: entry for entry in os.scandir(directory)}
|
||||
entry.name: entry for entry in os.scandir(directory)
|
||||
}
|
||||
except FileNotFoundError:
|
||||
self.existing_files[directory] = {}
|
||||
return self
|
||||
|
@ -92,7 +92,8 @@ class DistCatcher(object):
|
|||
return entry.name
|
||||
elif len(possible_new) > 1:
|
||||
logging.warning(
|
||||
"Found multiple tarballs %r in %s.", possible_new, directory)
|
||||
"Found multiple tarballs %r in %s.", possible_new, directory
|
||||
)
|
||||
return
|
||||
|
||||
if len(possible_updated) == 1:
|
||||
|
|
|
@ -17,17 +17,15 @@
|
|||
|
||||
from functools import partial
|
||||
import logging
|
||||
from typing import List, Optional, Tuple, Callable, Any
|
||||
from typing import List, Tuple, Callable, Any
|
||||
|
||||
from buildlog_consultant import Problem
|
||||
from buildlog_consultant.common import (
|
||||
find_build_failure_description,
|
||||
MissingCommand,
|
||||
)
|
||||
from breezy.mutabletree import MutableTree
|
||||
|
||||
from . import DetailedFailure, UnidentifiedError
|
||||
from .debian.apt import AptManager
|
||||
from .session import Session, run_with_tee
|
||||
|
||||
|
||||
|
@ -55,7 +53,7 @@ def run_detecting_problems(session: Session, args: List[str], **kwargs):
|
|||
else:
|
||||
if retcode == 0:
|
||||
return contents
|
||||
lines = ''.join(contents).splitlines(False)
|
||||
lines = "".join(contents).splitlines(False)
|
||||
match, error = find_build_failure_description(lines)
|
||||
if error is None:
|
||||
if match:
|
||||
|
@ -91,22 +89,26 @@ def iterate_with_build_fixers(fixers: List[BuildFixer], cb: Callable[[], Any]):
|
|||
try:
|
||||
resolved = resolve_error(f.error, None, fixers=fixers)
|
||||
except DetailedFailure as n:
|
||||
logging.info('New error %r while resolving %r', n, f)
|
||||
logging.info("New error %r while resolving %r", n, f)
|
||||
if n in to_resolve:
|
||||
raise
|
||||
to_resolve.append(f)
|
||||
to_resolve.append(n)
|
||||
else:
|
||||
if not resolved:
|
||||
logging.warning("Failed to find resolution for error %r. Giving up.", f.error)
|
||||
logging.warning(
|
||||
"Failed to find resolution for error %r. Giving up.", f.error
|
||||
)
|
||||
raise f
|
||||
fixed_errors.append(f.error)
|
||||
|
||||
|
||||
def run_with_build_fixers(session: Session, args: List[str], fixers: List[BuildFixer], **kwargs):
|
||||
def run_with_build_fixers(
|
||||
session: Session, args: List[str], fixers: List[BuildFixer], **kwargs
|
||||
):
|
||||
return iterate_with_build_fixers(
|
||||
fixers,
|
||||
partial(run_detecting_problems, session, args, **kwargs))
|
||||
fixers, partial(run_detecting_problems, session, args, **kwargs)
|
||||
)
|
||||
|
||||
|
||||
def resolve_error(error, phase, fixers):
|
||||
|
|
|
@ -31,7 +31,6 @@ from .fix_build import BuildFixer
|
|||
|
||||
|
||||
class GitIdentityFixer(BuildFixer):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
||||
|
||||
|
@ -39,16 +38,17 @@ class GitIdentityFixer(BuildFixer):
|
|||
return isinstance(problem, MissingGitIdentity)
|
||||
|
||||
def _fix(self, problem: Problem, phase: Tuple[str, ...]):
|
||||
for name in ['user.email', 'user.name']:
|
||||
value = subprocess.check_output(
|
||||
['git', 'config', '--global', name]).decode().strip()
|
||||
self.session.check_call(
|
||||
['git', 'config', '--global', name, value])
|
||||
for name in ["user.email", "user.name"]:
|
||||
value = (
|
||||
subprocess.check_output(["git", "config", "--global", name])
|
||||
.decode()
|
||||
.strip()
|
||||
)
|
||||
self.session.check_call(["git", "config", "--global", name, value])
|
||||
return True
|
||||
|
||||
|
||||
class SecretGpgKeyFixer(BuildFixer):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
||||
|
||||
|
@ -67,8 +67,10 @@ Expire-Date: 0
|
|||
Passphrase: ""
|
||||
"""
|
||||
p = self.session.Popen(
|
||||
['gpg', '--gen-key', '--batch', '/dev/stdin'],
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
["gpg", "--gen-key", "--batch", "/dev/stdin"],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
p.communicate(SCRIPT)
|
||||
if p.returncode == 0:
|
||||
return True
|
||||
|
@ -76,7 +78,6 @@ Passphrase: ""
|
|||
|
||||
|
||||
class UnexpandedAutoconfMacroFixer(BuildFixer):
|
||||
|
||||
def __init__(self, session, resolver):
|
||||
self.session = session
|
||||
self.resolver = resolver
|
||||
|
@ -97,6 +98,6 @@ class UnexpandedAutoconfMacroFixer(BuildFixer):
|
|||
return False
|
||||
from .fix_build import run_detecting_problems
|
||||
|
||||
run_detecting_problems(self.session, ['autoconf', '-f'])
|
||||
run_detecting_problems(self.session, ["autoconf", "-f"])
|
||||
|
||||
return True
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import posixpath
|
||||
import re
|
||||
import subprocess
|
||||
from typing import Optional, List, Tuple, Set
|
||||
from typing import Optional, List, Set
|
||||
|
||||
from . import Requirement
|
||||
|
||||
|
@ -72,19 +72,24 @@ class PythonPackageRequirement(Requirement):
|
|||
cmd = "python3"
|
||||
else:
|
||||
raise NotImplementedError
|
||||
text = self.package + ','.join([''.join(spec) for spec in self.specs])
|
||||
text = self.package + ",".join(["".join(spec) for spec in self.specs])
|
||||
p = session.Popen(
|
||||
[cmd, "-c", "import pkg_resources; pkg_resources.require(%r)" % text],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
p.communicate()
|
||||
return p.returncode == 0
|
||||
|
||||
|
||||
class PhpPackageRequirement(Requirement):
|
||||
|
||||
def __init__(self, package: str, channel: Optional[str] = None,
|
||||
def __init__(
|
||||
self,
|
||||
package: str,
|
||||
channel: Optional[str] = None,
|
||||
min_version: Optional[str] = None,
|
||||
max_version: Optional[str] = None):
|
||||
max_version: Optional[str] = None,
|
||||
):
|
||||
self.package = package
|
||||
self.channel = channel
|
||||
self.min_version = min_version
|
||||
|
@ -92,8 +97,12 @@ class PhpPackageRequirement(Requirement):
|
|||
|
||||
def __repr__(self):
|
||||
return "%s(%r, %r, %r, %r)" % (
|
||||
type(self).__name__, self.package, self.channel,
|
||||
self.min_version, self.max_version)
|
||||
type(self).__name__,
|
||||
self.package,
|
||||
self.channel,
|
||||
self.min_version,
|
||||
self.max_version,
|
||||
)
|
||||
|
||||
|
||||
class BinaryRequirement(Requirement):
|
||||
|
@ -109,8 +118,10 @@ class BinaryRequirement(Requirement):
|
|||
|
||||
def met(self, session):
|
||||
p = session.Popen(
|
||||
["which", self.binary_name], stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
["which", self.binary_name],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
p.communicate()
|
||||
return p.returncode == 0
|
||||
|
||||
|
@ -144,7 +155,7 @@ class VagueDependencyRequirement(Requirement):
|
|||
self.name = name
|
||||
|
||||
def expand(self):
|
||||
if ' ' not in self.name:
|
||||
if " " not in self.name:
|
||||
yield BinaryRequirement(self.name)
|
||||
yield LibraryRequirement(self.name)
|
||||
yield PkgConfigRequirement(self.name)
|
||||
|
@ -153,6 +164,7 @@ class VagueDependencyRequirement(Requirement):
|
|||
yield LibraryRequirement(self.name.lower())
|
||||
yield PkgConfigRequirement(self.name.lower())
|
||||
from .resolver.apt import AptRequirement
|
||||
|
||||
yield AptRequirement.simple(self.name.lower())
|
||||
|
||||
def met(self, session):
|
||||
|
@ -208,17 +220,18 @@ class CargoCrateRequirement(Requirement):
|
|||
type(self).__name__,
|
||||
self.crate,
|
||||
self.features,
|
||||
self.version
|
||||
self.version,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
if self.features:
|
||||
return "cargo crate: %s %s (%s)" % (
|
||||
self.crate, self.version or '',
|
||||
', '.join(sorted(self.features)))
|
||||
self.crate,
|
||||
self.version or "",
|
||||
", ".join(sorted(self.features)),
|
||||
)
|
||||
else:
|
||||
return "cargo crate: %s %s" % (
|
||||
self.crate, self.version or '')
|
||||
return "cargo crate: %s %s" % (self.crate, self.version or "")
|
||||
|
||||
|
||||
class PkgConfigRequirement(Requirement):
|
||||
|
@ -346,10 +359,10 @@ class RPackageRequirement(Requirement):
|
|||
@classmethod
|
||||
def from_str(cls, text):
|
||||
# TODO(jelmer): More complex parser
|
||||
m = re.fullmatch(r'(.*)\s+\(>=\s+(.*)\)', text)
|
||||
m = re.fullmatch(r"(.*)\s+\(>=\s+(.*)\)", text)
|
||||
if m:
|
||||
return cls(m.group(1), m.group(2))
|
||||
m = re.fullmatch(r'([^ ]+)', text)
|
||||
m = re.fullmatch(r"([^ ]+)", text)
|
||||
if m:
|
||||
return cls(m.group(1))
|
||||
raise ValueError(text)
|
||||
|
@ -381,10 +394,10 @@ class OctavePackageRequirement(Requirement):
|
|||
@classmethod
|
||||
def from_str(cls, text):
|
||||
# TODO(jelmer): More complex parser
|
||||
m = re.fullmatch(r'(.*)\s+\(>=\s+(.*)\)', text)
|
||||
m = re.fullmatch(r"(.*)\s+\(>=\s+(.*)\)", text)
|
||||
if m:
|
||||
return cls(m.group(1), m.group(2))
|
||||
m = re.fullmatch(r'([^ ]+)', text)
|
||||
m = re.fullmatch(r"([^ ]+)", text)
|
||||
if m:
|
||||
return cls(m.group(1))
|
||||
raise ValueError(text)
|
||||
|
@ -468,11 +481,14 @@ class MavenArtifactRequirement(Requirement):
|
|||
|
||||
def __str__(self):
|
||||
return "maven requirement: %s:%s:%s" % (
|
||||
self.group_id, self.artifact_id, self.version)
|
||||
self.group_id,
|
||||
self.artifact_id,
|
||||
self.version,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_str(cls, text):
|
||||
return cls.from_tuple(text.split(':'))
|
||||
return cls.from_tuple(text.split(":"))
|
||||
|
||||
@classmethod
|
||||
def from_tuple(cls, parts):
|
||||
|
@ -486,8 +502,7 @@ class MavenArtifactRequirement(Requirement):
|
|||
(group_id, artifact_id) = parts
|
||||
kind = "jar"
|
||||
else:
|
||||
raise ValueError(
|
||||
"invalid number of parts to artifact %r" % parts)
|
||||
raise ValueError("invalid number of parts to artifact %r" % parts)
|
||||
return cls(group_id, artifact_id, version, kind)
|
||||
|
||||
|
||||
|
@ -512,31 +527,26 @@ class JDKFileRequirement(Requirement):
|
|||
|
||||
|
||||
class JDKRequirement(Requirement):
|
||||
|
||||
def __init__(self):
|
||||
super(JDKRequirement, self).__init__("jdk")
|
||||
|
||||
|
||||
class JRERequirement(Requirement):
|
||||
|
||||
def __init__(self):
|
||||
super(JRERequirement, self).__init__("jre")
|
||||
|
||||
|
||||
class QTRequirement(Requirement):
|
||||
|
||||
def __init__(self):
|
||||
super(QTRequirement, self).__init__("qt")
|
||||
|
||||
|
||||
class X11Requirement(Requirement):
|
||||
|
||||
def __init__(self):
|
||||
super(X11Requirement, self).__init__("x11")
|
||||
|
||||
|
||||
class CertificateAuthorityRequirement(Requirement):
|
||||
|
||||
def __init__(self, url):
|
||||
super(CertificateAuthorityRequirement, self).__init__("ca-cert")
|
||||
self.url = url
|
||||
|
@ -561,7 +571,6 @@ class AutoconfMacroRequirement(Requirement):
|
|||
|
||||
|
||||
class LibtoolRequirement(Requirement):
|
||||
|
||||
def __init__(self):
|
||||
super(LibtoolRequirement, self).__init__("libtool")
|
||||
|
||||
|
@ -593,6 +602,8 @@ class PythonModuleRequirement(Requirement):
|
|||
raise NotImplementedError
|
||||
p = session.Popen(
|
||||
[cmd, "-c", "import %s" % self.module],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
p.communicate()
|
||||
return p.returncode == 0
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
import subprocess
|
||||
from ..fix_build import run_detecting_problems
|
||||
|
||||
|
||||
class UnsatisfiedRequirements(Exception):
|
||||
def __init__(self, reqs):
|
||||
self.requirements = reqs
|
||||
|
@ -53,7 +54,7 @@ class CPANResolver(Resolver):
|
|||
def _cmd(self, reqs):
|
||||
ret = ["cpan", "-i"]
|
||||
if self.skip_tests:
|
||||
ret.append('-T')
|
||||
ret.append("-T")
|
||||
ret.extend([req.module for req in reqs])
|
||||
return ret
|
||||
|
||||
|
@ -111,7 +112,11 @@ class RResolver(Resolver):
|
|||
|
||||
def _cmd(self, req):
|
||||
# TODO(jelmer: Handle self.user_local
|
||||
return ["R", "-e", "install.packages('%s', repos=%r)" % (req.package, self.repos)]
|
||||
return [
|
||||
"R",
|
||||
"-e",
|
||||
"install.packages('%s', repos=%r)" % (req.package, self.repos),
|
||||
]
|
||||
|
||||
def explain(self, requirements):
|
||||
from ..requirements import RPackageRequirement
|
||||
|
@ -187,16 +192,17 @@ class OctaveForgeResolver(Resolver):
|
|||
|
||||
|
||||
class CRANResolver(RResolver):
|
||||
|
||||
def __init__(self, session, user_local=False):
|
||||
super(CRANResolver, self).__init__(session, 'http://cran.r-project.org', user_local=user_local)
|
||||
super(CRANResolver, self).__init__(
|
||||
session, "http://cran.r-project.org", user_local=user_local
|
||||
)
|
||||
|
||||
|
||||
class BioconductorResolver(RResolver):
|
||||
|
||||
def __init__(self, session, user_local=False):
|
||||
super(BioconductorResolver, self).__init__(
|
||||
session, 'https://hedgehog.fhcrc.org/bioconductor', user_local=user_local)
|
||||
session, "https://hedgehog.fhcrc.org/bioconductor", user_local=user_local
|
||||
)
|
||||
|
||||
|
||||
class HackageResolver(Resolver):
|
||||
|
@ -213,7 +219,7 @@ class HackageResolver(Resolver):
|
|||
def _cmd(self, reqs):
|
||||
extra_args = []
|
||||
if self.user_local:
|
||||
extra_args.append('--user')
|
||||
extra_args.append("--user")
|
||||
return ["cabal", "install"] + extra_args + [req.package for req in reqs]
|
||||
|
||||
def install(self, requirements):
|
||||
|
@ -259,7 +265,7 @@ class PypiResolver(Resolver):
|
|||
def _cmd(self, reqs):
|
||||
extra_args = []
|
||||
if self.user_local:
|
||||
extra_args.append('--user')
|
||||
extra_args.append("--user")
|
||||
return ["pip", "install"] + extra_args + [req.package for req in reqs]
|
||||
|
||||
def install(self, requirements):
|
||||
|
@ -276,8 +282,7 @@ class PypiResolver(Resolver):
|
|||
missing.append(requirement)
|
||||
continue
|
||||
try:
|
||||
self.session.check_call(
|
||||
self._cmd([requirement]), user=user)
|
||||
self.session.check_call(self._cmd([requirement]), user=user)
|
||||
except subprocess.CalledProcessError:
|
||||
missing.append(requirement)
|
||||
if missing:
|
||||
|
@ -296,7 +301,6 @@ class PypiResolver(Resolver):
|
|||
|
||||
|
||||
class GoResolver(Resolver):
|
||||
|
||||
def __init__(self, session, user_local):
|
||||
self.session = session
|
||||
self.user_local = user_local
|
||||
|
@ -314,7 +318,7 @@ class GoResolver(Resolver):
|
|||
env = {}
|
||||
else:
|
||||
# TODO(jelmer): Isn't this Debian-specific?
|
||||
env = {'GOPATH': '/usr/share/gocode'}
|
||||
env = {"GOPATH": "/usr/share/gocode"}
|
||||
|
||||
missing = []
|
||||
for requirement in requirements:
|
||||
|
@ -334,8 +338,7 @@ class GoResolver(Resolver):
|
|||
continue
|
||||
goreqs.append(requirement)
|
||||
if goreqs:
|
||||
yield (["go", "get"] + [req.package for req in goreqs],
|
||||
goreqs)
|
||||
yield (["go", "get"] + [req.package for req in goreqs], goreqs)
|
||||
|
||||
|
||||
NPM_COMMAND_PACKAGES = {
|
||||
|
@ -379,13 +382,13 @@ class NpmResolver(Resolver):
|
|||
requirement = NodePackageRequirement(package)
|
||||
if isinstance(requirement, NodeModuleRequirement):
|
||||
# TODO: Is this legit?
|
||||
requirement = NodePackageRequirement(requirement.module.split('/')[0])
|
||||
requirement = NodePackageRequirement(requirement.module.split("/")[0])
|
||||
if not isinstance(requirement, NodePackageRequirement):
|
||||
missing.append(requirement)
|
||||
continue
|
||||
self.session.check_call(
|
||||
["npm", "-g", "install", requirement.package],
|
||||
user=user)
|
||||
["npm", "-g", "install", requirement.package], user=user
|
||||
)
|
||||
if missing:
|
||||
raise UnsatisfiedRequirements(missing)
|
||||
|
||||
|
|
|
@ -115,19 +115,27 @@ class AptRequirement(Requirement):
|
|||
return False
|
||||
|
||||
|
||||
def find_package_names(apt_mgr: AptManager, paths: List[str], regex: bool = False, case_insensitive=False) -> List[str]:
|
||||
def find_package_names(
|
||||
apt_mgr: AptManager, paths: List[str], regex: bool = False, case_insensitive=False
|
||||
) -> List[str]:
|
||||
if not isinstance(paths, list):
|
||||
raise TypeError(paths)
|
||||
return apt_mgr.get_packages_for_paths(paths, regex, case_insensitive)
|
||||
|
||||
|
||||
def find_reqs_simple(
|
||||
apt_mgr: AptManager, paths: List[str], regex: bool = False,
|
||||
minimum_version=None, case_insensitive=False) -> List[str]:
|
||||
apt_mgr: AptManager,
|
||||
paths: List[str],
|
||||
regex: bool = False,
|
||||
minimum_version=None,
|
||||
case_insensitive=False,
|
||||
) -> List[str]:
|
||||
if not isinstance(paths, list):
|
||||
raise TypeError(paths)
|
||||
return [AptRequirement.simple(package, minimum_version=minimum_version)
|
||||
for package in find_package_names(apt_mgr, paths, regex, case_insensitive)]
|
||||
return [
|
||||
AptRequirement.simple(package, minimum_version=minimum_version)
|
||||
for package in find_package_names(apt_mgr, paths, regex, case_insensitive)
|
||||
]
|
||||
|
||||
|
||||
def python_spec_to_apt_rels(pkg_name, specs):
|
||||
|
@ -138,36 +146,57 @@ def python_spec_to_apt_rels(pkg_name, specs):
|
|||
rels = []
|
||||
for spec in specs:
|
||||
deb_version = Version(spec[1])
|
||||
if spec[0] == '~=':
|
||||
if spec[0] == "~=":
|
||||
# PEP 440: For a given release identifier V.N , the compatible
|
||||
# release clause is approximately equivalent to the pair of
|
||||
# comparison clauses: >= V.N, == V.*
|
||||
parts = spec[1].split('.')
|
||||
parts = spec[1].split(".")
|
||||
parts.pop(-1)
|
||||
parts[-1] = str(int(parts[-1]) + 1)
|
||||
next_maj_deb_version = Version('.'.join(parts))
|
||||
rels.extend([{"name": pkg_name, "version": ('>=', deb_version)},
|
||||
{"name": pkg_name, "version": ('<<', next_maj_deb_version)}])
|
||||
elif spec[0] == '!=':
|
||||
rels.extend([{"name": pkg_name, "version": ('>>', deb_version)},
|
||||
{"name": pkg_name, "version": ('<<', deb_version)}])
|
||||
elif spec[1].endswith('.*') and spec[0] == '==':
|
||||
s = spec[1].split('.')
|
||||
next_maj_deb_version = Version(".".join(parts))
|
||||
rels.extend(
|
||||
[
|
||||
{"name": pkg_name, "version": (">=", deb_version)},
|
||||
{"name": pkg_name, "version": ("<<", next_maj_deb_version)},
|
||||
]
|
||||
)
|
||||
elif spec[0] == "!=":
|
||||
rels.extend(
|
||||
[
|
||||
{"name": pkg_name, "version": (">>", deb_version)},
|
||||
{"name": pkg_name, "version": ("<<", deb_version)},
|
||||
]
|
||||
)
|
||||
elif spec[1].endswith(".*") and spec[0] == "==":
|
||||
s = spec[1].split(".")
|
||||
s.pop(-1)
|
||||
n = list(s)
|
||||
n[-1] = str(int(n[-1]) + 1)
|
||||
rels.extend([{"name": pkg_name, "version": ('>=', Version('.'.join(s)))},
|
||||
{"name": pkg_name, "version": ('<<', Version('.'.join(n)))}])
|
||||
rels.extend(
|
||||
[
|
||||
{"name": pkg_name, "version": (">=", Version(".".join(s)))},
|
||||
{"name": pkg_name, "version": ("<<", Version(".".join(n)))},
|
||||
]
|
||||
)
|
||||
else:
|
||||
c = {">=": ">=", "<=": "<=", "<": "<<", ">": ">>", "==": "="}[spec[0]]
|
||||
rels.append([{"name": pkg_name, "version": (c, deb_version)}])
|
||||
return rels
|
||||
|
||||
|
||||
def get_package_for_python_package(apt_mgr, package, python_version: Optional[str], specs=None):
|
||||
pypy_regex = "/usr/lib/pypy/dist-packages/%s-.*.egg-info" % re.escape(package.replace("-", "_"))
|
||||
cpython2_regex = "/usr/lib/python2\\.[0-9]/dist-packages/%s-.*.egg-info" % re.escape(package.replace("-", "_"))
|
||||
cpython3_regex = "/usr/lib/python3/dist-packages/%s-.*.egg-info" % re.escape(package.replace("-", "_"))
|
||||
def get_package_for_python_package(
|
||||
apt_mgr, package, python_version: Optional[str], specs=None
|
||||
):
|
||||
pypy_regex = "/usr/lib/pypy/dist-packages/%s-.*.egg-info" % re.escape(
|
||||
package.replace("-", "_")
|
||||
)
|
||||
cpython2_regex = (
|
||||
"/usr/lib/python2\\.[0-9]/dist-packages/%s-.*.egg-info"
|
||||
% re.escape(package.replace("-", "_"))
|
||||
)
|
||||
cpython3_regex = "/usr/lib/python3/dist-packages/%s-.*.egg-info" % re.escape(
|
||||
package.replace("-", "_")
|
||||
)
|
||||
if python_version == "pypy":
|
||||
paths = [pypy_regex]
|
||||
elif python_version == "cpython2":
|
||||
|
@ -177,7 +206,7 @@ def get_package_for_python_package(apt_mgr, package, python_version: Optional[st
|
|||
elif python_version is None:
|
||||
paths = [cpython3_regex, cpython2_regex, pypy_regex]
|
||||
else:
|
||||
raise NotImplementedError('unsupported python version %s' % python_version)
|
||||
raise NotImplementedError("unsupported python version %s" % python_version)
|
||||
names = find_package_names(apt_mgr, paths, regex=True, case_insensitive=True)
|
||||
return [AptRequirement(python_spec_to_apt_rels(name, specs)) for name in names]
|
||||
|
||||
|
@ -190,7 +219,8 @@ def get_package_for_python_module(apt_mgr, module, python_version, specs):
|
|||
"__init__.py",
|
||||
),
|
||||
posixpath.join(
|
||||
"/usr/lib/python3/dist-packages", re.escape(module.replace(".", "/")) + ".py"
|
||||
"/usr/lib/python3/dist-packages",
|
||||
re.escape(module.replace(".", "/")) + ".py",
|
||||
),
|
||||
posixpath.join(
|
||||
"/usr/lib/python3\\.[0-9]+/lib-dynload",
|
||||
|
@ -200,7 +230,9 @@ def get_package_for_python_module(apt_mgr, module, python_version, specs):
|
|||
"/usr/lib/python3\\.[0-9]+/", re.escape(module.replace(".", "/")) + ".py"
|
||||
),
|
||||
posixpath.join(
|
||||
"/usr/lib/python3\\.[0-9]+/", re.escape(module.replace(".", "/")), "__init__.py"
|
||||
"/usr/lib/python3\\.[0-9]+/",
|
||||
re.escape(module.replace(".", "/")),
|
||||
"__init__.py",
|
||||
),
|
||||
]
|
||||
cpython2_regexes = [
|
||||
|
@ -220,7 +252,9 @@ def get_package_for_python_module(apt_mgr, module, python_version, specs):
|
|||
]
|
||||
pypy_regexes = [
|
||||
posixpath.join(
|
||||
"/usr/lib/pypy/dist-packages", re.escape(module.replace(".", "/")), "__init__.py"
|
||||
"/usr/lib/pypy/dist-packages",
|
||||
re.escape(module.replace(".", "/")),
|
||||
"__init__.py",
|
||||
),
|
||||
posixpath.join(
|
||||
"/usr/lib/pypy/dist-packages", re.escape(module.replace(".", "/")) + ".py"
|
||||
|
@ -245,8 +279,8 @@ def get_package_for_python_module(apt_mgr, module, python_version, specs):
|
|||
|
||||
|
||||
vague_map = {
|
||||
'the Gnu Scientific Library': 'libgsl-dev',
|
||||
'the required FreeType library': 'libfreetype-dev',
|
||||
"the Gnu Scientific Library": "libgsl-dev",
|
||||
"the required FreeType library": "libfreetype-dev",
|
||||
}
|
||||
|
||||
|
||||
|
@ -255,7 +289,7 @@ def resolve_vague_dep_req(apt_mgr, req):
|
|||
options = []
|
||||
if name in vague_map:
|
||||
options.append(AptRequirement.simple(vague_map[name]))
|
||||
if name.startswith('gnu '):
|
||||
if name.startswith("gnu "):
|
||||
name = name[4:]
|
||||
for x in req.expand():
|
||||
options.extend(resolve_requirement_apt(apt_mgr, x))
|
||||
|
@ -273,13 +307,23 @@ def resolve_binary_req(apt_mgr, req):
|
|||
|
||||
|
||||
def resolve_pkg_config_req(apt_mgr, req):
|
||||
names = find_package_names(apt_mgr,
|
||||
[posixpath.join("/usr/lib", ".*", "pkgconfig", re.escape(req.module) + "\\.pc")],
|
||||
regex=True)
|
||||
names = find_package_names(
|
||||
apt_mgr,
|
||||
[
|
||||
posixpath.join(
|
||||
"/usr/lib", ".*", "pkgconfig", re.escape(req.module) + "\\.pc"
|
||||
)
|
||||
],
|
||||
regex=True,
|
||||
)
|
||||
if not names:
|
||||
names = find_package_names(
|
||||
apt_mgr, [posixpath.join("/usr/lib/pkgconfig", req.module + ".pc")])
|
||||
return [AptRequirement.simple(name, minimum_version=req.minimum_version) for name in names]
|
||||
apt_mgr, [posixpath.join("/usr/lib/pkgconfig", req.module + ".pc")]
|
||||
)
|
||||
return [
|
||||
AptRequirement.simple(name, minimum_version=req.minimum_version)
|
||||
for name in names
|
||||
]
|
||||
|
||||
|
||||
def resolve_path_req(apt_mgr, req):
|
||||
|
@ -288,12 +332,13 @@ def resolve_path_req(apt_mgr, req):
|
|||
|
||||
def resolve_c_header_req(apt_mgr, req):
|
||||
reqs = find_reqs_simple(
|
||||
apt_mgr,
|
||||
[posixpath.join("/usr/include", req.header)], regex=False)
|
||||
apt_mgr, [posixpath.join("/usr/include", req.header)], regex=False
|
||||
)
|
||||
if not reqs:
|
||||
reqs = find_reqs_simple(
|
||||
apt_mgr,
|
||||
[posixpath.join("/usr/include", ".*", re.escape(req.header))], regex=True
|
||||
[posixpath.join("/usr/include", ".*", re.escape(req.header))],
|
||||
regex=True,
|
||||
)
|
||||
return reqs
|
||||
|
||||
|
@ -314,18 +359,21 @@ def resolve_ruby_gem_req(apt_mgr, req):
|
|||
"specifications/%s-.*\\.gemspec" % re.escape(req.gem)
|
||||
)
|
||||
]
|
||||
return find_reqs_simple(apt_mgr, paths, regex=True, minimum_version=req.minimum_version)
|
||||
return find_reqs_simple(
|
||||
apt_mgr, paths, regex=True, minimum_version=req.minimum_version
|
||||
)
|
||||
|
||||
|
||||
def resolve_go_package_req(apt_mgr, req):
|
||||
return find_reqs_simple(
|
||||
apt_mgr,
|
||||
[posixpath.join("/usr/share/gocode/src", re.escape(req.package), ".*")], regex=True
|
||||
[posixpath.join("/usr/share/gocode/src", re.escape(req.package), ".*")],
|
||||
regex=True,
|
||||
)
|
||||
|
||||
|
||||
def resolve_go_req(apt_mgr, req):
|
||||
return [AptRequirement.simple('golang-go', minimum_version='2:%s' % req.version)]
|
||||
return [AptRequirement.simple("golang-go", minimum_version="2:%s" % req.version)]
|
||||
|
||||
|
||||
def resolve_dh_addon_req(apt_mgr, req):
|
||||
|
@ -339,11 +387,15 @@ def resolve_php_class_req(apt_mgr, req):
|
|||
|
||||
|
||||
def resolve_php_package_req(apt_mgr, req):
|
||||
return [AptRequirement.simple('php-%s' % req.package, minimum_version=req.min_version)]
|
||||
return [
|
||||
AptRequirement.simple("php-%s" % req.package, minimum_version=req.min_version)
|
||||
]
|
||||
|
||||
|
||||
def resolve_r_package_req(apt_mgr, req):
|
||||
paths = [posixpath.join("/usr/lib/R/site-library/.*/R/%s$" % re.escape(req.package))]
|
||||
paths = [
|
||||
posixpath.join("/usr/lib/R/site-library/.*/R/%s$" % re.escape(req.package))
|
||||
]
|
||||
return find_reqs_simple(apt_mgr, paths, regex=True)
|
||||
|
||||
|
||||
|
@ -441,15 +493,17 @@ def resolve_maven_artifact_req(apt_mgr, req):
|
|||
else:
|
||||
version = req.version
|
||||
regex = False
|
||||
|
||||
def escape(x):
|
||||
return x
|
||||
kind = req.kind or 'jar'
|
||||
|
||||
kind = req.kind or "jar"
|
||||
path = posixpath.join(
|
||||
escape("/usr/share/maven-repo"),
|
||||
escape(req.group_id.replace(".", "/")),
|
||||
escape(req.artifact_id),
|
||||
version,
|
||||
escape("%s-") + version + escape("." + kind)
|
||||
escape("%s-") + version + escape("." + kind),
|
||||
)
|
||||
|
||||
return find_reqs_simple(apt_mgr, [path], regex=regex)
|
||||
|
@ -465,15 +519,15 @@ def resolve_jdk_file_req(apt_mgr, req):
|
|||
|
||||
|
||||
def resolve_jdk_req(apt_mgr, req):
|
||||
return [AptRequirement.simple('default-jdk')]
|
||||
return [AptRequirement.simple("default-jdk")]
|
||||
|
||||
|
||||
def resolve_jre_req(apt_mgr, req):
|
||||
return [AptRequirement.simple('default-jre')]
|
||||
return [AptRequirement.simple("default-jre")]
|
||||
|
||||
|
||||
def resolve_x11_req(apt_mgr, req):
|
||||
return [AptRequirement.simple('libx11-dev')]
|
||||
return [AptRequirement.simple("libx11-dev")]
|
||||
|
||||
|
||||
def resolve_qt_req(apt_mgr, req):
|
||||
|
@ -554,13 +608,12 @@ def resolve_python_package_req(apt_mgr, req):
|
|||
|
||||
|
||||
def resolve_cargo_crate_req(apt_mgr, req):
|
||||
paths = [
|
||||
'/usr/share/cargo/registry/%s-[0-9]+.*/Cargo.toml' % re.escape(req.crate)]
|
||||
paths = ["/usr/share/cargo/registry/%s-[0-9]+.*/Cargo.toml" % re.escape(req.crate)]
|
||||
return find_reqs_simple(apt_mgr, paths, regex=True)
|
||||
|
||||
|
||||
def resolve_ca_req(apt_mgr, req):
|
||||
return [AptRequirement.simple('ca-certificates')]
|
||||
return [AptRequirement.simple("ca-certificates")]
|
||||
|
||||
|
||||
def resolve_apt_req(apt_mgr, req):
|
||||
|
@ -670,7 +723,16 @@ class AptResolver(Resolver):
|
|||
if apt_req is not None:
|
||||
apt_requirements.append((r, apt_req))
|
||||
if apt_requirements:
|
||||
yield (self.apt.satisfy_command([PkgRelation.str(chain(*[r.relations for o, r in apt_requirements]))]), [o for o, r in apt_requirements])
|
||||
yield (
|
||||
self.apt.satisfy_command(
|
||||
[
|
||||
PkgRelation.str(
|
||||
chain(*[r.relations for o, r in apt_requirements])
|
||||
)
|
||||
]
|
||||
),
|
||||
[o for o, r in apt_requirements],
|
||||
)
|
||||
|
||||
def resolve(self, req: Requirement):
|
||||
ret = resolve_requirement_apt(self.apt, req)
|
||||
|
@ -678,14 +740,12 @@ class AptResolver(Resolver):
|
|||
return None
|
||||
if len(ret) == 1:
|
||||
return ret[0]
|
||||
logging.info('Need to break tie between %r with %r', ret, self.tie_breakers)
|
||||
logging.info("Need to break tie between %r with %r", ret, self.tie_breakers)
|
||||
for tie_breaker in self.tie_breakers:
|
||||
winner = tie_breaker(ret)
|
||||
if winner is not None:
|
||||
if not isinstance(winner, AptRequirement):
|
||||
raise TypeError(winner)
|
||||
return winner
|
||||
logging.info(
|
||||
'Unable to break tie over %r, picking first: %r',
|
||||
ret, ret[0])
|
||||
logging.info("Unable to break tie over %r, picking first: %r", ret, ret[0])
|
||||
return ret[0]
|
||||
|
|
|
@ -55,7 +55,7 @@ class Session(object):
|
|||
cwd: Optional[str] = None,
|
||||
user: Optional[str] = None,
|
||||
env: Optional[Dict[str, str]] = None,
|
||||
close_fds: bool = True
|
||||
close_fds: bool = True,
|
||||
):
|
||||
raise NotImplementedError(self.check_call)
|
||||
|
||||
|
@ -90,8 +90,8 @@ class Session(object):
|
|||
raise NotImplementedError(self.scandir)
|
||||
|
||||
def setup_from_vcs(
|
||||
self, tree, include_controldir: Optional[bool] = None,
|
||||
subdir="package") -> Tuple[str, str]:
|
||||
self, tree, include_controldir: Optional[bool] = None, subdir="package"
|
||||
) -> Tuple[str, str]:
|
||||
raise NotImplementedError(self.setup_from_vcs)
|
||||
|
||||
def setup_from_directory(self, path, subdir="package") -> Tuple[str, str]:
|
||||
|
@ -108,8 +108,8 @@ class SessionSetupFailure(Exception):
|
|||
|
||||
|
||||
def run_with_tee(session: Session, args: List[str], **kwargs):
|
||||
if 'stdin' not in kwargs:
|
||||
kwargs['stdin'] = subprocess.DEVNULL
|
||||
if "stdin" not in kwargs:
|
||||
kwargs["stdin"] = subprocess.DEVNULL
|
||||
p = session.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs)
|
||||
contents = []
|
||||
while p.poll() is None:
|
||||
|
|
|
@ -38,6 +38,7 @@ class PlainSession(Session):
|
|||
raise NoSessionOpen(self)
|
||||
if user is not None:
|
||||
import getpass
|
||||
|
||||
if user != getpass.getuser():
|
||||
args = ["sudo", "-u", user] + args
|
||||
return args
|
||||
|
@ -63,19 +64,23 @@ class PlainSession(Session):
|
|||
pass
|
||||
|
||||
def check_call(
|
||||
self, argv: List[str],
|
||||
self,
|
||||
argv: List[str],
|
||||
cwd: Optional[str] = None,
|
||||
user: Optional[str] = None,
|
||||
env: Optional[Dict[str, str]] = None,
|
||||
close_fds: bool = True):
|
||||
close_fds: bool = True,
|
||||
):
|
||||
argv = self._prepend_user(user, argv)
|
||||
return subprocess.check_call(argv, cwd=cwd, env=env, close_fds=close_fds)
|
||||
|
||||
def check_output(
|
||||
self, argv: List[str],
|
||||
self,
|
||||
argv: List[str],
|
||||
cwd: Optional[str] = None,
|
||||
user: Optional[str] = None,
|
||||
env: Optional[Dict[str, str]] = None) -> bytes:
|
||||
env: Optional[Dict[str, str]] = None,
|
||||
) -> bytes:
|
||||
argv = self._prepend_user(user, argv)
|
||||
return subprocess.check_output(argv, cwd=cwd, env=env)
|
||||
|
||||
|
@ -95,15 +100,16 @@ class PlainSession(Session):
|
|||
def external_path(self, path):
|
||||
return os.path.abspath(path)
|
||||
|
||||
def setup_from_vcs(
|
||||
self, tree, include_controldir=None, subdir="package"):
|
||||
def setup_from_vcs(self, tree, include_controldir=None, subdir="package"):
|
||||
from ..vcs import dupe_vcs_tree, export_vcs_tree
|
||||
|
||||
if include_controldir is False or (
|
||||
not hasattr(tree, 'base') and include_controldir is None):
|
||||
not hasattr(tree, "base") and include_controldir is None
|
||||
):
|
||||
td = self.es.enter_context(tempfile.TemporaryDirectory())
|
||||
export_vcs_tree(tree, td)
|
||||
return td, td
|
||||
elif not hasattr(tree, 'base'):
|
||||
elif not hasattr(tree, "base"):
|
||||
td = self.es.enter_context(tempfile.TemporaryDirectory())
|
||||
dupe_vcs_tree(tree, td)
|
||||
return td, td
|
||||
|
|
|
@ -57,12 +57,17 @@ class SchrootSession(Session):
|
|||
if self.session_id is None:
|
||||
raise NoSessionOpen(self)
|
||||
try:
|
||||
subprocess.check_output(["schroot", "-c", "session:" + self.session_id, "-e"], stderr=subprocess.PIPE)
|
||||
subprocess.check_output(
|
||||
["schroot", "-c", "session:" + self.session_id, "-e"],
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
for line in e.stderr.splitlines(False):
|
||||
if line.startswith(b'E: '):
|
||||
logging.error('%s', line[3:].decode(errors='replace'))
|
||||
logging.warning('Failed to close schroot session %s, leaving stray.', self.session_id)
|
||||
if line.startswith(b"E: "):
|
||||
logging.error("%s", line[3:].decode(errors="replace"))
|
||||
logging.warning(
|
||||
"Failed to close schroot session %s, leaving stray.", self.session_id
|
||||
)
|
||||
self.session_id = None
|
||||
return False
|
||||
self.session_id = None
|
||||
|
@ -134,10 +139,12 @@ class SchrootSession(Session):
|
|||
cwd: Optional[str] = None,
|
||||
user: Optional[str] = None,
|
||||
env: Optional[Dict[str, str]] = None,
|
||||
close_fds: bool = True
|
||||
close_fds: bool = True,
|
||||
):
|
||||
try:
|
||||
subprocess.check_call(self._run_argv(argv, cwd, user, env=env), close_fds=close_fds)
|
||||
subprocess.check_call(
|
||||
self._run_argv(argv, cwd, user, env=env), close_fds=close_fds
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise subprocess.CalledProcessError(e.returncode, argv)
|
||||
|
||||
|
@ -191,9 +198,10 @@ class SchrootSession(Session):
|
|||
return os.scandir(fullpath)
|
||||
|
||||
def setup_from_vcs(
|
||||
self, tree, include_controldir: Optional[bool] = None,
|
||||
subdir="package"):
|
||||
self, tree, include_controldir: Optional[bool] = None, subdir="package"
|
||||
):
|
||||
from ..vcs import dupe_vcs_tree, export_vcs_tree
|
||||
|
||||
build_dir = os.path.join(self.location, "build")
|
||||
|
||||
directory = tempfile.mkdtemp(dir=build_dir)
|
||||
|
@ -209,6 +217,7 @@ class SchrootSession(Session):
|
|||
|
||||
def setup_from_directory(self, path, subdir="package"):
|
||||
import shutil
|
||||
|
||||
build_dir = os.path.join(self.location, "build")
|
||||
directory = tempfile.mkdtemp(dir=build_dir)
|
||||
reldir = "/" + os.path.relpath(directory, self.location)
|
||||
|
|
|
@ -99,9 +99,12 @@ blah (0.1) UNRELEASED; urgency=medium
|
|||
apt = AptManager(session)
|
||||
apt._searchers = [DummyAptSearcher(self._apt_files)]
|
||||
context = DebianPackagingContext(
|
||||
self.tree, subpath="", committer="ognibuild <ognibuild@jelmer.uk>",
|
||||
self.tree,
|
||||
subpath="",
|
||||
committer="ognibuild <ognibuild@jelmer.uk>",
|
||||
update_changelog=True,
|
||||
commit_reporter=NullCommitReporter())
|
||||
commit_reporter=NullCommitReporter(),
|
||||
)
|
||||
fixers = versioned_package_fixers(session, context) + apt_fixers(apt, context)
|
||||
return resolve_error(error, ("build",), fixers)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue