| |
@@ -6,6 +6,7 @@
|
| |
import difflib
|
| |
import functools
|
| |
import itertools
|
| |
+ import glob
|
| |
import os
|
| |
import pathlib
|
| |
import re
|
| |
@@ -135,6 +136,10 @@
|
| |
os.unlink(path)
|
| |
raise
|
| |
|
| |
+ def package_name_suffixed(name, suffix):
|
| |
+ joiner = '_' if suffix and name[-1].isdigit() else ''
|
| |
+ return 'rust-' + name + joiner + (suffix or '')
|
| |
+
|
| |
def local_toml(toml, version):
|
| |
if os.path.isdir(toml):
|
| |
doc_files = get_doc_files(toml)
|
| |
@@ -150,14 +155,27 @@
|
| |
cratename, version = os.path.basename(crate)[:-6].rsplit("-", 1)
|
| |
return crate, cratename, version
|
| |
|
| |
+ def query_newest_version(crate):
|
| |
+ url = requests.compat.urljoin(API_URL, f"crates/{crate}/versions")
|
| |
+ req = requests.get(url, headers={"User-Agent": "rust2rpm"})
|
| |
+ req.raise_for_status()
|
| |
+ versions = req.json()["versions"]
|
| |
+ for struct in versions:
|
| |
+ version = struct["num"]
|
| |
+ if struct["yanked"]:
|
| |
+ print(f'Ignoring yanked version {version}')
|
| |
+ elif re.search('alpha|beta|rc|pre', version):
|
| |
+ print(f'Ignoring pre-release version {version}')
|
| |
+ else:
|
| |
+ print(f'Found version {version}')
|
| |
+ return version
|
| |
+
|
| |
+ raise ValueError("Couldn't find any release versions. Specify a version explicitly.")
|
| |
+
|
| |
def download(crate, version):
|
| |
if version is None:
|
| |
# Now we need to get latest version
|
| |
- url = requests.compat.urljoin(API_URL, f"crates/{crate}/versions")
|
| |
- req = requests.get(url, headers={"User-Agent": "rust2rpm"})
|
| |
- req.raise_for_status()
|
| |
- versions = req.json()["versions"]
|
| |
- version = next(version["num"] for version in versions if not version["yanked"])
|
| |
+ version = query_newest_version(crate)
|
| |
|
| |
os.makedirs(CACHEDIR, exist_ok=True)
|
| |
cratef_base = f"{crate}-{version}.crate"
|
| |
@@ -343,6 +361,44 @@
|
| |
return any(re.match(autochangelog_re, line) for line in text.splitlines())
|
| |
|
| |
|
| |
+ def guess_crate_name():
|
| |
+ """Guess crate name from directory name and/or spec file name
|
| |
+
|
| |
+ If a spec file is present, we use the %crate variable. This is the best
|
| |
+ option. But if we're in a new directory, and don't have a spec file yet,
|
| |
+ let's assume that this is a dist-git directory and extract the crate name.
|
| |
+ For compat packages, the directory name will contain a version suffix,
|
| |
+ but a compat package would almost always be created from an existing
|
| |
+ dist-git directory, hence there'd be a spec file, so we can ignore this.
|
| |
+ """
|
| |
+ specs = glob.glob('*.spec')
|
| |
+ if len(specs) > 1:
|
| |
+ print('Multiple spec files found, cannot guess crate name')
|
| |
+ return None
|
| |
+ if len(specs) == 1:
|
| |
+ crate = None
|
| |
+ for line in open(specs[0]):
|
| |
+ if m := re.match(r'^%(?:global|define)\s+crate\s+(\S+)\s+', line):
|
| |
+ if crate:
|
| |
+ print(f'{specs[0]}: Found duplicated %crate define, cannot guess crate name')
|
| |
+ return None
|
| |
+ crate = m.group(1)
|
| |
+ if '%' in crate:
|
| |
+ print(f'{specs[0]}: Crate name appears to use a macro, and evaluation is not implemented')
|
| |
+ return None
|
| |
+ if crate:
|
| |
+ print(f'{specs[0]}: Found crate name {crate!r}')
|
| |
+ else:
|
| |
+ print(f'{specs[0]}: %crate define not found, cannot guess crate name')
|
| |
+ return crate
|
| |
+
|
| |
+ dirname = os.path.basename(os.getcwd())
|
| |
+ if m := re.match('^rust-([a-z+0-9_-]+)$', dirname):
|
| |
+ print(f'Using crate name {m.group(1)!r} based on the directory name')
|
| |
+ return m.group(1)
|
| |
+
|
| |
+ return None
|
| |
+
|
| |
@contextlib.contextmanager
|
| |
def exit_on_common_errors():
|
| |
"""Suppress tracebacks on common "expected" exceptions"""
|
| |
@@ -419,7 +475,9 @@
|
| |
return
|
| |
|
| |
if args.crate is None:
|
| |
- parser.error("required crate/path argument missing")
|
| |
+ args.crate = guess_crate_name()
|
| |
+ if args.crate is None:
|
| |
+ parser.error("crate/path argument missing and autodetection failed")
|
| |
|
| |
crate, diff, metadata, doc_files, license_files = make_diff_metadata(args, args.crate, args.version)
|
| |
|
| |
@@ -450,21 +508,14 @@
|
| |
raise ValueError("No bins and no libs")
|
| |
kwargs["include_devel"] = is_lib
|
| |
|
| |
- if args.suffix is not None:
|
| |
- if metadata.name[-1].isdigit():
|
| |
- suffix = f'_{args.suffix}'
|
| |
- else:
|
| |
- suffix = args.suffix
|
| |
- else:
|
| |
- suffix = ""
|
| |
- kwargs["pkg_suffix"] = suffix
|
| |
- spec_file = pathlib.Path(f"rust-{metadata.name}{suffix}.spec")
|
| |
+ kwargs["pkg_name"] = pkg_name = package_name_suffixed(metadata.name, args.suffix)
|
| |
+ spec_file = pathlib.Path(f"{pkg_name}.spec")
|
| |
|
| |
if args.target in {"fedora"} and args.existence_check and not os.path.exists(spec_file):
|
| |
# No specfile, so this is probably a new package
|
| |
- package_info = get_package_info(f"rust-{metadata.name}{suffix}")
|
| |
+ package_info = get_package_info(pkg_name)
|
| |
if package_info:
|
| |
- print(f"Crate {metadata.name}{suffix} is already packaged in Fedora ({package_info['full_url']}).")
|
| |
+ print(f"Crate {pkg_name} is already packaged in Fedora ({package_info['full_url']}).")
|
| |
print("Re-run with --no-existence-check if you still want to convert it.")
|
| |
sys.exit(1)
|
| |
|
| |
Note that this is now broken, it prints something like:
Crate git2_0.13 is already packaged in Fedora (https://src.fedoraproject.org/rpms/rust-git2_0.13).
This is not the crate name, this is crate name + suffix. But at this point, shouldn't
pkg_name
berust-git2_0.13
?