Add hackage repository support.
This commit is contained in:
parent
a963db22be
commit
27a02686d6
5 changed files with 122 additions and 59 deletions
|
@ -38,11 +38,17 @@ def get_necessary_declared_requirements(resolver, requirements, stages):
|
|||
|
||||
def install_necessary_declared_requirements(resolver, buildsystem, stages):
|
||||
missing = []
|
||||
missing.extend(
|
||||
get_necessary_declared_requirements(
|
||||
resolver, buildsystem.get_declared_dependencies(), stages
|
||||
try:
|
||||
declared_reqs = buildsystem.get_declared_dependencies()
|
||||
except NotImplementedError:
|
||||
logging.warning(
|
||||
'Unable to determine declared dependencies from %s', buildsystem)
|
||||
else:
|
||||
missing.extend(
|
||||
get_necessary_declared_requirements(
|
||||
resolver, declared_reqs, stages
|
||||
)
|
||||
)
|
||||
)
|
||||
resolver.install(missing)
|
||||
|
||||
|
||||
|
|
|
@ -124,11 +124,10 @@ def problem_to_upstream_requirement(problem):
|
|||
elif isinstance(problem, MissingJavaClass):
|
||||
return JavaClassRequirement(problem.classname)
|
||||
elif isinstance(problem, MissingHaskellDependencies):
|
||||
# TODO(jelmer): Create multiple HaskellPackageRequirement objects?
|
||||
return HaskellPackageRequirement(problem.package)
|
||||
return [HaskellPackageRequirement(dep) for dep in problem.deps]
|
||||
elif isinstance(problem, MissingMavenArtifacts):
|
||||
# TODO(jelmer): Create multiple MavenArtifactRequirement objects?
|
||||
return MavenArtifactRequirement(problem.artifacts)
|
||||
return [MavenArtifactRequirement(artifact)
|
||||
for artifact in problem.artifacts]
|
||||
elif isinstance(problem, MissingCSharpCompiler):
|
||||
return BinaryRequirement('msc')
|
||||
elif isinstance(problem, GnomeCommonMissing):
|
||||
|
@ -179,16 +178,29 @@ class UpstreamRequirementFixer(BuildFixer):
|
|||
def __init__(self, resolver):
|
||||
self.resolver = resolver
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(%r)" % (type(self).__name__, self.resolver)
|
||||
|
||||
def __str__(self):
|
||||
return "upstream requirement fixer(%s)" % self.resolver
|
||||
|
||||
def can_fix(self, error):
|
||||
req = problem_to_upstream_requirement(error)
|
||||
return req is not None
|
||||
|
||||
def fix(self, error, context):
|
||||
req = problem_to_upstream_requirement(error)
|
||||
if req is None:
|
||||
reqs = problem_to_upstream_requirement(error)
|
||||
if reqs is None:
|
||||
return False
|
||||
|
||||
package = self.resolver.resolve(req)
|
||||
if package is None:
|
||||
return False
|
||||
return context.add_dependency(package)
|
||||
if not isinstance(reqs, list):
|
||||
reqs = [reqs]
|
||||
|
||||
changed = False
|
||||
for req in reqs:
|
||||
package = self.resolver.resolve(reqs)
|
||||
if package is None:
|
||||
return False
|
||||
if context.add_dependency(package):
|
||||
changed = True
|
||||
return changed
|
||||
|
|
|
@ -51,6 +51,9 @@ class BuildSystem(object):
|
|||
|
||||
name: str
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def dist(self, session, resolver, fixers):
|
||||
raise NotImplementedError(self.dist)
|
||||
|
||||
|
@ -125,13 +128,13 @@ class SetupPy(BuildSystem):
|
|||
except FileNotFoundError:
|
||||
setup_cfg_contents = ""
|
||||
if "setuptools" in setup_py_contents:
|
||||
logging.info("Reference to setuptools found, installing.")
|
||||
logging.debug("Reference to setuptools found, installing.")
|
||||
resolver.install([PythonPackageRequirement("setuptools")])
|
||||
if (
|
||||
"setuptools_scm" in setup_py_contents
|
||||
or "setuptools_scm" in setup_cfg_contents
|
||||
):
|
||||
logging.info("Reference to setuptools-scm found, installing.")
|
||||
logging.debug("Reference to setuptools-scm found, installing.")
|
||||
resolver.install(
|
||||
[
|
||||
PythonPackageRequirement("setuptools-scm"),
|
||||
|
@ -215,8 +218,9 @@ class PyProject(BuildSystem):
|
|||
|
||||
def dist(self, session, resolver, fixers):
|
||||
if "poetry" in self.pyproject.get("tool", []):
|
||||
logging.info(
|
||||
"Found pyproject.toml with poetry section, " "assuming poetry project."
|
||||
logging.debug(
|
||||
"Found pyproject.toml with poetry section, "
|
||||
"assuming poetry project."
|
||||
)
|
||||
resolver.install(
|
||||
[
|
||||
|
@ -279,13 +283,17 @@ class Waf(BuildSystem):
|
|||
def __init__(self, path):
|
||||
self.path = path
|
||||
|
||||
def setup(self, resolver):
|
||||
def setup(self, session, resolver, fixers):
|
||||
resolver.install([BinaryRequirement("python3")])
|
||||
|
||||
def dist(self, session, resolver, fixers):
|
||||
self.setup(resolver)
|
||||
self.setup(session, resolver, fixers)
|
||||
run_with_build_fixers(session, ["./waf", "dist"], fixers)
|
||||
|
||||
def test(self, session, resolver, fixers):
|
||||
self.setup(session, resolver, fixers)
|
||||
run_with_build_fixers(session, ["./waf", "test"], fixers)
|
||||
|
||||
|
||||
class Gem(BuildSystem):
|
||||
|
||||
|
@ -321,13 +329,14 @@ class DistInkt(BuildSystem):
|
|||
except ValueError:
|
||||
continue
|
||||
if key.strip() == b"class" and value.strip().startswith(b"'Dist::Inkt"):
|
||||
logging.info(
|
||||
"Found Dist::Inkt section in dist.ini, " "assuming distinkt."
|
||||
logging.debug(
|
||||
"Found Dist::Inkt section in dist.ini, "
|
||||
"assuming distinkt."
|
||||
)
|
||||
self.name = "dist-inkt"
|
||||
self.dist_inkt_class = value.decode().strip("'")
|
||||
return
|
||||
logging.info("Found dist.ini, assuming dist-zilla.")
|
||||
logging.debug("Found dist.ini, assuming dist-zilla.")
|
||||
|
||||
def setup(self, resolver):
|
||||
resolver.install(
|
||||
|
@ -397,15 +406,19 @@ class Make(BuildSystem):
|
|||
session.check_call(["./configure"])
|
||||
|
||||
def build(self, session, resolver, fixers):
|
||||
self.setup(session, resolver)
|
||||
self.setup(session, resolver, fixers)
|
||||
run_with_build_fixers(session, ["make", "all"], fixers)
|
||||
|
||||
def test(self, session, resolver, fixers):
|
||||
self.setup(session, resolver, fixers)
|
||||
run_with_build_fixers(session, ["make", "check"], fixers)
|
||||
|
||||
def install(self, session, resolver, fixers, install_target):
|
||||
self.setup(session, resolver)
|
||||
self.setup(session, resolver, fixers)
|
||||
run_with_build_fixers(session, ["make", "install"], fixers)
|
||||
|
||||
def dist(self, session, resolver, fixers):
|
||||
self.setup(session, resolver)
|
||||
self.setup(session, resolver, fixers)
|
||||
try:
|
||||
run_with_build_fixers(session, ["make", "dist"], fixers)
|
||||
except UnidentifiedError as e:
|
||||
|
@ -491,6 +504,9 @@ class Cargo(BuildSystem):
|
|||
# TODO(jelmer): Look at details['features'], details['version']
|
||||
yield "build", CargoCrateRequirement(name)
|
||||
|
||||
def test(self, session, resolver, fixers):
|
||||
run_with_build_fixers(session, ["cargo", "test"], fixers)
|
||||
|
||||
|
||||
class Golang(BuildSystem):
|
||||
"""Go builds."""
|
||||
|
@ -513,37 +529,59 @@ class Cabal(BuildSystem):
|
|||
def __init__(self, path):
|
||||
self.path = path
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(%r)" % (type(self).__name__, self.path)
|
||||
|
||||
def _run(self, session, args, fixers):
|
||||
try:
|
||||
run_with_build_fixers(
|
||||
session, ["runhaskell", "Setup.hs"] + args, fixers)
|
||||
except UnidentifiedError as e:
|
||||
if "Run the 'configure' command first.\n" in e.lines:
|
||||
run_with_build_fixers(
|
||||
session, ["runhaskell", "Setup.hs", "configure"], fixers)
|
||||
run_with_build_fixers(
|
||||
session, ["runhaskell", "Setup.hs"] + args, fixers)
|
||||
else:
|
||||
raise
|
||||
|
||||
def test(self, session, resolver, fixers):
|
||||
self._run(session, ["test"], fixers)
|
||||
|
||||
def detect_buildsystems(path, trust_package=False): # noqa: C901
|
||||
"""Detect build systems."""
|
||||
if os.path.exists(os.path.join(path, "package.xml")):
|
||||
logging.info("Found package.xml, assuming pear package.")
|
||||
logging.debug("Found package.xml, assuming pear package.")
|
||||
yield Pear("package.xml")
|
||||
|
||||
if os.path.exists(os.path.join(path, "setup.py")):
|
||||
logging.info("Found setup.py, assuming python project.")
|
||||
logging.debug("Found setup.py, assuming python project.")
|
||||
yield SetupPy("setup.py")
|
||||
elif os.path.exists(os.path.join(path, "pyproject.toml")):
|
||||
logging.info("Found pyproject.toml, assuming python project.")
|
||||
logging.debug("Found pyproject.toml, assuming python project.")
|
||||
yield PyProject("pyproject.toml")
|
||||
elif os.path.exists(os.path.join(path, "setup.cfg")):
|
||||
logging.info("Found setup.cfg, assuming python project.")
|
||||
logging.debug("Found setup.cfg, assuming python project.")
|
||||
yield SetupCfg("setup.cfg")
|
||||
|
||||
if os.path.exists(os.path.join(path, "package.json")):
|
||||
logging.info("Found package.json, assuming node package.")
|
||||
logging.debug("Found package.json, assuming node package.")
|
||||
yield Npm("package.json")
|
||||
|
||||
if os.path.exists(os.path.join(path, "waf")):
|
||||
logging.info("Found waf, assuming waf package.")
|
||||
logging.debug("Found waf, assuming waf package.")
|
||||
yield Waf("waf")
|
||||
|
||||
if os.path.exists(os.path.join(path, "Cargo.toml")):
|
||||
logging.info("Found Cargo.toml, assuming rust cargo package.")
|
||||
logging.debug("Found Cargo.toml, assuming rust cargo package.")
|
||||
yield Cargo("Cargo.toml")
|
||||
|
||||
if os.path.exists(os.path.join(path, 'Setup.hs')):
|
||||
logging.debug("Found Setup.hs, assuming haskell package.")
|
||||
yield Cabal('Setup.hs')
|
||||
|
||||
if os.path.exists(os.path.join(path, "pom.xml")):
|
||||
logging.info("Found pom.xml, assuming maven package.")
|
||||
logging.debug("Found pom.xml, assuming maven package.")
|
||||
yield Maven("pom.xml")
|
||||
|
||||
if os.path.exists(os.path.join(path, "dist.ini")) and not os.path.exists(
|
||||
|
@ -569,17 +607,6 @@ def detect_buildsystems(path, trust_package=False): # noqa: C901
|
|||
):
|
||||
yield Make()
|
||||
|
||||
cabal_filenames = [
|
||||
entry.name for entry in os.scandir(path) if entry.name.endswith(".cabal")
|
||||
]
|
||||
if cabal_filenames:
|
||||
if len(cabal_filenames) == 1:
|
||||
yield Cabal(cabal_filenames[0])
|
||||
else:
|
||||
warnings.warn(
|
||||
"More than one cabal filename, ignoring all: %r" % cabal_filenames
|
||||
)
|
||||
|
||||
if os.path.exists(os.path.join(path, ".travis.yml")):
|
||||
import ruamel.yaml.reader
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ def resolve_error(error, context, fixers):
|
|||
logging.warning("No fixer found for %r", error)
|
||||
return False
|
||||
for fixer in relevant_fixers:
|
||||
logging.info("Attempting to use fixer %r to address %r", fixer, error)
|
||||
logging.info("Attempting to use fixer %s to address %r", fixer, error)
|
||||
made_changes = fixer.fix(error, context)
|
||||
if made_changes:
|
||||
return True
|
||||
|
|
|
@ -60,8 +60,30 @@ class CPANResolver(Resolver):
|
|||
def explain(self, requirements):
|
||||
raise NotImplementedError(self.explain)
|
||||
|
||||
def met(self, requirement):
|
||||
raise NotImplementedError(self.met)
|
||||
|
||||
class HackageResolver(Resolver):
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
||||
|
||||
def __str__(self):
|
||||
return "hackage"
|
||||
|
||||
def install(self, requirements):
|
||||
from ..requirements import HaskellPackageRequirement
|
||||
missing = []
|
||||
for requirement in requirements:
|
||||
if not isinstance(requirement, HaskellPackageRequirement):
|
||||
missing.append(requirement)
|
||||
continue
|
||||
self.session.check_call(
|
||||
["cabal", "install", requirement.package],
|
||||
user="root")
|
||||
if missing:
|
||||
raise UnsatisfiedRequirements(missing)
|
||||
|
||||
def explain(self, requirements):
|
||||
raise NotImplementedError(self.explain)
|
||||
|
||||
|
||||
class CargoResolver(Resolver):
|
||||
|
@ -88,9 +110,6 @@ class CargoResolver(Resolver):
|
|||
def explain(self, requirements):
|
||||
raise NotImplementedError(self.explain)
|
||||
|
||||
def met(self, requirement):
|
||||
raise NotImplementedError(self.met)
|
||||
|
||||
|
||||
class PypiResolver(Resolver):
|
||||
|
||||
|
@ -114,9 +133,6 @@ class PypiResolver(Resolver):
|
|||
def explain(self, requirements):
|
||||
raise NotImplementedError(self.explain)
|
||||
|
||||
def met(self, requirement):
|
||||
raise NotImplementedError(self.met)
|
||||
|
||||
|
||||
NPM_COMMAND_PACKAGES = {
|
||||
"del-cli": "del-cli",
|
||||
|
@ -150,14 +166,14 @@ class NpmResolver(Resolver):
|
|||
def explain(self, requirements):
|
||||
raise NotImplementedError(self.explain)
|
||||
|
||||
def met(self, requirement):
|
||||
raise NotImplementedError(self.met)
|
||||
|
||||
|
||||
class StackedResolver(Resolver):
|
||||
def __init__(self, subs):
|
||||
self.subs = subs
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(%r)" % (type(self).__name__, self.subs)
|
||||
|
||||
def __str__(self):
|
||||
return "[" + ", ".join(map(str, self.subs)) + "]"
|
||||
|
||||
|
@ -176,7 +192,8 @@ def native_resolvers(session):
|
|||
CPANResolver(session),
|
||||
PypiResolver(session),
|
||||
NpmResolver(session),
|
||||
CargoResolver(session)])
|
||||
CargoResolver(session),
|
||||
HackageResolver(session)])
|
||||
|
||||
|
||||
class ExplainResolver(Resolver):
|
||||
|
@ -203,5 +220,6 @@ def auto_resolver(session):
|
|||
CPANResolver(session),
|
||||
PypiResolver(session),
|
||||
NpmResolver(session),
|
||||
CargoResolver(session)])
|
||||
CargoResolver(session),
|
||||
HackageResolver(session)])
|
||||
return StackedResolver(resolvers)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue