|
|
|
From 2cac5e5ad5ff5472923ce333bef59679612bbaa2 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Igor Gnatenko <ignatenkobrain@fedoraproject.org>
|
|
|
|
Date: Fri, 26 Oct 2018 11:20:13 +0200
|
|
|
|
Subject: [PATCH 07/13] split features into subpackages
|
|
|
|
|
|
|
|
References: https://discussion.fedoraproject.org/t/rfc-new-crates-packaging-design-features-have-their-own-subpackages/563?u=ignatenkobrain
|
|
|
|
Signed-off-by: Igor Gnatenko <ignatenkobrain@fedoraproject.org>
|
|
|
|
---
|
|
|
|
data/cargo.attr | 4 +-
|
|
|
|
data/macros.cargo | 10 +
|
|
|
|
rust2rpm/__main__.py | 11 +-
|
|
|
|
rust2rpm/inspector.py | 22 ++-
|
|
|
|
rust2rpm/metadata.py | 317 ++++++++++++++++----------------
|
|
|
|
rust2rpm/templates/main.spec | 142 +++++++-------
|
|
|
|
test.py | 347 ++++-------------------------------
|
|
|
|
7 files changed, 298 insertions(+), 555 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/data/cargo.attr b/data/cargo.attr
|
|
|
|
index 392a72b..4910b5c 100644
|
|
|
|
--- a/data/cargo.attr
|
|
|
|
+++ b/data/cargo.attr
|
|
|
|
@@ -1,3 +1,3 @@
|
|
|
|
-%__cargo_provides %{_bindir}/cargo-inspector --provides
|
|
|
|
-%__cargo_requires %{_bindir}/cargo-inspector --requires
|
|
|
|
+%__cargo_provides %{_bindir}/cargo-inspector --provides --feature=%{__cargo_feature_from_name -n %{name}}
|
|
|
|
+%__cargo_requires %{_bindir}/cargo-inspector --requires --feature=%{__cargo_feature_from_name -n %{name}}
|
|
|
|
%__cargo_path ^%{cargo_registry}/[^/]+/Cargo\\.toml$
|
|
|
|
diff --git a/data/macros.cargo b/data/macros.cargo
|
|
|
|
index a0c456a..7fb025b 100644
|
|
|
|
--- a/data/macros.cargo
|
|
|
|
+++ b/data/macros.cargo
|
|
|
|
@@ -84,3 +84,13 @@ if %__cargo_is_bin; then \
|
|
|
|
%{__rm} %{buildroot}%{_prefix}/.crates.toml \
|
|
|
|
fi \
|
|
|
|
)
|
|
|
|
+
|
|
|
|
+%__cargo_feature_from_name(n:) %{lua:
|
|
|
|
+local name = rpm.expand("%{-n*}")
|
|
|
|
+local feature = string.match(name, "^.+%+(.+)-devel$")
|
|
|
|
+if feature == nil then
|
|
|
|
+ print()
|
|
|
|
+else
|
|
|
|
+ print(feature)
|
|
|
|
+end
|
|
|
|
+}
|
|
|
|
diff --git a/rust2rpm/__main__.py b/rust2rpm/__main__.py
|
|
|
|
index f23ebbc..d19cb47 100644
|
|
|
|
--- a/rust2rpm/__main__.py
|
|
|
|
+++ b/rust2rpm/__main__.py
|
|
|
|
@@ -18,15 +18,19 @@ import requests
|
|
|
|
import tqdm
|
|
|
|
|
|
|
|
from . import Metadata, licensing
|
|
|
|
+from .metadata import normalize_deps
|
|
|
|
|
|
|
|
DEFAULT_EDITOR = "vi"
|
|
|
|
XDG_CACHE_HOME = os.getenv("XDG_CACHE_HOME", os.path.expanduser("~/.cache"))
|
|
|
|
CACHEDIR = os.path.join(XDG_CACHE_HOME, "rust2rpm")
|
|
|
|
API_URL = "https://crates.io/api/v1/"
|
|
|
|
JINJA_ENV = jinja2.Environment(loader=jinja2.ChoiceLoader([
|
|
|
|
- jinja2.FileSystemLoader(["/"]),
|
|
|
|
- jinja2.PackageLoader("rust2rpm", "templates"), ]),
|
|
|
|
- trim_blocks=True, lstrip_blocks=True)
|
|
|
|
+ jinja2.FileSystemLoader(["/"]),
|
|
|
|
+ jinja2.PackageLoader("rust2rpm", "templates"),
|
|
|
|
+ ]),
|
|
|
|
+ extensions=["jinja2.ext.do"],
|
|
|
|
+ trim_blocks=True,
|
|
|
|
+ lstrip_blocks=True)
|
|
|
|
|
|
|
|
def get_default_target():
|
|
|
|
# TODO: add fallback for /usr/lib/os-release
|
|
|
|
@@ -227,6 +231,7 @@ def main():
|
|
|
|
patch=args.patch,
|
|
|
|
store=args.store_crate)
|
|
|
|
|
|
|
|
+ JINJA_ENV.globals["normalize_deps"] = normalize_deps
|
|
|
|
template = JINJA_ENV.get_template("main.spec")
|
|
|
|
|
|
|
|
if args.patch and len(diff) > 0:
|
|
|
|
diff --git a/rust2rpm/inspector.py b/rust2rpm/inspector.py
|
|
|
|
index 2d488b2..9e79e88 100644
|
|
|
|
--- a/rust2rpm/inspector.py
|
|
|
|
+++ b/rust2rpm/inspector.py
|
|
|
|
@@ -1,8 +1,8 @@
|
|
|
|
import argparse
|
|
|
|
-import itertools
|
|
|
|
import sys
|
|
|
|
|
|
|
|
from . import Metadata
|
|
|
|
+from .metadata import normalize_deps
|
|
|
|
|
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
@@ -10,18 +10,23 @@ def main():
|
|
|
|
group.add_argument("-n", "--name", action="store_true", help="Print name")
|
|
|
|
group.add_argument("-v", "--version", action="store_true", help="Print version")
|
|
|
|
group.add_argument("-t", "--target-kinds", action="store_true", help="Print target kinds")
|
|
|
|
+ group.add_argument("-l", "--list-features", action="store_true", help="Print features")
|
|
|
|
group.add_argument("-P", "--provides", action="store_true", help="Print Provides")
|
|
|
|
group.add_argument("-R", "--requires", action="store_true", help="Print Requires")
|
|
|
|
group.add_argument("-BR", "--build-requires", action="store_true", help="Print BuildRequires")
|
|
|
|
group.add_argument("-TR", "--test-requires", action="store_true", help="Print TestRequires")
|
|
|
|
+ parser.add_argument("-f", "--feature", help="Feature to work on")
|
|
|
|
parser.add_argument("file", nargs="*", help="Path(s) to Cargo.toml")
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
files = args.file or sys.stdin.readlines()
|
|
|
|
|
|
|
|
+ if not args.feature:
|
|
|
|
+ args.feature = None
|
|
|
|
+
|
|
|
|
def print_deps(deps):
|
|
|
|
if len(deps) > 0:
|
|
|
|
- print("\n".join(str(dep) for dep in deps))
|
|
|
|
+ print("\n".join(sorted(normalize_deps(deps))))
|
|
|
|
|
|
|
|
for f in files:
|
|
|
|
f = f.rstrip()
|
|
|
|
@@ -32,17 +37,20 @@ def main():
|
|
|
|
print(md.version)
|
|
|
|
if args.target_kinds:
|
|
|
|
print("\n".join(set(tgt.kind for tgt in md.targets)))
|
|
|
|
+ if args.list_features:
|
|
|
|
+ for f in sorted(f for f in md.dependencies if f is not None):
|
|
|
|
+ print(f)
|
|
|
|
if args.provides:
|
|
|
|
- print_deps(md.provides)
|
|
|
|
- if args.requires or args.build_requires:
|
|
|
|
- print_deps(list(itertools.chain(md.requires, md.build_requires)))
|
|
|
|
- if args.test_requires:
|
|
|
|
- print_deps(md.test_requires)
|
|
|
|
+ print(md.provides(args.feature))
|
|
|
|
if args.requires:
|
|
|
|
# Someone should own /usr/share/cargo/registry
|
|
|
|
print("cargo")
|
|
|
|
+ print_deps(md.requires(args.feature))
|
|
|
|
if args.build_requires:
|
|
|
|
print("rust-packaging")
|
|
|
|
+ print_deps(md.requires(args.feature or "default", resolve=True))
|
|
|
|
+ if args.test_requires:
|
|
|
|
+ print_deps(md.dev_dependencies)
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|
|
|
|
diff --git a/rust2rpm/metadata.py b/rust2rpm/metadata.py
|
|
|
|
index 5adeb65..4929cdd 100644
|
|
|
|
--- a/rust2rpm/metadata.py
|
|
|
|
+++ b/rust2rpm/metadata.py
|
|
|
|
@@ -1,208 +1,207 @@
|
|
|
|
__all__ = ["Dependency", "Metadata"]
|
|
|
|
|
|
|
|
-import itertools
|
|
|
|
+import copy
|
|
|
|
import json
|
|
|
|
import subprocess
|
|
|
|
-import sys
|
|
|
|
|
|
|
|
import semantic_version as semver
|
|
|
|
import rustcfg
|
|
|
|
|
|
|
|
-class Target(object):
|
|
|
|
- def __init__(self, kind, name):
|
|
|
|
- self.kind = kind
|
|
|
|
+class Target:
|
|
|
|
+ def __init__(self, name, kind):
|
|
|
|
self.name = name
|
|
|
|
+ self.kind = kind
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
- return "<Target {self.kind}|{self.name}>".format(self=self)
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-def _req_to_str(name, spec=None, feature=None):
|
|
|
|
- f_part = "/{}".format(feature) if feature is not None else ""
|
|
|
|
- basestr = "crate({}{})".format(name, f_part)
|
|
|
|
- if spec is None:
|
|
|
|
- return basestr
|
|
|
|
- if spec.kind == spec.KIND_EQUAL:
|
|
|
|
- spec.kind = spec.KIND_SHORTEQ
|
|
|
|
- if spec.kind == spec.KIND_ANY:
|
|
|
|
- if spec.spec == "":
|
|
|
|
- # Just wildcard
|
|
|
|
- return basestr
|
|
|
|
- else:
|
|
|
|
- # Wildcard in string
|
|
|
|
- assert False, spec.spec
|
|
|
|
- version = str(spec.spec).replace("-", "~")
|
|
|
|
- return "{} {} {}".format(basestr, spec.kind, version)
|
|
|
|
+ return f"<Target {self.name} ({self.kind})>"
|
|
|
|
|
|
|
|
-class Dependency(object):
|
|
|
|
- def __init__(self, name, req, features=(), provides=False):
|
|
|
|
+class Dependency:
|
|
|
|
+ def __init__(self, name, req=None, features=(), optional=False):
|
|
|
|
self.name = name
|
|
|
|
- self.spec = self._parse_req(req)
|
|
|
|
+ self.req = req
|
|
|
|
self.features = features
|
|
|
|
- self.provides = provides
|
|
|
|
- if self.provides:
|
|
|
|
- if len(self.spec.specs) > 1 or \
|
|
|
|
- (len(self.spec.specs) == 1 and self.spec.specs[0].kind != self.spec.specs[0].KIND_EQUAL):
|
|
|
|
- raise Exception("Provides can't be applied to ranged version, {!r}".format(self.spec))
|
|
|
|
-
|
|
|
|
- def __repr__(self):
|
|
|
|
- if self.provides:
|
|
|
|
- spec = self.spec.specs[0]
|
|
|
|
- provs = [_req_to_str(self.name, spec)]
|
|
|
|
- for feature in self.features:
|
|
|
|
- provs.append(_req_to_str(self.name, spec, feature))
|
|
|
|
- return " and ".join(provs)
|
|
|
|
-
|
|
|
|
- reqs = [_req_to_str(self.name, spec=req) for req in self.spec.specs]
|
|
|
|
- features = [_req_to_str(self.name, feature=feature) for feature in self.features]
|
|
|
|
+ self.optional = optional
|
|
|
|
|
|
|
|
- use_rich = False
|
|
|
|
- if len(reqs) > 1:
|
|
|
|
- reqstr = "({})".format(" with ".join(reqs))
|
|
|
|
- use_rich = True
|
|
|
|
- elif len(reqs) == 1:
|
|
|
|
- reqstr = reqs[0]
|
|
|
|
- else:
|
|
|
|
- reqstr = ""
|
|
|
|
- if len(features) > 0:
|
|
|
|
- featurestr = " with ".join(features)
|
|
|
|
- use_rich = True
|
|
|
|
- else:
|
|
|
|
- featurestr = ""
|
|
|
|
-
|
|
|
|
- if use_rich:
|
|
|
|
- if reqstr and featurestr:
|
|
|
|
- return "({} with {})".format(reqstr, featurestr)
|
|
|
|
- elif reqstr and not featurestr:
|
|
|
|
- return reqstr
|
|
|
|
- elif not reqstr and featurestr:
|
|
|
|
- return "({})".format(featurestr)
|
|
|
|
- else:
|
|
|
|
- assert False
|
|
|
|
- else:
|
|
|
|
- return reqstr
|
|
|
|
+ @classmethod
|
|
|
|
+ def from_json(cls, metadata):
|
|
|
|
+ features = set(metadata['features'])
|
|
|
|
+ if metadata['uses_default_features']:
|
|
|
|
+ features.add('default')
|
|
|
|
+ kwargs = {'name': metadata['name'],
|
|
|
|
+ 'req': metadata['req'],
|
|
|
|
+ 'optional': metadata['optional'],
|
|
|
|
+ 'features': features}
|
|
|
|
+ return cls(**kwargs)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
- def _parse_req(s):
|
|
|
|
- if "*" in s and s != "*":
|
|
|
|
- # XXX: https://github.com/rbarrois/python-semanticversion/issues/51
|
|
|
|
- s = "~{}".format(s.replace(".*", "", 1))
|
|
|
|
- if ".*" in s:
|
|
|
|
- s = s.replace(".*", "")
|
|
|
|
- spec = semver.Spec(s.replace(" ", ""))
|
|
|
|
- parsed = []
|
|
|
|
+ def _normalize_req(req):
|
|
|
|
+ if "*" in req and req != "*":
|
|
|
|
+ raise NotImplementedError(f"'*' is not supported: {req}")
|
|
|
|
+ spec = semver.Spec(req.replace(" ", ""))
|
|
|
|
+ reqs = []
|
|
|
|
for req in spec.specs:
|
|
|
|
- ver = req.spec
|
|
|
|
if req.kind == req.KIND_ANY:
|
|
|
|
- parsed.append("*")
|
|
|
|
+ # Any means any
|
|
|
|
continue
|
|
|
|
+ ver = req.spec
|
|
|
|
+ if ver.prerelease:
|
|
|
|
+ raise NotImplementedError(f"Pre-release requirement is not supported: {ver}")
|
|
|
|
+ if req.kind in (req.KIND_NEQ, req.KIND_EMPTY):
|
|
|
|
+ raise NotImplementedError(f"'!=' and empty kinds are not supported: {req}")
|
|
|
|
coerced = semver.Version.coerce(str(ver))
|
|
|
|
- if req.kind in (req.KIND_CARET, req.KIND_TILDE):
|
|
|
|
- if ver.prerelease:
|
|
|
|
- # pre-release versions only match the same x.y.z
|
|
|
|
- if ver.patch is not None:
|
|
|
|
- upper = ver.next_patch()
|
|
|
|
- elif ver.minor is not None:
|
|
|
|
- upper = ver.next_minor()
|
|
|
|
- else:
|
|
|
|
- upper = ver.next_major()
|
|
|
|
- elif req.kind == req.KIND_CARET:
|
|
|
|
- if ver.major == 0:
|
|
|
|
- if ver.minor is not None:
|
|
|
|
- if ver.patch is None or ver.minor != 0:
|
|
|
|
- upper = ver.next_minor()
|
|
|
|
- else:
|
|
|
|
- upper = ver.next_patch()
|
|
|
|
+ if req.kind == req.KIND_EQUAL:
|
|
|
|
+ req.kind = req.KIND_SHORTEQ
|
|
|
|
+ if req.kind in (req.KIND_CARET, req.KIND_COMPATIBLE):
|
|
|
|
+ if ver.major == 0:
|
|
|
|
+ if ver.minor is not None:
|
|
|
|
+ if ver.minor != 0 or ver.patch is None:
|
|
|
|
+ upper = ver.next_minor()
|
|
|
|
else:
|
|
|
|
- upper = ver.next_major()
|
|
|
|
+ upper = ver.next_patch()
|
|
|
|
else:
|
|
|
|
upper = ver.next_major()
|
|
|
|
- elif req.kind == req.KIND_TILDE:
|
|
|
|
- if ver.minor is None:
|
|
|
|
- upper = ver.next_major()
|
|
|
|
- else:
|
|
|
|
- upper = ver.next_minor()
|
|
|
|
else:
|
|
|
|
- assert False
|
|
|
|
- parsed.append(">={}".format(coerced))
|
|
|
|
- parsed.append("<{}".format(upper))
|
|
|
|
- elif req.kind == req.KIND_NEQ:
|
|
|
|
- parsed.append(">{}".format(coerced))
|
|
|
|
- parsed.append("<{}".format(coerced))
|
|
|
|
- elif req.kind in (req.KIND_EQUAL, req.KIND_GT, req.KIND_GTE, req.KIND_LT, req.KIND_LTE):
|
|
|
|
- parsed.append("{}{}".format(req.kind, coerced))
|
|
|
|
+ upper = ver.next_major()
|
|
|
|
+ reqs.append((">=", coerced))
|
|
|
|
+ reqs.append(("<", upper))
|
|
|
|
+ elif req.kind == req.KIND_TILDE:
|
|
|
|
+ if ver.minor is None:
|
|
|
|
+ upper = ver.next_major()
|
|
|
|
+ else:
|
|
|
|
+ upper = ver.next_minor()
|
|
|
|
+ reqs.append((">=", coerced))
|
|
|
|
+ reqs.append(("<", upper))
|
|
|
|
+ elif req.kind in (req.KIND_SHORTEQ,
|
|
|
|
+ req.KIND_GT,
|
|
|
|
+ req.KIND_GTE,
|
|
|
|
+ req.KIND_LT,
|
|
|
|
+ req.KIND_LTE):
|
|
|
|
+ reqs.append((str(req.kind), coerced))
|
|
|
|
else:
|
|
|
|
- assert False, req.kind
|
|
|
|
- return semver.Spec(",".join(parsed))
|
|
|
|
+ raise AssertionError(f"Found unhandled kind: {req.kind}")
|
|
|
|
+ return reqs
|
|
|
|
|
|
|
|
-class Metadata(object):
|
|
|
|
- def __init__(self):
|
|
|
|
- self.name = None
|
|
|
|
+ @staticmethod
|
|
|
|
+ def _apply_reqs(name, reqs, feature=None):
|
|
|
|
+ fstr = f"/{feature}" if feature is not None else ""
|
|
|
|
+ cap = f"crate({name}{fstr})"
|
|
|
|
+ if not reqs:
|
|
|
|
+ return cap
|
|
|
|
+ deps = " with ".join(f"{cap} {op} {version}" for op, version in reqs)
|
|
|
|
+ if len(reqs) > 1:
|
|
|
|
+ return f"({deps})"
|
|
|
|
+ else:
|
|
|
|
+ return deps
|
|
|
|
+
|
|
|
|
+ def normalize(self):
|
|
|
|
+ return [self._apply_reqs(self.name, self._normalize_req(self.req), feature)
|
|
|
|
+ for feature in self.features or (None,)]
|
|
|
|
+
|
|
|
|
+ def __repr__(self):
|
|
|
|
+ return f"<Dependency: {self.name} {self.req} ({', '.join(sorted(self.features))})>"
|
|
|
|
+
|
|
|
|
+ def __str__(self):
|
|
|
|
+ return "\n".join(self.normalize())
|
|
|
|
+
|
|
|
|
+class Metadata:
|
|
|
|
+ def __init__(self, name, version):
|
|
|
|
+ self.name = name
|
|
|
|
+ self.version = version
|
|
|
|
self.license = None
|
|
|
|
self.license_file = None
|
|
|
|
self.readme = None
|
|
|
|
self.description = None
|
|
|
|
- self.version = None
|
|
|
|
- self._targets = []
|
|
|
|
- self.provides = []
|
|
|
|
- self.requires = []
|
|
|
|
- self.build_requires = []
|
|
|
|
- self.test_requires = []
|
|
|
|
+ self.targets = set()
|
|
|
|
+ self.dependencies = {}
|
|
|
|
+ self.dev_dependencies = set()
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def from_json(cls, metadata):
|
|
|
|
- self = cls()
|
|
|
|
-
|
|
|
|
md = metadata
|
|
|
|
- self.name = md["name"]
|
|
|
|
+ self = cls(md["name"], md["version"])
|
|
|
|
+
|
|
|
|
self.license = md["license"]
|
|
|
|
self.license_file = md["license_file"]
|
|
|
|
self.readme = md["readme"]
|
|
|
|
self.description = md.get("description")
|
|
|
|
- self.version = md["version"]
|
|
|
|
- version = "={}".format(self.version)
|
|
|
|
-
|
|
|
|
- # Targets
|
|
|
|
- self.targets = [Target(tgt["kind"][0], tgt["name"]) for tgt in md["targets"]]
|
|
|
|
-
|
|
|
|
- # Provides
|
|
|
|
- # All optional dependencies are also features
|
|
|
|
- # https://github.com/rust-lang/cargo/issues/4911
|
|
|
|
- features = itertools.chain((x["name"] for x in md["dependencies"] if x["optional"]),
|
|
|
|
- md["features"])
|
|
|
|
- provides = Dependency(self.name, version, features=features, provides=True)
|
|
|
|
- self.provides = str(provides).split(" and ")
|
|
|
|
-
|
|
|
|
- ev = rustcfg.Evaluator.platform()
|
|
|
|
-
|
|
|
|
- # Dependencies
|
|
|
|
- for dep in md["dependencies"]:
|
|
|
|
- kind = dep["kind"]
|
|
|
|
- if kind is None:
|
|
|
|
- requires = self.requires
|
|
|
|
- elif kind == "build":
|
|
|
|
- requires = self.build_requires
|
|
|
|
- elif kind == "dev":
|
|
|
|
- requires = self.test_requires
|
|
|
|
- else:
|
|
|
|
- raise ValueError("Unknown kind: {!r}, please report bug.".format(kind))
|
|
|
|
|
|
|
|
- target = dep["target"]
|
|
|
|
- if target is None:
|
|
|
|
- pass
|
|
|
|
+ # dependencies + build-dependencies → runtime
|
|
|
|
+ deps_by_name = {dep["name"]: Dependency.from_json(dep)
|
|
|
|
+ for dep in md["dependencies"]
|
|
|
|
+ if dep["kind"] != "dev"}
|
|
|
|
+
|
|
|
|
+ deps_by_feature = {}
|
|
|
|
+ for feature, f_deps in md["features"].items():
|
|
|
|
+ features = {None}
|
|
|
|
+ deps = set()
|
|
|
|
+ for dep in f_deps:
|
|
|
|
+ if dep in md["features"]:
|
|
|
|
+ features.add(dep)
|
|
|
|
+ else:
|
|
|
|
+ pkg, _, f = dep.partition("/")
|
|
|
|
+ dep = copy.deepcopy(deps_by_name[pkg])
|
|
|
|
+ if f:
|
|
|
|
+ dep.features = {f}
|
|
|
|
+ deps.add(dep)
|
|
|
|
+ deps_by_feature[feature] = (features, deps)
|
|
|
|
+
|
|
|
|
+ mandatory_deps = set()
|
|
|
|
+ for dep in deps_by_name.values():
|
|
|
|
+ if dep.optional:
|
|
|
|
+ deps_by_feature[dep.name] = ({None}, {copy.deepcopy(dep)})
|
|
|
|
else:
|
|
|
|
- cond = ev.parse_and_eval(target)
|
|
|
|
- if not cond:
|
|
|
|
- print(f'Dependency {dep["name"]} for target {target!r} is not needed, ignoring.',
|
|
|
|
- file=sys.stderr)
|
|
|
|
- continue
|
|
|
|
+ mandatory_deps.add(copy.deepcopy(dep))
|
|
|
|
+ deps_by_feature[None] = (set(), mandatory_deps)
|
|
|
|
+
|
|
|
|
+ if "default" not in deps_by_feature:
|
|
|
|
+ deps_by_feature["default"] = ({None}, set())
|
|
|
|
|
|
|
|
- requires.append(Dependency(dep["name"], dep["req"], features=dep["features"]))
|
|
|
|
+ self.dependencies = deps_by_feature
|
|
|
|
+ self.dev_dependencies = {Dependency.from_json(dep)
|
|
|
|
+ for dep in md["dependencies"]
|
|
|
|
+ if dep["kind"] == "dev"}
|
|
|
|
+
|
|
|
|
+ self.targets = {Target(tgt["name"], tgt["kind"][0])
|
|
|
|
+ for tgt in md["targets"]}
|
|
|
|
|
|
|
|
return self
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def from_file(cls, path):
|
|
|
|
metadata = subprocess.check_output(["cargo", "read-manifest",
|
|
|
|
- "--manifest-path={}".format(path)])
|
|
|
|
+ f"--manifest-path={path}"])
|
|
|
|
return cls.from_json(json.loads(metadata))
|
|
|
|
+
|
|
|
|
+ @property
|
|
|
|
+ def all_dependencies(self):
|
|
|
|
+ return set().union(*(x[1] for x in self.dependencies.values()))
|
|
|
|
+
|
|
|
|
+ def provides(self, feature=None):
|
|
|
|
+ if feature not in self.dependencies:
|
|
|
|
+ raise KeyError(f"Feature {feature!r} doesn't exist")
|
|
|
|
+ return Dependency(self.name, f"={self.version}", features={feature})
|
|
|
|
+
|
|
|
|
+ @classmethod
|
|
|
|
+ def _resolve(cls, deps_by_feature, feature):
|
|
|
|
+ all_features = set()
|
|
|
|
+ all_deps = set()
|
|
|
|
+ ff, dd = copy.deepcopy(deps_by_feature[feature])
|
|
|
|
+ all_features |= ff
|
|
|
|
+ all_deps |= dd
|
|
|
|
+ for f in ff:
|
|
|
|
+ ff1, dd1 = cls._resolve(deps_by_feature, f)
|
|
|
|
+ all_features |= ff1
|
|
|
|
+ all_deps |= dd1
|
|
|
|
+ return all_features, all_deps
|
|
|
|
+
|
|
|
|
+ def requires(self, feature=None, resolve=False):
|
|
|
|
+ if resolve:
|
|
|
|
+ return self._resolve(self.dependencies, feature)[1]
|
|
|
|
+ else:
|
|
|
|
+ features, deps = self.dependencies[feature]
|
|
|
|
+ fdeps = set(Dependency(self.name, f"={self.version}", features={feature})
|
|
|
|
+ for feature in features)
|
|
|
|
+ return fdeps | deps
|
|
|
|
+
|
|
|
|
+def normalize_deps(deps):
|
|
|
|
+ return set().union(*(d.normalize() for d in deps))
|
|
|
|
diff --git a/rust2rpm/templates/main.spec b/rust2rpm/templates/main.spec
|
|
|
|
index 7dbcc3f..0d9a80b 100644
|
|
|
|
--- a/rust2rpm/templates/main.spec
|
|
|
|
+++ b/rust2rpm/templates/main.spec
|
|
|
|
@@ -48,82 +48,102 @@ Patch0: {{ patch_file }}
|
|
|
|
ExclusiveArch: %{rust_arches}
|
|
|
|
|
|
|
|
BuildRequires: rust-packaging
|
|
|
|
-{% if include_build_requires %}
|
|
|
|
-{% if md.requires|length > 0 %}
|
|
|
|
-# [dependencies]
|
|
|
|
-{% for req in md.requires|sort(attribute="name") %}
|
|
|
|
+{# We will put all non-optional and optional dependencies until
|
|
|
|
+ https://github.com/rust-lang/cargo/issues/5133
|
|
|
|
+ is solved
|
|
|
|
+{% set buildrequires = normalize_deps(md.requires("default", resolve=True))|sort %}
|
|
|
|
+#}
|
|
|
|
+{% set buildrequires = normalize_deps(md.all_dependencies)|sort %}
|
|
|
|
+{% for req in buildrequires %}
|
|
|
|
BuildRequires: {{ req }}
|
|
|
|
{% endfor %}
|
|
|
|
-{% endif %}
|
|
|
|
-{% if md.build_requires|length > 0 %}
|
|
|
|
-# [build-dependencies]
|
|
|
|
-{% for req in md.build_requires|sort(attribute="name") %}
|
|
|
|
-BuildRequires: {{ req }}
|
|
|
|
-{% endfor %}
|
|
|
|
-{% endif %}
|
|
|
|
-{% if md.test_requires|length > 0 %}
|
|
|
|
+{% set testrequires = normalize_deps(md.dev_dependencies)|sort %}
|
|
|
|
+{% if testrequires|length > 0 %}
|
|
|
|
%if %{with check}
|
|
|
|
-# [dev-dependencies]
|
|
|
|
-{% for req in md.test_requires|sort(attribute="name") %}
|
|
|
|
+ {% for req in testrequires %}
|
|
|
|
BuildRequires: {{ req }}
|
|
|
|
-{% endfor %}
|
|
|
|
+ {% endfor %}
|
|
|
|
%endif
|
|
|
|
{% endif %}
|
|
|
|
-{% endif %}
|
|
|
|
|
|
|
|
-%description
|
|
|
|
+%global _description \
|
|
|
|
+{% if md.description is none %}
|
|
|
|
%{summary}.
|
|
|
|
+{% else %}
|
|
|
|
+{{ md.description|wordwrap(wrapstring="\\\n")|trim }}
|
|
|
|
+{% endif %}
|
|
|
|
+
|
|
|
|
+%description %{_description}
|
|
|
|
|
|
|
|
{% if include_main %}
|
|
|
|
%package -n %{crate}
|
|
|
|
Summary: %{summary}
|
|
|
|
-{% if rust_group is defined %}
|
|
|
|
+ {% if rust_group is defined %}
|
|
|
|
Group: # FIXME
|
|
|
|
-{% endif %}
|
|
|
|
+ {% endif %}
|
|
|
|
|
|
|
|
%description -n %{crate}
|
|
|
|
%{summary}.
|
|
|
|
|
|
|
|
-{% endif %}
|
|
|
|
+%files -n %{crate}
|
|
|
|
+ {% if md.license_file is not none %}
|
|
|
|
+%license {{ md.license_file }}
|
|
|
|
+ {% endif %}
|
|
|
|
+ {% if md.readme is not none %}
|
|
|
|
+%doc {{ md.readme }}
|
|
|
|
+ {% endif %}
|
|
|
|
+ {% for bin in bins %}
|
|
|
|
+%{_bindir}/{{ bin.name }}
|
|
|
|
+ {% endfor %}
|
|
|
|
+
|
|
|
|
+{% endif -%}
|
|
|
|
+
|
|
|
|
{% if include_devel %}
|
|
|
|
-%package devel
|
|
|
|
+ {% set features = md.dependencies.keys()|list %}
|
|
|
|
+ {% do features.remove(None) %}
|
|
|
|
+ {% do features.remove("default") %}
|
|
|
|
+ {% set features = features|sort %}
|
|
|
|
+ {% do features.insert(0, None) %}
|
|
|
|
+ {% do features.insert(1, "default") %}
|
|
|
|
+ {% for feature in features %}
|
|
|
|
+ {% set pkg = "-n %%{name}+%s-devel"|format(feature) if feature is not none else " devel" %}
|
|
|
|
+%package {{ pkg }}
|
|
|
|
Summary: %{summary}
|
|
|
|
-{% if rust_group is defined %}
|
|
|
|
+ {% if rust_group is defined %}
|
|
|
|
Group: {{ rust_group }}
|
|
|
|
-{% endif %}
|
|
|
|
+ {% endif %}
|
|
|
|
BuildArch: noarch
|
|
|
|
-{% if include_provides %}
|
|
|
|
-{% for prv in md.provides %}
|
|
|
|
-Provides: {{ prv }}
|
|
|
|
-{% endfor %}
|
|
|
|
-{% endif %}
|
|
|
|
-{% if include_requires %}
|
|
|
|
+ {% if include_provides %}
|
|
|
|
+Provides: {{ md.provides(feature) }}
|
|
|
|
+ {% endif %}
|
|
|
|
+ {% if include_requires %}
|
|
|
|
Requires: cargo
|
|
|
|
-{% if md.requires|length > 0 %}
|
|
|
|
-# [dependencies]
|
|
|
|
-{% for req in md.requires|sort(attribute="name") %}
|
|
|
|
-Requires: {{ req }}
|
|
|
|
-{% endfor %}
|
|
|
|
-{% endif %}
|
|
|
|
-{% if md.build_requires|length > 0 %}
|
|
|
|
-# [build-dependencies]
|
|
|
|
-{% for req in md.build_requires|sort(attribute="name") %}
|
|
|
|
+ {% for req in md.requires(feature)|map("string")|sort %}
|
|
|
|
Requires: {{ req }}
|
|
|
|
-{% endfor %}
|
|
|
|
-{% endif %}
|
|
|
|
-{% endif %}
|
|
|
|
+ {% endfor %}
|
|
|
|
+ {% endif %}
|
|
|
|
|
|
|
|
-%description devel
|
|
|
|
-{% if md.description is none %}
|
|
|
|
-%{summary}.
|
|
|
|
-{% else %}
|
|
|
|
-{{ md.description|wordwrap|trim }}
|
|
|
|
-{% endif %}
|
|
|
|
+%description {{ pkg }} %{_description}
|
|
|
|
|
|
|
|
This package contains library source intended for building other packages
|
|
|
|
-which use %{crate} from crates.io.
|
|
|
|
+which use {% if feature is not none %}"{{ feature }}" feature of {% endif %}"%{crate}" crate.
|
|
|
|
+
|
|
|
|
+%files {{ pkg }}
|
|
|
|
+ {% if feature is none %}
|
|
|
|
+ {% if md.license_file is not none %}
|
|
|
|
+%license {{ md.license_file }}
|
|
|
|
+ {% endif %}
|
|
|
|
+ {% if md.readme is not none %}
|
|
|
|
+%doc {{ md.readme }}
|
|
|
|
+ {% endif %}
|
|
|
|
+%{cargo_registry}/%{crate}-%{version}/
|
|
|
|
+ {% else %}
|
|
|
|
+%ghost %{cargo_registry}/%{crate}-%{version}/Cargo.toml
|
|
|
|
+ {% endif %}
|
|
|
|
+
|
|
|
|
+ {% endfor %}
|
|
|
|
+{% endif -%}
|
|
|
|
|
|
|
|
-{% endif %}
|
|
|
|
%prep
|
|
|
|
{% if md.name != crate %}
|
|
|
|
%autosetup -n %{real_crate}-%{version} -p1
|
|
|
|
@@ -143,29 +163,5 @@ which use %{crate} from crates.io.
|
|
|
|
%cargo_test
|
|
|
|
%endif
|
|
|
|
|
|
|
|
-{% if include_main %}
|
|
|
|
-%files -n %{crate}
|
|
|
|
-{% if md.license_file is not none %}
|
|
|
|
-%license {{ md.license_file }}
|
|
|
|
-{% endif %}
|
|
|
|
-{% if md.readme is not none %}
|
|
|
|
-%doc {{ md.readme }}
|
|
|
|
-{% endif %}
|
|
|
|
-{% for bin in bins %}
|
|
|
|
-%{_bindir}/{{ bin.name }}
|
|
|
|
-{% endfor %}
|
|
|
|
-
|
|
|
|
-{% endif %}
|
|
|
|
-{% if include_devel %}
|
|
|
|
-%files devel
|
|
|
|
-{% if md.license_file is not none %}
|
|
|
|
-%license {{ md.license_file }}
|
|
|
|
-{% endif %}
|
|
|
|
-{% if md.readme is not none %}
|
|
|
|
-%doc {{ md.readme }}
|
|
|
|
-{% endif %}
|
|
|
|
-%{cargo_registry}/%{crate}-%{version}/
|
|
|
|
-
|
|
|
|
-{% endif %}
|
|
|
|
%changelog
|
|
|
|
{% include target ~ "-changelog.spec.inc" %}
|
|
|
|
diff --git a/test.py b/test.py
|
|
|
|
index b856fdd..30263b4 100644
|
|
|
|
--- a/test.py
|
|
|
|
+++ b/test.py
|
|
|
|
@@ -1,318 +1,43 @@
|
|
|
|
-import os
|
|
|
|
-import shutil
|
|
|
|
-import subprocess
|
|
|
|
-import sys
|
|
|
|
-import tempfile
|
|
|
|
-import textwrap
|
|
|
|
-
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
import rust2rpm
|
|
|
|
|
|
|
|
-DUMMY_LIB = """
|
|
|
|
-pub fn say_hello() {
|
|
|
|
- println!("Hello, World!");
|
|
|
|
-}
|
|
|
|
-"""
|
|
|
|
-DEPGEN = os.path.join(os.path.dirname(__file__), "cargodeps.py")
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-@pytest.mark.parametrize("req, features, rpmdep", [
|
|
|
|
- ("=1.0.0", [],
|
|
|
|
- "crate(test) = 1.0.0"),
|
|
|
|
- ("=1.0.0", ["feature"],
|
|
|
|
- "(crate(test) = 1.0.0 with crate(test/feature))"),
|
|
|
|
- (">=1.0.0,<2.0.0", [],
|
|
|
|
+@pytest.mark.parametrize("req, rpmdep", [
|
|
|
|
+ ("^1.2.3",
|
|
|
|
+ "(crate(test) >= 1.2.3 with crate(test) < 2.0.0)"),
|
|
|
|
+ ("^1.2",
|
|
|
|
+ "(crate(test) >= 1.2.0 with crate(test) < 2.0.0)"),
|
|
|
|
+ ("^1",
|
|
|
|
"(crate(test) >= 1.0.0 with crate(test) < 2.0.0)"),
|
|
|
|
- (">=1.0.0,<2.0.0", ["feature"],
|
|
|
|
- "((crate(test) >= 1.0.0 with crate(test) < 2.0.0) with crate(test/feature))"),
|
|
|
|
+ ("^0.2.3",
|
|
|
|
+ "(crate(test) >= 0.2.3 with crate(test) < 0.3.0)"),
|
|
|
|
+ ("^0.2",
|
|
|
|
+ "(crate(test) >= 0.2.0 with crate(test) < 0.3.0)"),
|
|
|
|
+ ("^0.0.3",
|
|
|
|
+ "(crate(test) >= 0.0.3 with crate(test) < 0.0.4)"),
|
|
|
|
+ ("^0.0",
|
|
|
|
+ "(crate(test) >= 0.0.0 with crate(test) < 0.1.0)"),
|
|
|
|
+ ("^0",
|
|
|
|
+ "(crate(test) >= 0.0.0 with crate(test) < 1.0.0)"),
|
|
|
|
+ ("~1.2.3",
|
|
|
|
+ "(crate(test) >= 1.2.3 with crate(test) < 1.3.0)"),
|
|
|
|
+ ("~1.2",
|
|
|
|
+ "(crate(test) >= 1.2.0 with crate(test) < 1.3.0)"),
|
|
|
|
+ ("~1",
|
|
|
|
+ "(crate(test) >= 1.0.0 with crate(test) < 2.0.0)"),
|
|
|
|
+ ("*",
|
|
|
|
+ "crate(test)"),
|
|
|
|
+ (">= 1.2.0",
|
|
|
|
+ "crate(test) >= 1.2.0"),
|
|
|
|
+ ("> 1",
|
|
|
|
+ "crate(test) > 1.0.0"),
|
|
|
|
+ ("< 2",
|
|
|
|
+ "crate(test) < 2.0.0"),
|
|
|
|
+ ("= 1.2.3",
|
|
|
|
+ "crate(test) = 1.2.3"),
|
|
|
|
+ (">= 1.2, < 1.5",
|
|
|
|
+ "(crate(test) >= 1.2.0 with crate(test) < 1.5.0)"),
|
|
|
|
])
|
|
|
|
-def test_dependency(req, features, rpmdep):
|
|
|
|
- dep = rust2rpm.Dependency("test", req, features)
|
|
|
|
+def test_dependency(req, rpmdep):
|
|
|
|
+ dep = rust2rpm.Dependency("test", req)
|
|
|
|
assert str(dep) == rpmdep
|
|
|
|
-
|
|
|
|
-@pytest.fixture
|
|
|
|
-def cargo_toml(request):
|
|
|
|
- def make_cargo_toml(contents):
|
|
|
|
- toml = os.path.join(tmpdir, "Cargo.toml")
|
|
|
|
- with open(toml, "w") as fobj:
|
|
|
|
- fobj.write(textwrap.dedent(contents))
|
|
|
|
- return toml
|
|
|
|
-
|
|
|
|
- tmpdir = tempfile.mkdtemp(prefix="cargo-deps-")
|
|
|
|
- srcdir = os.path.join(tmpdir, "src")
|
|
|
|
- os.mkdir(srcdir)
|
|
|
|
- with open(os.path.join(srcdir, "lib.rs"), "w") as fobj:
|
|
|
|
- fobj.write(DUMMY_LIB)
|
|
|
|
-
|
|
|
|
- def finalize():
|
|
|
|
- shutil.rmtree(tmpdir)
|
|
|
|
- request.addfinalizer(finalize)
|
|
|
|
-
|
|
|
|
- return make_cargo_toml
|
|
|
|
-
|
|
|
|
-@pytest.mark.parametrize("toml, provides, requires", [
|
|
|
|
-
|
|
|
|
- # Basic provides
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- []),
|
|
|
|
-
|
|
|
|
- # Basic provides for feature
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "1.2.3"
|
|
|
|
-
|
|
|
|
- [features]
|
|
|
|
- color = []
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 1.2.3",
|
|
|
|
- "crate(hello/color) = 1.2.3"],
|
|
|
|
- []),
|
|
|
|
-
|
|
|
|
- # Provides for optional dependencies
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "1.2.3"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- non_optional = "1"
|
|
|
|
- serde = { version = "1", optional = true }
|
|
|
|
- rand = { version = "0.4", optional = true }
|
|
|
|
-
|
|
|
|
- [features]
|
|
|
|
- std = []
|
|
|
|
- v1 = ["rand"]
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 1.2.3",
|
|
|
|
- "crate(hello/rand) = 1.2.3",
|
|
|
|
- "crate(hello/serde) = 1.2.3",
|
|
|
|
- "crate(hello/std) = 1.2.3",
|
|
|
|
- "crate(hello/v1) = 1.2.3"],
|
|
|
|
- ["(crate(non_optional) >= 1.0.0 with crate(non_optional) < 2.0.0)",
|
|
|
|
- "(crate(rand) >= 0.4.0 with crate(rand) < 0.5.0)",
|
|
|
|
- "(crate(serde) >= 1.0.0 with crate(serde) < 2.0.0)"]),
|
|
|
|
-
|
|
|
|
- # Caret requirements
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "^0"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 0.0.0 with crate(libc) < 1.0.0)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "^0.0"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 0.0.0 with crate(libc) < 0.1.0)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "^0.0.3"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 0.0.3 with crate(libc) < 0.0.4)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "^0.2.3"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 0.2.3 with crate(libc) < 0.3.0)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "^1"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 1.0.0 with crate(libc) < 2.0.0)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "^1.2"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 1.2.0 with crate(libc) < 2.0.0)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "^1.2.3"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 1.2.3 with crate(libc) < 2.0.0)"]),
|
|
|
|
-
|
|
|
|
- # Tilde requirements
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "~1"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 1.0.0 with crate(libc) < 2.0.0)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "~1.2"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 1.2.0 with crate(libc) < 1.3.0)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "~1.2.3"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 1.2.3 with crate(libc) < 1.3.0)"]),
|
|
|
|
-
|
|
|
|
- # Wildcard requirements
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "*"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["crate(libc)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "1.*"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 1.0.0 with crate(libc) < 2.0.0)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "1.2.*"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 1.2.0 with crate(libc) < 1.3.0)"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "1.*.*"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 1.0.0 with crate(libc) < 2.0.0)"]),
|
|
|
|
-
|
|
|
|
- # Inequality requirements
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = ">= 1.2.0"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["crate(libc) >= 1.2.0"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "> 1"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["crate(libc) > 1.0.0"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "< 2"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["crate(libc) < 2.0.0"]),
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = "= 1.2.3"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["crate(libc) = 1.2.3"]),
|
|
|
|
-
|
|
|
|
- # Multiple requirements
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- libc = ">= 1.2, < 1.5"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0"],
|
|
|
|
- ["(crate(libc) >= 1.2.0 with crate(libc) < 1.5.0)"]),
|
|
|
|
-
|
|
|
|
- # Pre-release requirements
|
|
|
|
- ("""
|
|
|
|
- [package]
|
|
|
|
- name = "hello"
|
|
|
|
- version = "0.0.0-alpha"
|
|
|
|
-
|
|
|
|
- [dependencies]
|
|
|
|
- foo-bar = "1.2.3-beta"
|
|
|
|
- """,
|
|
|
|
- ["crate(hello) = 0.0.0~alpha"],
|
|
|
|
- ["(crate(foo-bar) >= 1.2.3~beta with crate(foo-bar) < 1.2.3)"]),
|
|
|
|
-
|
|
|
|
-])
|
|
|
|
-def test_depgen(toml, provides, requires, cargo_toml):
|
|
|
|
- md = rust2rpm.Metadata.from_file(cargo_toml(toml))
|
|
|
|
- assert [str(x) for x in md.provides] == provides
|
|
|
|
- assert [str(x) for x in md.requires] == requires
|
|
|
|
--
|
|
|
|
2.20.0.rc2
|
|
|
|
|