rust2rpm/cargodeps.py
Igor Gnatenko cd9f892d51 rename cargo-deps.py to cargodeps.py
To allow importing from outside. import cargo-deps doesn't really work.

Signed-off-by: Igor Gnatenko <ignatenkobrain@fedoraproject.org>
2017-01-30 23:21:21 +01:00

96 lines
3.7 KiB
Python
Executable file

#!/usr/bin/python
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import json
import subprocess
import sys
import semantic_version as semver
REQ_TO_CON = {">": "<=",
"<": ">=",
">=": "<",
"<=": ">"}
def get_metadata(path):
# --no-deps is to disable recursive scanning of deps
metadata = subprocess.check_output(["cargo", "metadata", "--no-deps",
"--manifest-path={}".format(path)])
return json.loads(metadata)["packages"][0]
def parse_req(s):
if "*" in s:
raise NotImplementedError("https://github.com/rbarrois/python-semanticversion/issues/51")
spec = semver.Spec(s.replace(" ", ""))
specs = spec.specs
if len(specs) == 1:
req = specs[0]
if req.kind in (req.KIND_CARET, req.KIND_TILDE):
ver = req.spec
lower = semver.Version.coerce(str(ver))
if 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()
else:
upper = ver.next_major()
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
return (semver.Spec(">={}".format(lower)).specs[0],
semver.Spec("<{}".format(upper)).specs[0])
else:
return (req, None)
elif len(specs) == 2:
return (specs[0], specs[1])
else:
# it's something uber-complicated
raise NotImplementedError("More than two ranges are unsupported, probably something is wrong with metadata")
assert False
def print_dep(name, spec, kind="=", feature=None):
f_part = "/{}".format(feature) if feature is not None else ""
print("crate({}{}) {} {}".format(name, f_part, kind.replace("==", "="), spec))
if __name__ == "__main__":
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
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("-C", "--conflicts", action="store_true", help="Print Conflicts")
parser.add_argument("file", nargs="*", help="Path(s) to Cargo.toml")
args = parser.parse_args()
files = args.file or sys.stdin.readlines()
for f in files:
f = f.rstrip()
md = get_metadata(f)
if args.provides:
print_dep(md["name"], md["version"])
for feature in md["features"]:
print_dep(md["name"], md["version"], feature=feature)
if args.requires or args.conflicts:
for dep in md["dependencies"]:
if dep["kind"] is not None:
# kind: build -> build dependencies
# kind: dev -> test dependencies
continue
req, con = parse_req(dep["req"])
assert req is not None
for feature in dep["features"] or [None]:
if args.requires:
print_dep(dep["name"], req.spec, req.kind, feature=feature)
if args.conflicts and con is not None:
print_dep(dep["name"], con.spec, REQ_TO_CON[con.kind], feature=feature)