aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2022-03-22 13:26:10 -0700
committerDylan Baker <dylan@pnwbakers.com>2023-06-07 19:20:30 -0700
commit5e59e5a9e49e9eee4e551f4078f32edd67659da4 (patch)
tree693b0e54d8925b3354eb632a4fbc480eb73a9ce2 /mesonbuild
parentb01ae087f5f54b0777201c83440fb6777648acd8 (diff)
downloadmeson-5e59e5a9e49e9eee4e551f4078f32edd67659da4.zip
meson-5e59e5a9e49e9eee4e551f4078f32edd67659da4.tar.gz
meson-5e59e5a9e49e9eee4e551f4078f32edd67659da4.tar.bz2
cargo/version: add a function to convert cargo versioning to meson
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/cargo/version.py96
1 files changed, 96 insertions, 0 deletions
diff --git a/mesonbuild/cargo/version.py b/mesonbuild/cargo/version.py
new file mode 100644
index 0000000..cb09a00
--- /dev/null
+++ b/mesonbuild/cargo/version.py
@@ -0,0 +1,96 @@
+# 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:
+ if not (bumped and v_ == '0'):
+ 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