rust2rpm: fall back to latest pre-release if there is no stable release

This situation can occur in two ways:
- either the crate has published only pre-releases so far, or
- all previously published stable releases were yanked
This commit is contained in:
Fabio Valentini 2022-10-11 14:19:08 +02:00
parent 93e10cba84
commit 23523b5fdc
No known key found for this signature in database
GPG key ID: 5AC5F572E5D410AF

View file

@ -53,6 +53,10 @@ TARGET_DEPENDENCY_LINE = re.compile(
) )
class NoVersionsError(Exception):
pass
def sortify(func): def sortify(func):
"""Return a sorted list from a generator""" """Return a sorted list from a generator"""
@ -122,22 +126,34 @@ def local_crate(crate, version):
return crate, cratename, version return crate, cratename, version
def query_newest_version(crate): def query_newest_version(crate) -> str:
url = requests.compat.urljoin(API_URL, f"crates/{crate}/versions") url = requests.compat.urljoin(API_URL, f"crates/{crate}/versions")
req = requests.get(url, headers={"User-Agent": "rust2rpm"}) req = requests.get(url, headers={"User-Agent": "rust2rpm"})
req.raise_for_status() req.raise_for_status()
versions = req.json()["versions"] versions = req.json()["versions"]
for struct in versions:
version = struct["num"] is_stable = lambda s: not re.search("alpha|beta|rc|pre", s["num"])
if struct["yanked"]: is_not_yanked = lambda s: not s["yanked"]
log.info(f"Ignoring yanked version {version!r}.")
elif re.search("alpha|beta|rc|pre", version): # return the most recent, non-yanked stable version
log.info(f"Ignoring pre-release version {version!r}.")
else: is_not_yanked_and_stable = lambda s: is_stable(s) and is_not_yanked(s)
log.success(f"Using latest stable version {version!r}.") not_yanked_and_stable = [*filter(is_not_yanked_and_stable, versions)]
if len(not_yanked_and_stable) > 0:
version = not_yanked_and_stable[0]["num"]
return version return version
raise ValueError("Couldn't find any release versions. Specify a version explicitly.") # there are no non-yanked stable versions:
# fall back to the latest pre-release
not_yanked = [*filter(is_not_yanked, versions)]
if len(not_yanked) > 0:
version = not_yanked[0]["num"]
log.warn(f"No stable versions available. Falling back to the latest pre-release version {version!r}.")
return version
# there are no non-yanked versions: fatal
raise NoVersionsError()
def download(crate, version): def download(crate, version):
@ -637,7 +653,11 @@ def main():
if args.crate is None: if args.crate is None:
parser.error("crate/path argument missing and autodetection failed") parser.error("crate/path argument missing and autodetection failed")
try:
crate, diffs, metadata, doc_files, license_files = make_diff_metadata(args, args.crate, args.version) crate, diffs, metadata, doc_files, license_files = make_diff_metadata(args, args.crate, args.version)
except NoVersionsError:
log.error(f"No versions are available for crate {args.crate!r}.")
sys.exit(1)
pkg_name = package_name_suffixed(metadata.name, args.suffix) pkg_name = package_name_suffixed(metadata.name, args.suffix)