rust2rpm/rust2rpm.py
Igor Gnatenko c946648932 generate BuildRequires/BuildConflicts
Closes: https://pagure.io/fedora-rust/rust2rpm/issue/8
Signed-off-by: Igor Gnatenko <ignatenkobrain@fedoraproject.org>
2017-02-03 10:05:26 +01:00

150 lines
4.4 KiB
Python

import argparse
import os
import tarfile
import tempfile
import subprocess
import sys
import jinja2
import requests
import cargodeps
API_URL = "https://crates.io/api/v1/"
TEMPLATE = """# Generated by rust2rpm
%bcond_without check
%global crate {{ name }}
Name: rust-%{crate}
Version: {{ version }}
Release: 1%{?dist}
Summary: # FIXME
License: # FIXME
URL: https://crates.io/crates/{{ name }}
Source0: https://crates.io/api/v1/crates/%{crate}/%{version}/download#/%{crate}-%{version}.crate
ExclusiveArch: %{rust_arches}
BuildRequires: rust
BuildRequires: cargo
{% for br in buildrequires %}
BuildRequires: {{ br }}
{% endfor %}
{% for bc in buildconflicts %}
BuildConflicts: {{ bc }}
{% endfor %}
{% if testrequires|length > 0 %}
%if %{with check}
{% for tr in testrequires %}
BuildRequires: {{ tr }}
{% endfor %}
{% for tc in testconflicts %}
BuildConflicts: {{ tc }}
{% endfor %}
%endif
{% endif %}
%description
%{summary}.
%package devel
Summary: %{summary}
BuildArch: noarch
{% for prov in provides %}
Provides: {{ prov }}
{% endfor %}
{% for req in requires %}
Requires: {{ req }}
{% endfor %}
{% for con in conflicts %}
Conflicts: {{ con }}
{% endfor %}
%description devel
%{summary}.
%prep
%autosetup -n %{crate}-%{version}
%cargo_prep
%install
%cargo_install_crate %{crate}-%{version}
%if %{with check}
%check
%cargo_test
%endif
%files devel
%license # FIXME
%{cargo_registry}/%{crate}-%{version}/
%changelog
"""
JINJA_ENV = jinja2.Environment(undefined=jinja2.StrictUndefined,
trim_blocks=True, lstrip_blocks=True)
def run_depgen(*params):
cmd = [sys.executable, cargodeps.__file__, *params]
out = subprocess.check_output(cmd, universal_newlines=True)
return out.split("\n")[:-1]
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--target", choices=("epel-7", "fedora-26"), required=True,
help="Distribution target")
parser.add_argument("crate", help="crates.io name")
parser.add_argument("version", nargs="?", help="crates.io version")
args = parser.parse_args()
if args.version is None:
# Now we need to get latest version
url = requests.compat.urljoin(API_URL, "crates/{}/versions".format(args.crate))
req = requests.get(url)
req.raise_for_status()
args.version = req.json()["versions"][0]["num"]
cratef = "{}-{}.crate".format(args.crate, args.version)
if not os.path.isfile(cratef):
url = requests.compat.urljoin(API_URL, "crates/{}/{}/download#".format(args.crate, args.version))
req = requests.get(url, stream=True)
req.raise_for_status()
with open(cratef, "wb") as f:
# FIXME: should we use req.iter_content() and specify custom chunk size?
for chunk in req:
f.write(chunk)
files = []
with tempfile.TemporaryDirectory() as tmpdir:
target_dir = "{}/".format(tmpdir)
with tarfile.open(cratef, "r") as archive:
for n in archive.getnames():
if not os.path.abspath(os.path.join(target_dir, n)).startswith(target_dir):
raise Exception("Unsafe filenames!")
archive.extractall(target_dir)
toml = "{}/{}-{}/Cargo.toml".format(tmpdir, args.crate, args.version)
assert os.path.isfile(toml)
buildrequires = run_depgen("--build-requires", toml)
buildconflicts = run_depgen("--build-conflicts", toml)
testrequires = run_depgen("--test-requires", toml)
testconflicts = run_depgen("--test-conflicts", toml)
if args.target == "fedora-26":
# Those are automatically added by dependency generator
provides = []
requires = []
conflicts = []
else:
provides = run_depgen("--provides", toml)
requires = run_depgen("--requires", toml)
conflicts = run_depgen("--conflicts", toml)
template = JINJA_ENV.from_string(TEMPLATE)
print(template.render(name=args.crate, version=args.version,
provides=provides,
buildrequires=buildrequires, buildconflicts=buildconflicts,
testrequires=testrequires, testconflicts=testconflicts,
requires=requires, conflicts=conflicts))