2017-01-30 23:44:25 +00:00
|
|
|
import argparse
|
2018-01-08 18:40:19 +00:00
|
|
|
import configparser
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
import contextlib
|
2017-02-17 16:30:45 +00:00
|
|
|
from datetime import datetime, timezone
|
|
|
|
import difflib
|
2018-01-08 18:40:19 +00:00
|
|
|
import itertools
|
2017-01-30 23:44:25 +00:00
|
|
|
import os
|
2018-01-08 18:40:19 +00:00
|
|
|
import shlex
|
2017-03-06 15:48:19 +00:00
|
|
|
import shutil
|
2018-08-16 14:09:15 +00:00
|
|
|
import sys
|
2017-01-30 23:44:25 +00:00
|
|
|
import tarfile
|
|
|
|
import tempfile
|
2017-03-06 15:48:19 +00:00
|
|
|
import time
|
2017-01-30 23:44:25 +00:00
|
|
|
import subprocess
|
|
|
|
|
|
|
|
import jinja2
|
|
|
|
import requests
|
2017-02-05 13:20:55 +00:00
|
|
|
import tqdm
|
2017-01-30 23:44:25 +00:00
|
|
|
|
2018-08-14 09:54:33 +00:00
|
|
|
from . import Metadata, licensing
|
2018-10-26 09:20:13 +00:00
|
|
|
from .metadata import normalize_deps
|
2017-01-30 23:44:25 +00:00
|
|
|
|
2017-02-17 20:09:14 +00:00
|
|
|
DEFAULT_EDITOR = "vi"
|
2017-02-05 12:56:50 +00:00
|
|
|
XDG_CACHE_HOME = os.getenv("XDG_CACHE_HOME", os.path.expanduser("~/.cache"))
|
|
|
|
CACHEDIR = os.path.join(XDG_CACHE_HOME, "rust2rpm")
|
2017-01-30 23:44:25 +00:00
|
|
|
API_URL = "https://crates.io/api/v1/"
|
2017-12-29 15:21:01 +00:00
|
|
|
JINJA_ENV = jinja2.Environment(loader=jinja2.ChoiceLoader([
|
2018-10-26 09:20:13 +00:00
|
|
|
jinja2.FileSystemLoader(["/"]),
|
|
|
|
jinja2.PackageLoader("rust2rpm", "templates"),
|
|
|
|
]),
|
|
|
|
extensions=["jinja2.ext.do"],
|
|
|
|
trim_blocks=True,
|
|
|
|
lstrip_blocks=True)
|
2017-01-30 23:44:25 +00:00
|
|
|
|
2018-01-08 18:40:19 +00:00
|
|
|
def get_default_target():
|
|
|
|
# TODO: add fallback for /usr/lib/os-release
|
2017-12-29 15:45:53 +00:00
|
|
|
with open("/etc/os-release") as os_release_file:
|
2018-01-08 18:40:19 +00:00
|
|
|
conf = configparser.ConfigParser()
|
|
|
|
conf.read_file(itertools.chain(["[os-release]"], os_release_file))
|
|
|
|
os_release = conf["os-release"]
|
|
|
|
os_id = os_release.get("ID")
|
|
|
|
os_like = os_release.get("ID_LIKE")
|
|
|
|
if os_like is not None:
|
|
|
|
os_like = shlex.split(os_like)
|
|
|
|
else:
|
|
|
|
os_like = []
|
2017-12-29 15:45:53 +00:00
|
|
|
|
|
|
|
# Order matters here!
|
2018-01-08 18:40:19 +00:00
|
|
|
if os_id == "mageia" or ("mageia" in os_like):
|
2017-12-29 15:45:53 +00:00
|
|
|
return "mageia"
|
2018-01-08 18:40:19 +00:00
|
|
|
elif os_id == "fedora" or ("fedora" in os_like):
|
2017-12-29 15:45:53 +00:00
|
|
|
return "fedora"
|
2018-01-08 18:40:19 +00:00
|
|
|
elif "suse" in os_like:
|
2017-12-29 15:45:53 +00:00
|
|
|
return "opensuse"
|
|
|
|
else:
|
|
|
|
return "plain"
|
|
|
|
|
2017-02-17 20:09:14 +00:00
|
|
|
def detect_editor():
|
|
|
|
terminal = os.getenv("TERM")
|
|
|
|
terminal_is_dumb = terminal is None or terminal == "dumb"
|
|
|
|
editor = None
|
|
|
|
if not terminal_is_dumb:
|
|
|
|
editor = os.getenv("VISUAL")
|
|
|
|
if editor is None:
|
|
|
|
editor = os.getenv("EDITOR")
|
|
|
|
if editor is None:
|
|
|
|
if terminal_is_dumb:
|
|
|
|
raise Exception("Terminal is dumb, but EDITOR unset")
|
|
|
|
else:
|
|
|
|
editor = DEFAULT_EDITOR
|
|
|
|
return editor
|
|
|
|
|
2017-03-06 15:48:19 +00:00
|
|
|
def detect_packager():
|
|
|
|
rpmdev_packager = shutil.which("rpmdev-packager")
|
|
|
|
if rpmdev_packager is not None:
|
|
|
|
return subprocess.check_output(rpmdev_packager, universal_newlines=True).strip()
|
|
|
|
|
|
|
|
git = shutil.which("git")
|
|
|
|
if git is not None:
|
|
|
|
name = subprocess.check_output([git, "config", "user.name"], universal_newlines=True).strip()
|
|
|
|
email = subprocess.check_output([git, "config", "user.email"], universal_newlines=True).strip()
|
2018-10-31 16:00:58 +00:00
|
|
|
return f"{name} <{email}>"
|
2017-03-06 15:48:19 +00:00
|
|
|
|
|
|
|
return None
|
|
|
|
|
2017-02-17 16:30:45 +00:00
|
|
|
def file_mtime(path):
|
|
|
|
t = datetime.fromtimestamp(os.stat(path).st_mtime, timezone.utc)
|
|
|
|
return t.astimezone().isoformat()
|
|
|
|
|
2018-08-17 08:03:48 +00:00
|
|
|
@contextlib.contextmanager
|
|
|
|
def remove_on_error(path):
|
|
|
|
try:
|
|
|
|
yield
|
|
|
|
except: # this is supposed to include ^C
|
|
|
|
os.unlink(path)
|
|
|
|
raise
|
|
|
|
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
def local_toml(toml, version):
|
|
|
|
if os.path.isdir(toml):
|
2018-08-14 06:59:21 +00:00
|
|
|
toml = os.path.join(toml, "Cargo.toml")
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
|
|
|
|
return toml, None, version
|
|
|
|
|
|
|
|
def local_crate(crate, version):
|
2018-08-14 06:59:21 +00:00
|
|
|
cratename, version = os.path.basename(crate)[:-6].rsplit("-", 1)
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
return crate, cratename, version
|
|
|
|
|
2018-04-17 11:54:41 +00:00
|
|
|
def download(crate, version):
|
|
|
|
if version is None:
|
2017-01-30 23:44:25 +00:00
|
|
|
# Now we need to get latest version
|
2018-10-31 16:00:58 +00:00
|
|
|
url = requests.compat.urljoin(API_URL, f"crates/{crate}/versions")
|
2017-01-30 23:44:25 +00:00
|
|
|
req = requests.get(url)
|
|
|
|
req.raise_for_status()
|
2017-11-13 20:36:18 +00:00
|
|
|
versions = req.json()["versions"]
|
2018-04-17 11:54:41 +00:00
|
|
|
version = next(version["num"] for version in versions if not version["yanked"])
|
2017-01-30 23:44:25 +00:00
|
|
|
|
2018-08-15 16:47:05 +00:00
|
|
|
os.makedirs(CACHEDIR, exist_ok=True)
|
2018-10-31 16:00:58 +00:00
|
|
|
cratef_base = f"{crate}-{version}.crate"
|
2017-02-05 13:20:55 +00:00
|
|
|
cratef = os.path.join(CACHEDIR, cratef_base)
|
2017-01-30 23:44:25 +00:00
|
|
|
if not os.path.isfile(cratef):
|
2018-10-31 16:00:58 +00:00
|
|
|
url = requests.compat.urljoin(API_URL, f"crates/{crate}/{version}/download#")
|
2017-01-30 23:44:25 +00:00
|
|
|
req = requests.get(url, stream=True)
|
|
|
|
req.raise_for_status()
|
2017-02-05 13:20:55 +00:00
|
|
|
total = int(req.headers["Content-Length"])
|
2018-08-17 08:03:48 +00:00
|
|
|
with remove_on_error(cratef), \
|
|
|
|
open(cratef, "wb") as f:
|
2018-10-31 16:00:58 +00:00
|
|
|
for chunk in tqdm.tqdm(req.iter_content(), f"Downloading {cratef_base}".format(cratef_base),
|
2017-02-05 13:20:55 +00:00
|
|
|
total=total, unit="B", unit_scale=True):
|
2017-01-30 23:44:25 +00:00
|
|
|
f.write(chunk)
|
2018-04-17 11:54:41 +00:00
|
|
|
return cratef, crate, version
|
|
|
|
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
@contextlib.contextmanager
|
|
|
|
def toml_from_crate(cratef, crate, version):
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
2018-10-31 16:00:58 +00:00
|
|
|
target_dir = f"{tmpdir}/"
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
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)
|
2018-10-31 16:00:58 +00:00
|
|
|
toml_relpath = f"{crate}-{version}/Cargo.toml"
|
|
|
|
toml = f"{tmpdir}/{toml_relpath}"
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
if not os.path.isfile(toml):
|
2018-08-14 06:59:21 +00:00
|
|
|
raise IOError("crate does not contain Cargo.toml file")
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
yield toml
|
|
|
|
|
2018-08-13 15:52:53 +00:00
|
|
|
def make_patch(toml, enabled=True, tmpfile=False):
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
if not enabled:
|
|
|
|
return []
|
|
|
|
|
|
|
|
editor = detect_editor()
|
|
|
|
|
|
|
|
mtime_before = file_mtime(toml)
|
|
|
|
toml_before = open(toml).readlines()
|
2018-08-13 15:52:53 +00:00
|
|
|
|
|
|
|
# When we are editing a git checkout, we should not modify the real file.
|
|
|
|
# When we are editing an unpacked crate, we are free to edit anything.
|
|
|
|
# Let's keep the file name as close as possible to make editing easier.
|
|
|
|
if tmpfile:
|
2018-08-14 06:59:21 +00:00
|
|
|
tmpfile = tempfile.NamedTemporaryFile("w+t", dir=os.path.dirname(toml),
|
|
|
|
prefix="Cargo.", suffix=".toml")
|
2018-08-13 15:52:53 +00:00
|
|
|
tmpfile.writelines(toml_before)
|
|
|
|
tmpfile.flush()
|
|
|
|
fname = tmpfile.name
|
|
|
|
else:
|
|
|
|
fname = toml
|
|
|
|
subprocess.check_call([editor, fname])
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
mtime_after = file_mtime(toml)
|
2018-08-13 15:52:53 +00:00
|
|
|
toml_after = open(fname).readlines()
|
2018-08-14 06:59:21 +00:00
|
|
|
toml_relpath = "/".join(toml.split("/")[-2:])
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
diff = list(difflib.unified_diff(toml_before, toml_after,
|
|
|
|
fromfile=toml_relpath, tofile=toml_relpath,
|
|
|
|
fromfiledate=mtime_before, tofiledate=mtime_after))
|
|
|
|
return diff
|
|
|
|
|
|
|
|
def _is_path(path):
|
2018-08-14 06:59:21 +00:00
|
|
|
return "/" in path or path in {".", ".."}
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
|
2018-08-15 17:57:08 +00:00
|
|
|
def make_diff_metadata(crate, version, patch=False, store=False):
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
if _is_path(crate):
|
|
|
|
# Only things that look like a paths are considered local arguments
|
2018-08-14 06:59:21 +00:00
|
|
|
if crate.endswith(".crate"):
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
cratef, crate, version = local_crate(crate, version)
|
|
|
|
else:
|
2018-08-17 08:18:59 +00:00
|
|
|
if store:
|
|
|
|
raise ValueError('--store-crate can only be used for a crate')
|
|
|
|
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
toml, crate, version = local_toml(crate, version)
|
2018-08-13 15:52:53 +00:00
|
|
|
diff = make_patch(toml, enabled=patch, tmpfile=True)
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
metadata = Metadata.from_file(toml)
|
|
|
|
return metadata.name, diff, metadata
|
|
|
|
else:
|
|
|
|
cratef, crate, version = download(crate, version)
|
|
|
|
|
|
|
|
with toml_from_crate(cratef, crate, version) as toml:
|
|
|
|
diff = make_patch(toml, enabled=patch)
|
|
|
|
metadata = Metadata.from_file(toml)
|
2018-08-15 17:57:08 +00:00
|
|
|
if store:
|
2018-09-10 22:06:50 +00:00
|
|
|
shutil.copy2(cratef, os.path.join(os.getcwd(), f"{metadata.name}-{version}.crate"))
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
return crate, diff, metadata
|
2018-04-17 11:54:41 +00:00
|
|
|
|
2018-10-31 17:03:21 +00:00
|
|
|
def to_list(s):
|
|
|
|
if not s:
|
|
|
|
return []
|
|
|
|
return list(filter(None, (l.strip() for l in s.splitlines())))
|
|
|
|
|
2018-04-17 11:54:41 +00:00
|
|
|
def main():
|
2018-08-14 06:59:21 +00:00
|
|
|
parser = argparse.ArgumentParser("rust2rpm",
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
formatter_class=argparse.RawTextHelpFormatter)
|
2018-08-16 14:09:15 +00:00
|
|
|
parser.add_argument("--show-license-map", action="store_true",
|
|
|
|
help="Print license mappings and exit")
|
2018-11-11 16:06:27 +00:00
|
|
|
parser.add_argument("--no-auto-changelog-entry", action="store_true",
|
|
|
|
help="Do not generate a changelog entry")
|
2018-04-17 11:54:41 +00:00
|
|
|
parser.add_argument("-", "--stdout", action="store_true",
|
|
|
|
help="Print spec and patches into stdout")
|
|
|
|
parser.add_argument("-t", "--target", action="store",
|
|
|
|
choices=("plain", "fedora", "mageia", "opensuse"), default=get_default_target(),
|
|
|
|
help="Distribution target")
|
|
|
|
parser.add_argument("-p", "--patch", action="store_true",
|
|
|
|
help="Do initial patching of Cargo.toml")
|
2018-08-15 17:57:08 +00:00
|
|
|
parser.add_argument("-s", "--store-crate", action="store_true",
|
|
|
|
help="Store crate in current directory")
|
Allow generating the spec file from rust project checkout
This adds the possibility to generate the spec file from a rust project
checkout, by specifying either the toml file or just the directory name, without
having a crate at all. This is nice when developing local projects and tweaking
the metadata. The expected way to use this is 'rust2rpm .../project/', look at
the generated spec file, do fixes to source, regenerate spec file, etc.
$ rust2rpm -t fedora --stdout .
(when testing)
or
$ rust2rpm -t fedora /path/to/project
(in the dist-git directory)
Only args that contain "/" are considered local arguments. An special exception
is made for "." and "..", since that's likely to be a common use case and cannot
be mistaken for a remote crate name.
When --patch is used, the filename is changed from name-version-fix-metadata.diff
to name-fix-metadata.diff. This seems more useful, because after the crate
version is updated, the patch file would either stay the same or would just need
to be rebased, and it is not tied to the crate version.
2018-08-11 18:13:18 +00:00
|
|
|
parser.add_argument("crate", help="crates.io name\n"
|
|
|
|
"path/to/local.crate\n"
|
2018-08-16 14:09:15 +00:00
|
|
|
"path/to/project/",
|
|
|
|
nargs="?")
|
2018-04-17 11:54:41 +00:00
|
|
|
parser.add_argument("version", nargs="?", help="crates.io version")
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
2018-08-16 14:09:15 +00:00
|
|
|
if args.show_license_map:
|
|
|
|
licensing.dump_sdpx_to_fedora_map(sys.stdout)
|
|
|
|
return
|
|
|
|
|
|
|
|
if args.crate is None:
|
|
|
|
parser.error('required crate/path argument missing')
|
|
|
|
|
2018-08-15 17:57:08 +00:00
|
|
|
crate, diff, metadata = make_diff_metadata(args.crate, args.version,
|
|
|
|
patch=args.patch,
|
|
|
|
store=args.store_crate)
|
2017-01-30 23:44:25 +00:00
|
|
|
|
2018-10-26 09:20:13 +00:00
|
|
|
JINJA_ENV.globals["normalize_deps"] = normalize_deps
|
2018-10-31 17:03:21 +00:00
|
|
|
JINJA_ENV.globals["to_list"] = to_list
|
2017-12-29 15:21:01 +00:00
|
|
|
template = JINJA_ENV.get_template("main.spec")
|
2017-02-17 16:30:45 +00:00
|
|
|
|
|
|
|
if args.patch and len(diff) > 0:
|
2018-09-10 22:06:50 +00:00
|
|
|
patch_file = f"{metadata.name}-fix-metadata.diff"
|
2017-02-17 16:30:45 +00:00
|
|
|
else:
|
|
|
|
patch_file = None
|
|
|
|
|
2017-02-18 00:45:35 +00:00
|
|
|
kwargs = {}
|
2018-09-10 22:06:50 +00:00
|
|
|
kwargs["crate"] = crate
|
2017-12-29 15:21:01 +00:00
|
|
|
kwargs["target"] = args.target
|
2017-02-18 00:45:35 +00:00
|
|
|
bins = [tgt for tgt in metadata.targets if tgt.kind == "bin"]
|
2018-01-08 18:09:54 +00:00
|
|
|
libs = [tgt for tgt in metadata.targets if tgt.kind in ("lib", "rlib", "proc-macro")]
|
2017-02-18 00:45:35 +00:00
|
|
|
is_bin = len(bins) > 0
|
|
|
|
is_lib = len(libs) > 0
|
|
|
|
if is_bin:
|
|
|
|
kwargs["include_main"] = True
|
|
|
|
kwargs["bins"] = bins
|
|
|
|
elif is_lib:
|
|
|
|
kwargs["include_main"] = False
|
|
|
|
else:
|
|
|
|
raise ValueError("No bins and no libs")
|
2017-03-11 12:21:12 +00:00
|
|
|
kwargs["include_devel"] = is_lib
|
2017-02-18 00:45:35 +00:00
|
|
|
|
2018-11-11 16:06:27 +00:00
|
|
|
if args.no_auto_changelog_entry:
|
|
|
|
kwargs["auto_changelog_entry"] = False
|
|
|
|
else:
|
|
|
|
kwargs["auto_changelog_entry"] = True
|
|
|
|
|
2017-12-29 15:21:01 +00:00
|
|
|
if args.target in ("fedora", "mageia", "opensuse"):
|
2017-02-26 22:43:49 +00:00
|
|
|
kwargs["include_build_requires"] = True
|
|
|
|
kwargs["include_provides"] = False
|
|
|
|
kwargs["include_requires"] = False
|
|
|
|
elif args.target == "plain":
|
|
|
|
kwargs["include_build_requires"] = True
|
|
|
|
kwargs["include_provides"] = True
|
|
|
|
kwargs["include_requires"] = True
|
|
|
|
else:
|
2018-10-31 16:00:58 +00:00
|
|
|
assert False, f"Unknown target {args.target!r}"
|
2017-02-26 22:43:49 +00:00
|
|
|
|
2017-12-29 15:21:01 +00:00
|
|
|
if args.target == "mageia":
|
|
|
|
kwargs["pkg_release"] = "%mkrel 1"
|
|
|
|
kwargs["rust_group"] = "Development/Rust"
|
|
|
|
elif args.target == "opensuse":
|
|
|
|
kwargs["spec_copyright_year"] = time.strftime("%Y")
|
|
|
|
kwargs["pkg_release"] = "0"
|
|
|
|
kwargs["rust_group"] = "Development/Libraries/Rust"
|
|
|
|
else:
|
|
|
|
kwargs["pkg_release"] = "1%{?dist}"
|
|
|
|
|
|
|
|
if args.target == "opensuse":
|
|
|
|
kwargs["date"] = time.strftime("%a %b %d %T %Z %Y")
|
|
|
|
else:
|
|
|
|
kwargs["date"] = time.strftime("%a %b %d %Y")
|
2017-03-06 15:48:19 +00:00
|
|
|
kwargs["packager"] = detect_packager()
|
|
|
|
|
2018-08-14 09:54:33 +00:00
|
|
|
if metadata.license is not None:
|
|
|
|
license, comments = licensing.translate_license(args.target, metadata.license)
|
|
|
|
kwargs["license"] = license
|
|
|
|
kwargs["license_comments"] = comments
|
|
|
|
|
2018-10-31 17:03:21 +00:00
|
|
|
conf = configparser.ConfigParser(interpolation=configparser.ExtendedInterpolation())
|
|
|
|
conf.read(".rust2rpm.conf")
|
|
|
|
if args.target not in conf:
|
|
|
|
conf.add_section(args.target)
|
|
|
|
|
|
|
|
kwargs["distconf"] = conf[args.target]
|
|
|
|
|
2018-09-10 22:06:50 +00:00
|
|
|
spec_file = f"rust-{metadata.name}.spec"
|
2017-02-26 22:43:49 +00:00
|
|
|
spec_contents = template.render(md=metadata, patch_file=patch_file, **kwargs)
|
2017-02-18 00:54:02 +00:00
|
|
|
if args.stdout:
|
2018-10-31 16:00:58 +00:00
|
|
|
print(f"# {spec_file}")
|
2017-02-18 00:54:02 +00:00
|
|
|
print(spec_contents)
|
|
|
|
if patch_file is not None:
|
2018-10-31 16:00:58 +00:00
|
|
|
print(f"# {patch_file}")
|
2017-02-18 00:54:02 +00:00
|
|
|
print("".join(diff), end="")
|
|
|
|
else:
|
|
|
|
with open(spec_file, "w") as fobj:
|
|
|
|
fobj.write(spec_contents)
|
2017-03-06 15:51:31 +00:00
|
|
|
fobj.write("\n")
|
2017-02-18 00:54:02 +00:00
|
|
|
if patch_file is not None:
|
|
|
|
with open(patch_file, "w") as fobj:
|
|
|
|
fobj.writelines(diff)
|
2017-02-05 17:14:52 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|