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):
|
def install_necessary_declared_requirements(resolver, buildsystem, stages):
|
||||||
missing = []
|
missing = []
|
||||||
missing.extend(
|
try:
|
||||||
get_necessary_declared_requirements(
|
declared_reqs = buildsystem.get_declared_dependencies()
|
||||||
resolver, buildsystem.get_declared_dependencies(), stages
|
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)
|
resolver.install(missing)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -124,11 +124,10 @@ def problem_to_upstream_requirement(problem):
|
||||||
elif isinstance(problem, MissingJavaClass):
|
elif isinstance(problem, MissingJavaClass):
|
||||||
return JavaClassRequirement(problem.classname)
|
return JavaClassRequirement(problem.classname)
|
||||||
elif isinstance(problem, MissingHaskellDependencies):
|
elif isinstance(problem, MissingHaskellDependencies):
|
||||||
# TODO(jelmer): Create multiple HaskellPackageRequirement objects?
|
return [HaskellPackageRequirement(dep) for dep in problem.deps]
|
||||||
return HaskellPackageRequirement(problem.package)
|
|
||||||
elif isinstance(problem, MissingMavenArtifacts):
|
elif isinstance(problem, MissingMavenArtifacts):
|
||||||
# TODO(jelmer): Create multiple MavenArtifactRequirement objects?
|
return [MavenArtifactRequirement(artifact)
|
||||||
return MavenArtifactRequirement(problem.artifacts)
|
for artifact in problem.artifacts]
|
||||||
elif isinstance(problem, MissingCSharpCompiler):
|
elif isinstance(problem, MissingCSharpCompiler):
|
||||||
return BinaryRequirement('msc')
|
return BinaryRequirement('msc')
|
||||||
elif isinstance(problem, GnomeCommonMissing):
|
elif isinstance(problem, GnomeCommonMissing):
|
||||||
|
@ -179,16 +178,29 @@ class UpstreamRequirementFixer(BuildFixer):
|
||||||
def __init__(self, resolver):
|
def __init__(self, resolver):
|
||||||
self.resolver = 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):
|
def can_fix(self, error):
|
||||||
req = problem_to_upstream_requirement(error)
|
req = problem_to_upstream_requirement(error)
|
||||||
return req is not None
|
return req is not None
|
||||||
|
|
||||||
def fix(self, error, context):
|
def fix(self, error, context):
|
||||||
req = problem_to_upstream_requirement(error)
|
reqs = problem_to_upstream_requirement(error)
|
||||||
if req is None:
|
if reqs is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
package = self.resolver.resolve(req)
|
if not isinstance(reqs, list):
|
||||||
if package is None:
|
reqs = [reqs]
|
||||||
return False
|
|
||||||
return context.add_dependency(package)
|
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
|
name: str
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
def dist(self, session, resolver, fixers):
|
def dist(self, session, resolver, fixers):
|
||||||
raise NotImplementedError(self.dist)
|
raise NotImplementedError(self.dist)
|
||||||
|
|
||||||
|
@ -125,13 +128,13 @@ class SetupPy(BuildSystem):
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
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.debug("Reference to setuptools found, installing.")
|
||||||
resolver.install([PythonPackageRequirement("setuptools")])
|
resolver.install([PythonPackageRequirement("setuptools")])
|
||||||
if (
|
if (
|
||||||
"setuptools_scm" in setup_py_contents
|
"setuptools_scm" in setup_py_contents
|
||||||
or "setuptools_scm" in setup_cfg_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(
|
resolver.install(
|
||||||
[
|
[
|
||||||
PythonPackageRequirement("setuptools-scm"),
|
PythonPackageRequirement("setuptools-scm"),
|
||||||
|
@ -215,8 +218,9 @@ class PyProject(BuildSystem):
|
||||||
|
|
||||||
def dist(self, session, resolver, fixers):
|
def dist(self, session, resolver, fixers):
|
||||||
if "poetry" in self.pyproject.get("tool", []):
|
if "poetry" in self.pyproject.get("tool", []):
|
||||||
logging.info(
|
logging.debug(
|
||||||
"Found pyproject.toml with poetry section, " "assuming poetry project."
|
"Found pyproject.toml with poetry section, "
|
||||||
|
"assuming poetry project."
|
||||||
)
|
)
|
||||||
resolver.install(
|
resolver.install(
|
||||||
[
|
[
|
||||||
|
@ -279,13 +283,17 @@ class Waf(BuildSystem):
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
self.path = path
|
self.path = path
|
||||||
|
|
||||||
def setup(self, resolver):
|
def setup(self, session, resolver, fixers):
|
||||||
resolver.install([BinaryRequirement("python3")])
|
resolver.install([BinaryRequirement("python3")])
|
||||||
|
|
||||||
def dist(self, session, resolver, fixers):
|
def dist(self, session, resolver, fixers):
|
||||||
self.setup(resolver)
|
self.setup(session, resolver, fixers)
|
||||||
run_with_build_fixers(session, ["./waf", "dist"], 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):
|
class Gem(BuildSystem):
|
||||||
|
|
||||||
|
@ -321,13 +329,14 @@ class DistInkt(BuildSystem):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
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.debug(
|
||||||
"Found Dist::Inkt section in dist.ini, " "assuming distinkt."
|
"Found Dist::Inkt section in dist.ini, "
|
||||||
|
"assuming distinkt."
|
||||||
)
|
)
|
||||||
self.name = "dist-inkt"
|
self.name = "dist-inkt"
|
||||||
self.dist_inkt_class = value.decode().strip("'")
|
self.dist_inkt_class = value.decode().strip("'")
|
||||||
return
|
return
|
||||||
logging.info("Found dist.ini, assuming dist-zilla.")
|
logging.debug("Found dist.ini, assuming dist-zilla.")
|
||||||
|
|
||||||
def setup(self, resolver):
|
def setup(self, resolver):
|
||||||
resolver.install(
|
resolver.install(
|
||||||
|
@ -397,15 +406,19 @@ class Make(BuildSystem):
|
||||||
session.check_call(["./configure"])
|
session.check_call(["./configure"])
|
||||||
|
|
||||||
def build(self, session, resolver, fixers):
|
def build(self, session, resolver, fixers):
|
||||||
self.setup(session, resolver)
|
self.setup(session, resolver, fixers)
|
||||||
run_with_build_fixers(session, ["make", "all"], 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):
|
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)
|
run_with_build_fixers(session, ["make", "install"], fixers)
|
||||||
|
|
||||||
def dist(self, session, resolver, fixers):
|
def dist(self, session, resolver, fixers):
|
||||||
self.setup(session, resolver)
|
self.setup(session, resolver, fixers)
|
||||||
try:
|
try:
|
||||||
run_with_build_fixers(session, ["make", "dist"], fixers)
|
run_with_build_fixers(session, ["make", "dist"], fixers)
|
||||||
except UnidentifiedError as e:
|
except UnidentifiedError as e:
|
||||||
|
@ -491,6 +504,9 @@ class Cargo(BuildSystem):
|
||||||
# TODO(jelmer): Look at details['features'], details['version']
|
# TODO(jelmer): Look at details['features'], details['version']
|
||||||
yield "build", CargoCrateRequirement(name)
|
yield "build", CargoCrateRequirement(name)
|
||||||
|
|
||||||
|
def test(self, session, resolver, fixers):
|
||||||
|
run_with_build_fixers(session, ["cargo", "test"], fixers)
|
||||||
|
|
||||||
|
|
||||||
class Golang(BuildSystem):
|
class Golang(BuildSystem):
|
||||||
"""Go builds."""
|
"""Go builds."""
|
||||||
|
@ -513,37 +529,59 @@ class Cabal(BuildSystem):
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
self.path = 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
|
def detect_buildsystems(path, trust_package=False): # noqa: C901
|
||||||
"""Detect build systems."""
|
"""Detect build systems."""
|
||||||
if os.path.exists(os.path.join(path, "package.xml")):
|
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")
|
yield Pear("package.xml")
|
||||||
|
|
||||||
if os.path.exists(os.path.join(path, "setup.py")):
|
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")
|
yield SetupPy("setup.py")
|
||||||
elif os.path.exists(os.path.join(path, "pyproject.toml")):
|
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")
|
yield PyProject("pyproject.toml")
|
||||||
elif os.path.exists(os.path.join(path, "setup.cfg")):
|
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")
|
yield SetupCfg("setup.cfg")
|
||||||
|
|
||||||
if os.path.exists(os.path.join(path, "package.json")):
|
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")
|
yield Npm("package.json")
|
||||||
|
|
||||||
if os.path.exists(os.path.join(path, "waf")):
|
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")
|
yield Waf("waf")
|
||||||
|
|
||||||
if os.path.exists(os.path.join(path, "Cargo.toml")):
|
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")
|
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")):
|
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")
|
yield Maven("pom.xml")
|
||||||
|
|
||||||
if os.path.exists(os.path.join(path, "dist.ini")) and not os.path.exists(
|
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()
|
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")):
|
if os.path.exists(os.path.join(path, ".travis.yml")):
|
||||||
import ruamel.yaml.reader
|
import ruamel.yaml.reader
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ def resolve_error(error, context, fixers):
|
||||||
logging.warning("No fixer found for %r", error)
|
logging.warning("No fixer found for %r", error)
|
||||||
return False
|
return False
|
||||||
for fixer in relevant_fixers:
|
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)
|
made_changes = fixer.fix(error, context)
|
||||||
if made_changes:
|
if made_changes:
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -60,8 +60,30 @@ class CPANResolver(Resolver):
|
||||||
def explain(self, requirements):
|
def explain(self, requirements):
|
||||||
raise NotImplementedError(self.explain)
|
raise NotImplementedError(self.explain)
|
||||||
|
|
||||||
def met(self, requirement):
|
|
||||||
raise NotImplementedError(self.met)
|
class 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):
|
class CargoResolver(Resolver):
|
||||||
|
@ -88,9 +110,6 @@ class CargoResolver(Resolver):
|
||||||
def explain(self, requirements):
|
def explain(self, requirements):
|
||||||
raise NotImplementedError(self.explain)
|
raise NotImplementedError(self.explain)
|
||||||
|
|
||||||
def met(self, requirement):
|
|
||||||
raise NotImplementedError(self.met)
|
|
||||||
|
|
||||||
|
|
||||||
class PypiResolver(Resolver):
|
class PypiResolver(Resolver):
|
||||||
|
|
||||||
|
@ -114,9 +133,6 @@ class PypiResolver(Resolver):
|
||||||
def explain(self, requirements):
|
def explain(self, requirements):
|
||||||
raise NotImplementedError(self.explain)
|
raise NotImplementedError(self.explain)
|
||||||
|
|
||||||
def met(self, requirement):
|
|
||||||
raise NotImplementedError(self.met)
|
|
||||||
|
|
||||||
|
|
||||||
NPM_COMMAND_PACKAGES = {
|
NPM_COMMAND_PACKAGES = {
|
||||||
"del-cli": "del-cli",
|
"del-cli": "del-cli",
|
||||||
|
@ -150,14 +166,14 @@ class NpmResolver(Resolver):
|
||||||
def explain(self, requirements):
|
def explain(self, requirements):
|
||||||
raise NotImplementedError(self.explain)
|
raise NotImplementedError(self.explain)
|
||||||
|
|
||||||
def met(self, requirement):
|
|
||||||
raise NotImplementedError(self.met)
|
|
||||||
|
|
||||||
|
|
||||||
class StackedResolver(Resolver):
|
class StackedResolver(Resolver):
|
||||||
def __init__(self, subs):
|
def __init__(self, subs):
|
||||||
self.subs = subs
|
self.subs = subs
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "%s(%r)" % (type(self).__name__, self.subs)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "[" + ", ".join(map(str, self.subs)) + "]"
|
return "[" + ", ".join(map(str, self.subs)) + "]"
|
||||||
|
|
||||||
|
@ -176,7 +192,8 @@ def native_resolvers(session):
|
||||||
CPANResolver(session),
|
CPANResolver(session),
|
||||||
PypiResolver(session),
|
PypiResolver(session),
|
||||||
NpmResolver(session),
|
NpmResolver(session),
|
||||||
CargoResolver(session)])
|
CargoResolver(session),
|
||||||
|
HackageResolver(session)])
|
||||||
|
|
||||||
|
|
||||||
class ExplainResolver(Resolver):
|
class ExplainResolver(Resolver):
|
||||||
|
@ -203,5 +220,6 @@ def auto_resolver(session):
|
||||||
CPANResolver(session),
|
CPANResolver(session),
|
||||||
PypiResolver(session),
|
PypiResolver(session),
|
||||||
NpmResolver(session),
|
NpmResolver(session),
|
||||||
CargoResolver(session)])
|
CargoResolver(session),
|
||||||
|
HackageResolver(session)])
|
||||||
return StackedResolver(resolvers)
|
return StackedResolver(resolvers)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue