More work on factoring out resolver.

This commit is contained in:
Jelmer Vernooij 2021-02-09 02:11:02 +00:00
parent 713a624b00
commit fa222a6ae4
No known key found for this signature in database
GPG key ID: 579C160D4C9E23E8
8 changed files with 399 additions and 226 deletions

View file

@ -42,3 +42,17 @@ def shebang_binary(p):
if args[0] in (b"/usr/bin/env", b"env"): if args[0] in (b"/usr/bin/env", b"env"):
return os.path.basename(args[1].decode()).strip() return os.path.basename(args[1].decode()).strip()
return os.path.basename(args[0].decode()).strip() return os.path.basename(args[0].decode()).strip()
class UpstreamRequirement(object):
def __init__(self, family, name):
self.family = family
self.name = name
class UpstreamOutput(object):
def __init__(self, family, name):
self.family = family
self.name = name

View file

@ -34,14 +34,31 @@ from .resolver import (
from .test import run_test from .test import run_test
def install_declared_requirements(resolver, requirements, subcommand): def get_necessary_declared_requirements(resolver, requirements, stages):
missing = [] missing = []
for req in requirements: for stage, req in requirements:
# TODO(jelmer): Look at stage if stage in stages:
missing.append(UpstreamPackage(req.package.family, req.package.name)) missing.append(req)
return missing
def install_necessary_declared_requirements(resolver, buildsystem, stages):
missing = []
missing.extend(get_necessary_declared_requirements(
resolver, buildsystem.get_declared_dependencies(),
stages))
resolver.install(missing) resolver.install(missing)
STAGE_MAP = {
'dist': [],
'install': ['build'],
'test': ['test', 'dev'],
'build': ['build'],
'clean': []
}
def main(): def main():
import argparse import argparse
@ -81,26 +98,23 @@ def main():
resolver = AutoResolver.from_session(session) resolver = AutoResolver.from_session(session)
os.chdir(args.directory) os.chdir(args.directory)
try: try:
bss = list(detect_buildsystems(args.directory))
if not args.ignore_declared_dependencies: if not args.ignore_declared_dependencies:
from upstream_ontologist.guess import get_upstream_info stages = STAGE_MAP[args.subcommand]
buildsystem, requirements, metadata = get_upstream_info( if stages:
path=args.directory, for bs in bss:
trust_package=True, install_necessary_declared_requirements(
net_access=True, resolver, bs, stages)
consult_external_directory=True,
check=True)
install_declared_requirements(
resolver, requirements, args.subcommand)
if args.subcommand == 'dist': if args.subcommand == 'dist':
run_dist(session=session, resolver=resolver) run_dist(session=session, buildsystems=bss, resolver=resolver)
if args.subcommand == 'build': if args.subcommand == 'build':
run_build(session, resolver=resolver) run_build(session, buildsystems=bss, resolver=resolver)
if args.subcommand == 'clean': if args.subcommand == 'clean':
run_clean(session, resolver=resolver) run_clean(session, buildsystems=bss, resolver=resolver)
if args.subcommand == 'install': if args.subcommand == 'install':
run_install(session, resolver=resolver) run_install(session, buildsystems=bss, resolver=resolver)
if args.subcommand == 'test': if args.subcommand == 'test':
run_test(session, resolver=resolver) run_test(session, buildsystems=bss, resolver=resolver)
except NoBuildToolsFound: except NoBuildToolsFound:
logging.info("No build tools found.") logging.info("No build tools found.")
return 1 return 1

View file

@ -15,16 +15,16 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
from .buildsystem import detect_buildsystems, NoBuildToolsFound from .buildsystem import NoBuildToolsFound
def run_build(session, resolver): def run_build(session, buildsystems, resolver):
# Some things want to write to the user's home directory, # Some things want to write to the user's home directory,
# e.g. pip caches in ~/.cache # e.g. pip caches in ~/.cache
session.create_home() session.create_home()
for buildsystem in detect_buildsystems(session): for buildsystem in buildsystems:
buildsystem.build(resolver) buildsystem.build(session, resolver)
return return
raise NoBuildToolsFound() raise NoBuildToolsFound()

View file

@ -18,9 +18,11 @@
import logging import logging
import os
import re import re
import warnings
from . import shebang_binary, UpstreamPackage from . import shebang_binary, UpstreamRequirement, UpstreamOutput
from .apt import UnidentifiedError from .apt import UnidentifiedError
from .fix_build import run_with_build_fixer from .fix_build import run_with_build_fixer
@ -32,57 +34,73 @@ class NoBuildToolsFound(Exception):
class BuildSystem(object): class BuildSystem(object):
"""A particular buildsystem.""" """A particular buildsystem."""
def __init__(self, session): name: str
self.session = session
def dist(self, resolver): def dist(self, session, resolver):
raise NotImplementedError(self.dist) raise NotImplementedError(self.dist)
def test(self, resolver): def test(self, session, resolver):
raise NotImplementedError(self.test) raise NotImplementedError(self.test)
def build(self, resolver): def build(self, session, resolver):
raise NotImplementedError(self.build) raise NotImplementedError(self.build)
def clean(self, resolver): def clean(self, session, resolver):
raise NotImplementedError(self.clean) raise NotImplementedError(self.clean)
def install(self, resolver): def install(self, session, resolver):
raise NotImplementedError(self.install) raise NotImplementedError(self.install)
def get_declared_dependencies(self):
raise NotImplementedError(self.get_declared_dependencies)
def get_declared_outputs(self):
raise NotImplementedError(self.get_declared_outputs)
class Pear(BuildSystem): class Pear(BuildSystem):
name = 'pear'
def __init__(self, path):
self.path = path
def setup(self, resolver): def setup(self, resolver):
resolver.install([UpstreamPackage('binary', 'pear')]) resolver.install([UpstreamRequirement('binary', 'pear')])
def dist(self, resolver): def dist(self, session, resolver):
self.setup(resolver) self.setup(resolver)
run_with_build_fixer(self.session, ['pear', 'package']) run_with_build_fixer(session, ['pear', 'package'])
def test(self, resolver): def test(self, session, resolver):
self.setup()
run_with_build_fixer(self.session, ["pear", "run-tests"])
def build(self, resolver):
self.setup(resolver) self.setup(resolver)
run_with_build_fixer(self.session, ['pear', 'build']) run_with_build_fixer(session, ['pear', 'run-tests'])
def clean(self, resolver): def build(self, session, resolver):
self.setup(resolver)
run_with_build_fixer(session, ['pear', 'build'])
def clean(self, session, resolver):
self.setup(resolver) self.setup(resolver)
# TODO # TODO
def install(self, resolver): def install(self, session, resolver):
self.setup(resolver) self.setup(resolver)
run_with_build_fixer(self.session, ['pear', 'install']) run_with_build_fixer(session, ['pear', 'install'])
class SetupPy(BuildSystem): class SetupPy(BuildSystem):
name = 'setup.py'
def __init__(self, path):
from distutils.core import run_setup
self.result = run_setup(os.path.abspath(path), stop_after="init")
def setup(self, resolver): def setup(self, resolver):
resolver.install([ resolver.install([
UpstreamPackage('python3', 'pip'), UpstreamRequirement('python3', 'pip'),
UpstreamPackage('binary', 'python3'), UpstreamRequirement('binary', 'python3'),
]) ])
with open('setup.py', 'r') as f: with open('setup.py', 'r') as f:
setup_py_contents = f.read() setup_py_contents = f.read()
@ -93,129 +111,175 @@ class SetupPy(BuildSystem):
setup_cfg_contents = '' setup_cfg_contents = ''
if 'setuptools' in setup_py_contents: if 'setuptools' in setup_py_contents:
logging.info('Reference to setuptools found, installing.') logging.info('Reference to setuptools found, installing.')
resolver.install([UpstreamPackage('python3', 'setuptools')]) resolver.install([UpstreamRequirement('python3', 'setuptools')])
if ('setuptools_scm' in setup_py_contents or if ('setuptools_scm' in setup_py_contents or
'setuptools_scm' in setup_cfg_contents): 'setuptools_scm' in setup_cfg_contents):
logging.info('Reference to setuptools-scm found, installing.') logging.info('Reference to setuptools-scm found, installing.')
resolver.install([ resolver.install([
UpstreamPackage('python3', 'setuptools-scm'), UpstreamRequirement('python3', 'setuptools-scm'),
UpstreamPackage('binary', 'git'), UpstreamRequirement('binary', 'git'),
UpstreamPackage('binary', 'mercurial'), UpstreamRequirement('binary', 'mercurial'),
]) ])
# TODO(jelmer): Install setup_requires # TODO(jelmer): Install setup_requires
def test(self, resolver): def test(self, session, resolver):
self.setup(resolver) self.setup(resolver)
self._run_setup(resolver, ['test']) self._run_setup(session, resolver, ['test'])
def dist(self, resolver): def dist(self, session, resolver):
self.setup(resolver) self.setup(resolver)
self._run_setup(resolver, ['sdist']) self._run_setup(session, resolver, ['sdist'])
def clean(self, resolver): def clean(self, session, resolver):
self.setup(resolver) self.setup(resolver)
self._run_setup(resolver, ['clean']) self._run_setup(session, resolver, ['clean'])
def install(self, resolver): def install(self, session, resolver):
self.setup(resolver) self.setup(resolver)
self._run_setup(resolver, ['install']) self._run_setup(session, resolver, ['install'])
def _run_setup(self, resolver, args): def _run_setup(self, session, resolver, args):
interpreter = shebang_binary('setup.py') interpreter = shebang_binary('setup.py')
if interpreter is not None: if interpreter is not None:
if interpreter in ('python3', 'python2', 'python'): if interpreter in ('python3', 'python2', 'python'):
resolver.install([UpstreamPackage('binary', interpreter)]) resolver.install([UpstreamRequirement('binary', interpreter)])
else: else:
raise ValueError('Unknown interpreter %r' % interpreter) raise ValueError('Unknown interpreter %r' % interpreter)
run_with_build_fixer( run_with_build_fixer(
self.session, ['./setup.py'] + args) session, ['./setup.py'] + args)
else: else:
# Just assume it's Python 3 # Just assume it's Python 3
resolver.install([UpstreamPackage('binary', 'python3')]) resolver.install([UpstreamRequirement('binary', 'python3')])
run_with_build_fixer( run_with_build_fixer(
self.session, ['python3', './setup.py'] + args) session, ['python3', './setup.py'] + args)
def get_declared_dependencies(self):
for require in self.result.get_requires():
yield 'build', UpstreamRequirement('python3', require)
for require in self.result.install_requires:
yield 'install', UpstreamRequirement('python3', require)
for require in self.result.tests_require:
yield 'test', UpstreamRequirement('python3', require)
def get_declared_outputs(self):
for script in (self.result.scripts or []):
yield UpstreamOutput('binary', os.path.basename(script))
entry_points = self.result.entry_points or {}
for script in entry_points.get('console_scripts', []):
yield UpstreamOutput('binary', script.split('=')[0])
for package in self.result.packages or []:
yield UpstreamOutput('python3', package)
class PyProject(BuildSystem): class PyProject(BuildSystem):
name = 'pyproject'
def load_toml(self): def load_toml(self):
import toml import toml
with open("pyproject.toml", "r") as pf: with open("pyproject.toml", "r") as pf:
return toml.load(pf) return toml.load(pf)
def dist(self, resolver): def dist(self, session, resolver):
pyproject = self.load_toml() pyproject = self.load_toml()
if "poetry" in pyproject.get("tool", []): if "poetry" in pyproject.get("tool", []):
logging.info( logging.info(
'Found pyproject.toml with poetry section, ' 'Found pyproject.toml with poetry section, '
'assuming poetry project.') 'assuming poetry project.')
resolver.install([ resolver.install([
UpstreamPackage('python3', 'venv'), UpstreamRequirement('python3', 'venv'),
UpstreamPackage('python3', 'pip'), UpstreamRequirement('python3', 'pip'),
]) ])
self.session.check_call(['pip3', 'install', 'poetry'], user='root') session.check_call(['pip3', 'install', 'poetry'], user='root')
self.session.check_call(['poetry', 'build', '-f', 'sdist']) session.check_call(['poetry', 'build', '-f', 'sdist'])
return return
raise AssertionError("no supported section in pyproject.toml") raise AssertionError("no supported section in pyproject.toml")
class SetupCfg(BuildSystem): class SetupCfg(BuildSystem):
name = 'setup.cfg'
def __init__(self, path):
self.path = path
def setup(self, resolver): def setup(self, resolver):
resolver.install([ resolver.install([
UpstreamPackage('python3', 'pep517'), UpstreamRequirement('python3', 'pep517'),
UpstreamPackage('python3', 'pip'), UpstreamRequirement('python3', 'pip'),
]) ])
def dist(self, resolver): def dist(self, session, resolver):
self.setup(resolver) self.setup(resolver)
self.session.check_call(['python3', '-m', 'pep517.build', '-s', '.']) session.check_call(['python3', '-m', 'pep517.build', '-s', '.'])
class NpmPackage(BuildSystem): class Npm(BuildSystem):
name = 'npm'
def __init__(self, path):
import json
with open(path, 'r') as f:
self.package = json.load(f)
def get_declared_dependencies(self):
if 'devDependencies' in self.package:
for name, unused_version in (
self.package['devDependencies'].items()):
# TODO(jelmer): Look at version
yield 'dev', UpstreamRequirement('npm', name)
def setup(self, resolver): def setup(self, resolver):
resolver.install([UpstreamPackage('binary', 'npm')]) resolver.install([UpstreamRequirement('binary', 'npm')])
def dist(self, resolver): def dist(self, session, resolver):
self.setup(resolver) self.setup(resolver)
run_with_build_fixer(self.session, ['npm', 'pack']) run_with_build_fixer(session, ['npm', 'pack'])
class Waf(BuildSystem): class Waf(BuildSystem):
def setup(self, resolver): name = 'waf'
resolver.install([UpstreamPackage('binary', 'python3')])
def dist(self, resolver): def __init__(self, path):
self.path = path
def setup(self, resolver):
resolver.install([UpstreamRequirement('binary', 'python3')])
def dist(self, session, resolver):
self.setup(resolver) self.setup(resolver)
run_with_build_fixer(self.session, ['./waf', 'dist']) run_with_build_fixer(session, ['./waf', 'dist'])
class Gem(BuildSystem): class Gem(BuildSystem):
def setup(self, resolver): name = 'gem'
resolver.install([UpstreamPackage('binary', 'gem2deb')])
def dist(self, resolver): def __init__(self, path):
self.path = path
def setup(self, resolver):
resolver.install([UpstreamRequirement('binary', 'gem2deb')])
def dist(self, session, resolver):
self.setup(resolver) self.setup(resolver)
gemfiles = [entry.name for entry in self.session.scandir('.') gemfiles = [entry.name for entry in session.scandir('.')
if entry.name.endswith('.gem')] if entry.name.endswith('.gem')]
if len(gemfiles) > 1: if len(gemfiles) > 1:
logging.warning("More than one gemfile. Trying the first?") logging.warning('More than one gemfile. Trying the first?')
run_with_build_fixer(self.session, ["gem2tgz", gemfiles[0]]) run_with_build_fixer(session, ['gem2tgz', gemfiles[0]])
class DistInkt(BuildSystem): class DistInkt(BuildSystem):
def setup(self, resolver): def __init__(self, path):
resolver.install([ self.path = path
UpstreamPackage('perl', 'Dist::Inkt'), self.name = 'dist-zilla'
]) self.dist_inkt_class = None
def dist(self, resolver):
self.setup(resolver)
with open('dist.ini', 'rb') as f: with open('dist.ini', 'rb') as f:
for line in f: for line in f:
if not line.startswith(b";;"): if not line.startswith(b";;"):
@ -226,155 +290,234 @@ class DistInkt(BuildSystem):
continue continue
if key.strip() == b"class" and value.strip().startswith(b"'Dist::Inkt"): if key.strip() == b"class" and value.strip().startswith(b"'Dist::Inkt"):
logging.info( logging.info(
"Found Dist::Inkt section in dist.ini, " "assuming distinkt." 'Found Dist::Inkt section in dist.ini, '
) 'assuming distinkt.')
# TODO(jelmer): install via apt if possible self.name = 'dist-inkt'
self.session.check_call( self.dist_inkt_class = value.decode().strip("'")
["cpan", "install", value.decode().strip("'")], user="root"
)
run_with_build_fixer(self.session, ["distinkt-dist"])
return return
# Default to invoking Dist::Zilla
logging.info('Found dist.ini, assuming dist-zilla.') logging.info('Found dist.ini, assuming dist-zilla.')
resolver.install([UpstreamPackage('perl', 'Dist::Zilla')])
run_with_build_fixer(self.session, ['dzil', 'build', '--in', '..']) def setup(self, resolver):
resolver.install([
UpstreamRequirement('perl', 'Dist::Inkt'),
])
def dist(self, session, resolver):
self.setup(resolver)
if self.name == 'dist-inkt':
resolver.install([
UpstreamRequirement('perl-module', self.dist_inkt_class)])
run_with_build_fixer(session, ['distinkt-dist'])
else:
# Default to invoking Dist::Zilla
resolver.install([UpstreamRequirement('perl', 'Dist::Zilla')])
run_with_build_fixer(session, ['dzil', 'build', '--in', '..'])
class Make(BuildSystem): class Make(BuildSystem):
def setup(self, resolver): name = 'make'
if self.session.exists('Makefile.PL') and not self.session.exists('Makefile'):
resolver.install([UpstreamPackage('binary', 'perl')])
run_with_build_fixer(self.session, ['perl', 'Makefile.PL'])
if not self.session.exists('Makefile') and not self.session.exists('configure'): def setup(self, session, resolver):
if self.session.exists('autogen.sh'): if session.exists('Makefile.PL') and not session.exists('Makefile'):
resolver.install([UpstreamRequirement('binary', 'perl')])
run_with_build_fixer(session, ['perl', 'Makefile.PL'])
if not session.exists('Makefile') and not session.exists('configure'):
if session.exists('autogen.sh'):
if shebang_binary('autogen.sh') is None: if shebang_binary('autogen.sh') is None:
run_with_build_fixer( run_with_build_fixer(
self.session, ['/bin/sh', './autogen.sh']) session, ['/bin/sh', './autogen.sh'])
try: try:
run_with_build_fixer(self.session, ["./autogen.sh"]) run_with_build_fixer(
session, ['./autogen.sh'])
except UnidentifiedError as e: except UnidentifiedError as e:
if ( if ("Gnulib not yet bootstrapped; "
"Gnulib not yet bootstrapped; " "run ./bootstrap instead.\n" in e.lines):
"run ./bootstrap instead.\n" in e.lines run_with_build_fixer(session, ["./bootstrap"])
): run_with_build_fixer(session, ['./autogen.sh'])
run_with_build_fixer(self.session, ["./bootstrap"])
run_with_build_fixer(self.session, ["./autogen.sh"])
else: else:
raise raise
elif self.session.exists("configure.ac") or self.session.exists( elif (session.exists('configure.ac') or
"configure.in" session.exists('configure.in')):
): resolver.install([
apt.install( UpstreamRequirement('binary', 'autoconf'),
["autoconf", "automake", "gettext", "libtool", "gnu-standards"] UpstreamRequirement('binary', 'automake'),
) UpstreamRequirement('binary', 'gettextize'),
run_with_build_fixer(self.session, ["autoreconf", "-i"]) UpstreamRequirement('binary', 'libtoolize'),
])
run_with_build_fixer(session, ['autoreconf', '-i'])
if not self.session.exists("Makefile") and self.session.exists("configure"): if not session.exists('Makefile') and session.exists('configure'):
self.session.check_call(["./configure"]) session.check_call(['./configure'])
def dist(self, resolver): def dist(self, session, resolver):
self.setup(resolver) self.setup(session, resolver)
resolver.install([UpstreamPackage('binary', 'make')]) resolver.install([UpstreamRequirement('binary', 'make')])
try: try:
run_with_build_fixer(self.session, ["make", "dist"]) run_with_build_fixer(session, ['make', 'dist'])
except UnidentifiedError as e: except UnidentifiedError as e:
if "make: *** No rule to make target 'dist'. Stop.\n" in e.lines: if "make: *** No rule to make target 'dist'. Stop.\n" in e.lines:
pass pass
elif "make[1]: *** No rule to make target 'dist'. Stop.\n" in e.lines: elif "make[1]: *** No rule to make target 'dist'. Stop.\n" in e.lines:
pass pass
elif ("Reconfigure the source tree "
"(via './config' or 'perl Configure'), please.\n"
) in e.lines:
run_with_build_fixer(session, ['./config'])
run_with_build_fixer(session, ['make', 'dist'])
elif ( elif (
"Reconfigure the source tree " "Please try running 'make manifest' and then run "
"(via './config' or 'perl Configure'), please.\n" "'make dist' again.\n" in e.lines):
) in e.lines: run_with_build_fixer(session, ['make', 'manifest'])
run_with_build_fixer(self.session, ["./config"]) run_with_build_fixer(session, ['make', 'dist'])
run_with_build_fixer(self.session, ["make", "dist"])
elif (
"Please try running 'make manifest' and then run "
"'make dist' again.\n" in e.lines
):
run_with_build_fixer(self.session, ["make", "manifest"])
run_with_build_fixer(self.session, ["make", "dist"])
elif "Please run ./configure first\n" in e.lines: elif "Please run ./configure first\n" in e.lines:
run_with_build_fixer(self.session, ["./configure"]) run_with_build_fixer(session, ['./configure'])
run_with_build_fixer(self.session, ["make", "dist"]) run_with_build_fixer(session, ['make', 'dist'])
elif any( elif any([re.match(
[ r'Makefile:[0-9]+: \*\*\* Missing \'Make.inc\' '
re.match( r'Run \'./configure \[options\]\' and retry. Stop.\n',
r"Makefile:[0-9]+: \*\*\* Missing \'Make.inc\' " line) for line in e.lines]):
r"Run \'./configure \[options\]\' and retry. Stop.\n", run_with_build_fixer(session, ['./configure'])
line, run_with_build_fixer(session, ['make', 'dist'])
) elif any([re.match(
for line in e.lines r'Problem opening MANIFEST: No such file or directory '
] r'at .* line [0-9]+\.', line) for line in e.lines]):
): run_with_build_fixer(session, ['make', 'manifest'])
run_with_build_fixer(self.session, ["./configure"]) run_with_build_fixer(session, ['make', 'dist'])
run_with_build_fixer(self.session, ["make", "dist"])
elif any(
[
re.match(
r"Problem opening MANIFEST: No such file or directory "
r"at .* line [0-9]+\.",
line,
)
for line in e.lines
]
):
run_with_build_fixer(self.session, ["make", "manifest"])
run_with_build_fixer(self.session, ["make", "dist"])
else: else:
raise raise
else: else:
return return
def get_declared_dependencies(self):
# TODO(jelmer): Split out the perl-specific stuff?
if os.path.exists('META.yml'):
# See http://module-build.sourceforge.net/META-spec-v1.4.html for
# the specification of the format.
import ruamel.yaml
import ruamel.yaml.reader
with open('META.yml', 'rb') as f:
try:
data = ruamel.yaml.load(f, ruamel.yaml.SafeLoader)
except ruamel.yaml.reader.ReaderError as e:
warnings.warn('Unable to parse META.yml: %s' % e)
return
for require in data.get('requires', []):
yield 'build', UpstreamRequirement('perl', require)
def detect_buildsystems(session):
class Cargo(BuildSystem):
name = 'cargo'
def __init__(self, path):
from toml.decoder import load, TomlDecodeError
with open(path, 'r') as f:
self.cargo = load(f)
def get_declared_dependencies(self):
if 'dependencies' in self.cargo:
for name, details in self.cargo['dependencies'].items():
# TODO(jelmer): Look at details['features'], details['version']
yield 'build', UpstreamRequirement('cargo-crate', name)
class Golang(BuildSystem):
"""Go builds."""
name = 'golang'
class Maven(BuildSystem):
name = 'maven'
def __init__(self, path):
self.path = path
class Cabal(BuildSystem):
name = 'cabal'
def __init__(self, path):
self.path = path
def detect_buildsystems(path):
"""Detect build systems.""" """Detect build systems."""
if session.exists("package.xml"): if os.path.exists(os.path.join(path, 'package.xml')):
logging.info("Found package.xml, assuming pear package.") logging.info('Found package.xml, assuming pear package.')
yield Pear(session) yield Pear('package.xml')
if session.exists("setup.py"): if os.path.exists(os.path.join(path, 'setup.py')):
logging.info("Found setup.py, assuming python project.") logging.info('Found setup.py, assuming python project.')
yield SetupPy(session) yield SetupPy('setup.py')
elif os.path.exists(os.path.join(path, 'pyproject.toml')):
logging.info('Found pyproject.toml, assuming python project.')
yield PyProject()
elif os.path.exists(os.path.join(path, 'setup.cfg')):
logging.info('Found setup.cfg, assuming python project.')
yield SetupCfg('setup.cfg')
if session.exists("pyproject.toml"): if os.path.exists(os.path.join(path, 'package.json')):
logging.info("Found pyproject.toml, assuming python project.") logging.info('Found package.json, assuming node package.')
yield PyProject(session) yield Npm('package.json')
if session.exists("setup.cfg"): if os.path.exists(os.path.join(path, 'waf')):
logging.info("Found setup.cfg, assuming python project.") logging.info('Found waf, assuming waf package.')
yield SetupCfg(session) yield Waf('waf')
if session.exists("package.json"): if os.path.exists(os.path.join(path, 'Cargo.toml')):
logging.info("Found package.json, assuming node package.") logging.info('Found Cargo.toml, assuming rust cargo package.')
yield NpmPackage(session) yield Cargo('Cargo.toml')
if session.exists("waf"): if os.path.exists(os.path.join(path, 'pom.xml')):
logging.info("Found waf, assuming waf package.") logging.info('Found pom.xml, assuming maven package.')
yield Waf(session) yield Maven('pom.xml')
if (os.path.exists(os.path.join(path, 'dist.ini')) and
not os.path.exists(os.path.join(path, 'Makefile.PL'))):
yield DistInkt('dist.ini')
gemfiles = [ gemfiles = [
entry.name for entry in session.scandir(".") if entry.name.endswith(".gem") entry.name for entry in os.scandir(path)
] if entry.name.endswith('.gem')]
if gemfiles: if gemfiles:
yield Gem(session) yield Gem(gemfiles[0])
if session.exists("dist.ini") and not session.exists("Makefile.PL"): if any([os.path.exists(os.path.join(path, p)) for p in [
yield DistInkt(session) 'Makefile', 'Makefile.PL', 'autogen.sh', 'configure.ac',
'configure.in']]):
yield Make()
if any( cabal_filenames = [
[ entry.name for entry in os.scandir(path)
session.exists(p) if entry.name.endswith('.cabal')]
for p in [ if cabal_filenames:
"Makefile", if len(cabal_filenames) == 1:
"Makefile.PL", yield Cabal(cabal_filenames[0])
"autogen.sh", else:
"configure.ac", warnings.warn(
"configure.in", 'More than one cabal filename, ignoring all: %r' %
] cabal_filenames)
]
): if os.path.exists(os.path.join(path, '.travis.yml')):
yield Make(session) import yaml
import ruamel.yaml.reader
with open('.travis.yml', 'rb') as f:
try:
data = ruamel.yaml.load(f, ruamel.yaml.SafeLoader)
except ruamel.yaml.reader.ReaderError as e:
warnings.warn('Unable to parse .travis.yml: %s' % (e, ))
else:
language = data.get('language')
if language == 'go':
yield Golang()
for entry in os.scandir(path):
if entry.name.endswith('.go'):
yield Golang()
break

View file

@ -15,16 +15,16 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
from .buildsystem import detect_buildsystems, NoBuildToolsFound from .buildsystem import NoBuildToolsFound
def run_clean(session, resolver): def run_clean(session, buildsystems, resolver):
# Some things want to write to the user's home directory, # Some things want to write to the user's home directory,
# e.g. pip caches in ~/.cache # e.g. pip caches in ~/.cache
session.create_home() session.create_home()
for buildsystem in detect_buildsystems(session): for buildsystem in buildsystems:
buildsystem.clean(resolver) buildsystem.clean(session, resolver)
return return
raise NoBuildToolsFound() raise NoBuildToolsFound()

View file

@ -34,7 +34,7 @@ from buildlog_consultant.common import (
from . import DetailedFailure from . import DetailedFailure
from .buildsystem import detect_buildsystems, NoBuildToolsFound from .buildsystem import NoBuildToolsFound
from .session.schroot import SchrootSession from .session.schroot import SchrootSession
from .vcs import dupe_vcs_tree, export_vcs_tree from .vcs import dupe_vcs_tree, export_vcs_tree
@ -62,13 +62,13 @@ class DistNoTarball(Exception):
"""Dist operation did not create a tarball.""" """Dist operation did not create a tarball."""
def run_dist(session, resolver): def run_dist(session, buildsystems, resolver):
# Some things want to write to the user's home directory, # Some things want to write to the user's home directory,
# e.g. pip caches in ~/.cache # e.g. pip caches in ~/.cache
session.create_home() session.create_home()
for buildsystem in detect_buildsystems(session): for buildsystem in buildsystems:
buildsystem.dist(resolver) buildsystem.dist(session, resolver)
return return
raise NoBuildToolsFound() raise NoBuildToolsFound()
@ -115,13 +115,12 @@ class DistCatcher(object):
def create_dist_schroot( def create_dist_schroot(
tree: Tree, tree: Tree, target_dir: str,
target_dir: str, chroot: str, packaging_tree: Optional[Tree] = None,
chroot: str, include_controldir: bool = True,
packaging_tree: Optional[Tree] = None, subdir: Optional[str] = None) -> str:
include_controldir: bool = True, from .buildsystem import detect_buildsystems
subdir: Optional[str] = None, from .apt import AptResolver
) -> str:
if subdir is None: if subdir is None:
subdir = "package" subdir = "package"
with SchrootSession(chroot) as session: with SchrootSession(chroot) as session:
@ -144,12 +143,15 @@ def create_dist_schroot(
else: else:
dupe_vcs_tree(tree, export_directory) dupe_vcs_tree(tree, export_directory)
buildsystems = list(detect_buildsystems(export_directory))
resolver = AptResolver.from_session(session)
with DistCatcher(export_directory) as dc: with DistCatcher(export_directory) as dc:
oldcwd = os.getcwd() oldcwd = os.getcwd()
os.chdir(export_directory) os.chdir(export_directory)
try: try:
session.chdir(os.path.join(reldir, subdir)) session.chdir(os.path.join(reldir, subdir))
run_dist(session) run_dist(session, buildsystems, resolver)
finally: finally:
os.chdir(oldcwd) os.chdir(oldcwd)

View file

@ -15,16 +15,16 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
from .buildsystem import detect_buildsystems, NoBuildToolsFound from .buildsystem import NoBuildToolsFound
def run_install(session, resolver): def run_install(session, buildsystems, resolver):
# Some things want to write to the user's home directory, # Some things want to write to the user's home directory,
# e.g. pip caches in ~/.cache # e.g. pip caches in ~/.cache
session.create_home() session.create_home()
for buildsystem in detect_buildsystems(session): for buildsystem in buildsystems:
buildsystem.install(resolver) buildsystem.install(session, resolver)
return return
raise NoBuildToolsFound() raise NoBuildToolsFound()

View file

@ -15,16 +15,16 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
from .buildsystem import detect_buildsystems, NoBuildToolsFound from .buildsystem import NoBuildToolsFound
def run_test(session, resolver): def run_test(session, buildsystems, resolver):
# Some things want to write to the user's home directory, # Some things want to write to the user's home directory,
# e.g. pip caches in ~/.cache # e.g. pip caches in ~/.cache
session.create_home() session.create_home()
for buildsystem in detect_buildsystems(session): for buildsystem in buildsystems:
buildsystem.test(resolver) buildsystem.test(session, resolver)
return return
raise NoBuildToolsFound() raise NoBuildToolsFound()