|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
# Copyright © 2022-2023 Intel Corporation
|
|
|
|
|
|
|
|
"""Convert Cargo versions into Meson compatible ones."""
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
import typing as T
|
|
|
|
|
|
|
|
|
|
|
|
def convert(cargo_ver: str) -> T.List[str]:
|
|
|
|
"""Convert a Cargo compatible version into a Meson compatible one.
|
|
|
|
|
|
|
|
:param cargo_ver: The version, as Cargo specifies
|
|
|
|
:return: A list of version constraints, as Meson understands them
|
|
|
|
"""
|
|
|
|
# Cleanup, just for safety
|
|
|
|
cargo_ver = cargo_ver.strip()
|
|
|
|
cargo_vers = [c.strip() for c in cargo_ver.split(',')]
|
|
|
|
|
|
|
|
out: T.List[str] = []
|
|
|
|
|
|
|
|
for ver in cargo_vers:
|
|
|
|
# This covers >= and =< as well
|
|
|
|
# https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#comparison-requirements
|
|
|
|
if ver.startswith(('>', '<', '=')):
|
|
|
|
out.append(ver)
|
|
|
|
|
|
|
|
elif ver.startswith('~'):
|
|
|
|
# Rust has these tilde requirements, which means that it is >= to
|
|
|
|
# the version, but less than the next version
|
|
|
|
# https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#tilde-requirements
|
|
|
|
# we convert those into a pair of constraints
|
|
|
|
v = ver[1:].split('.')
|
|
|
|
out.append(f'>= {".".join(v)}')
|
|
|
|
if len(v) == 3:
|
|
|
|
out.append(f'< {v[0]}.{int(v[1]) + 1}.0')
|
|
|
|
elif len(v) == 2:
|
|
|
|
out.append(f'< {v[0]}.{int(v[1]) + 1}')
|
|
|
|
else:
|
|
|
|
out.append(f'< {int(v[0]) + 1}')
|
|
|
|
|
|
|
|
elif '*' in ver:
|
|
|
|
# Rust has astrisk requirements,, which are like 1.* == ~1
|
|
|
|
# https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#wildcard-requirements
|
|
|
|
v = ver.split('.')[:-1]
|
|
|
|
if v:
|
|
|
|
out.append(f'>= {".".join(v)}')
|
|
|
|
if len(v) == 2:
|
|
|
|
out.append(f'< {v[0]}.{int(v[1]) + 1}')
|
|
|
|
elif len(v) == 1:
|
|
|
|
out.append(f'< {int(v[0]) + 1}')
|
|
|
|
|
|
|
|
else:
|
|
|
|
# a Caret version is equivalent to the default strategy
|
|
|
|
# https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#caret-requirements
|
|
|
|
if ver.startswith('^'):
|
|
|
|
ver = ver[1:]
|
|
|
|
|
|
|
|
# If there is no qualifier, then it means this or the next non-zero version
|
|
|
|
# That means that if this is `1.1.0``, then we need `>= 1.1.0` && `< 2.0.0`
|
|
|
|
# Or if we have `0.1.0`, then we need `>= 0.1.0` && `< 0.2.0`
|
|
|
|
# Or if we have `0.1`, then we need `>= 0.1.0` && `< 0.2.0`
|
|
|
|
# Or if we have `0.0.0`, then we need `< 1.0.0`
|
|
|
|
# Or if we have `0.0`, then we need `< 1.0.0`
|
|
|
|
# Or if we have `0`, then we need `< 1.0.0`
|
|
|
|
# Or if we have `0.0.3`, then we need `>= 0.0.3` && `< 0.0.4`
|
|
|
|
# https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-cratesio
|
|
|
|
#
|
|
|
|
# this works much like the ~ versions, but in reverse. Tilde starts
|
|
|
|
# at the patch version and works up, to the major version, while
|
|
|
|
# bare numbers start at the major version and work down to the patch
|
|
|
|
# version
|
|
|
|
vers = ver.split('.')
|
|
|
|
min_: T.List[str] = []
|
|
|
|
max_: T.List[str] = []
|
|
|
|
bumped = False
|
|
|
|
for v_ in vers:
|
|
|
|
if v_ != '0' and not bumped:
|
|
|
|
min_.append(v_)
|
|
|
|
max_.append(str(int(v_) + 1))
|
|
|
|
bumped = True
|
|
|
|
else:
|
|
|
|
min_.append(v_)
|
|
|
|
if not bumped:
|
|
|
|
max_.append('0')
|
|
|
|
|
|
|
|
# If there is no minimum, don't emit one
|
|
|
|
if set(min_) != {'0'}:
|
|
|
|
out.append('>= {}'.format('.'.join(min_)))
|
|
|
|
if set(max_) != {'0'}:
|
|
|
|
out.append('< {}'.format('.'.join(max_)))
|
|
|
|
else:
|
|
|
|
out.append('< 1')
|
|
|
|
|
|
|
|
return out
|