diff options
| author | Stefan Hajnoczi <stefanha@redhat.com> | 2025-07-28 09:30:47 -0400 |
|---|---|---|
| committer | Stefan Hajnoczi <stefanha@redhat.com> | 2025-07-28 09:30:48 -0400 |
| commit | 26453a7f3572068d2731c9f712b26ca2f74097e0 (patch) | |
| tree | f95af372121059a870106b5f9294cb5b69e7fa76 /scripts | |
| parent | c017386f28c03a03b8f14444f8671d3d8f7180fe (diff) | |
| parent | feea87cd6b645d5166bdd304aac88f47f63dc2ef (diff) | |
| download | focaccia-qemu-26453a7f3572068d2731c9f712b26ca2f74097e0.tar.gz focaccia-qemu-26453a7f3572068d2731c9f712b26ca2f74097e0.zip | |
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
* rust: small cleanups + script to update packages * target/i386: AVX bugfix # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCgAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmiDfdIUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroO94Af7BJomIpZfOvtE/NJFXNfjdMrVQMhc # A1BzFahs0MY0Zg3SzVu+wQa6yG2m4sHlqFVQBBCoUCL8Fu7UQoCJesMkCvI6KQly # rZ/5Pp6zZWs4CXR+3mBsw0YqPGG/+rjPxsJf32Z04yrCFPZha7+V9Y+ABDCHv3cZ # IIRQwzIPNu0kv8qeBeXZ5ZfBghsmRiQTJTCv0agezp+5jMH1mtATLUqnKiOMLlLh # ERcw6n74bY7MXqIfFlYRfNmJ+v2jHZQbP3MhEk8ReXfhx2yC9axpppfm6a/bDjhU # iCSSgAi7+Kj/7GPp6TdDmvQTvg3tKRdiEcvnxF95EIvcsu8L8wEPNJAzFA== # =H4e7 # -----END PGP SIGNATURE----- # gpg: Signature made Fri 25 Jul 2025 08:51:30 EDT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: target/i386: fix width of third operand of VINSERTx128 scripts: add script to help distros use global Rust packages rust/pl011: merge device_class.rs into device.rs rust: devices are not staticlibs Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/get-wraps-from-cargo-registry.py | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/scripts/get-wraps-from-cargo-registry.py b/scripts/get-wraps-from-cargo-registry.py new file mode 100755 index 0000000000..31eed5c2dd --- /dev/null +++ b/scripts/get-wraps-from-cargo-registry.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python3 + +# SPDX-License-Identifier: GPL-2.0-or-later + +""" +get-wraps-from-cargo-registry.py - Update Meson subprojects from a global registry +""" + +# Copyright (C) 2025 Red Hat, Inc. +# +# Author: Paolo Bonzini <pbonzini@redhat.com> + +import argparse +import configparser +import filecmp +import glob +import os +import subprocess +import sys + + +def get_name_and_semver(namever: str) -> tuple[str, str]: + """Split a subproject name into its name and semantic version parts""" + parts = namever.rsplit("-", 1) + if len(parts) != 2: + return namever, "" + + return parts[0], parts[1] + + +class UpdateSubprojects: + cargo_registry: str + top_srcdir: str + dry_run: bool + changes: int = 0 + + def find_installed_crate(self, namever: str) -> str | None: + """Find installed crate matching name and semver prefix""" + name, semver = get_name_and_semver(namever) + + # exact version match + path = os.path.join(self.cargo_registry, f"{name}-{semver}") + if os.path.exists(path): + return f"{name}-{semver}" + + # semver match + matches = sorted(glob.glob(f"{path}.*")) + return os.path.basename(matches[0]) if matches else None + + def compare_build_rs(self, orig_dir: str, registry_namever: str) -> None: + """Warn if the build.rs in the original directory differs from the registry version.""" + orig_build_rs = os.path.join(orig_dir, "build.rs") + new_build_rs = os.path.join(self.cargo_registry, registry_namever, "build.rs") + + msg = None + if os.path.isfile(orig_build_rs) != os.path.isfile(new_build_rs): + if os.path.isfile(orig_build_rs): + msg = f"build.rs removed in {registry_namever}" + if os.path.isfile(new_build_rs): + msg = f"build.rs added in {registry_namever}" + + elif os.path.isfile(orig_build_rs) and not filecmp.cmp(orig_build_rs, new_build_rs): + msg = f"build.rs changed from {orig_dir} to {registry_namever}" + + if msg: + print(f"⚠️ Warning: {msg}") + print(" This may affect the build process - please review the differences.") + + def update_subproject(self, wrap_file: str, registry_namever: str) -> None: + """Modify [wrap-file] section to point to self.cargo_registry.""" + assert wrap_file.endswith("-rs.wrap") + wrap_name = wrap_file[:-5] + + env = os.environ.copy() + env["MESON_PACKAGE_CACHE_DIR"] = self.cargo_registry + + config = configparser.ConfigParser() + config.read(wrap_file) + if "wrap-file" not in config: + return + + # do not download the wrap, always use the local copy + orig_dir = config["wrap-file"]["directory"] + if os.path.exists(orig_dir) and orig_dir != registry_namever: + self.compare_build_rs(orig_dir, registry_namever) + + if self.dry_run: + if orig_dir == registry_namever: + print(f"Will install {orig_dir} from registry.") + else: + print(f"Will replace {orig_dir} with {registry_namever}.") + self.changes += 1 + return + + config["wrap-file"]["directory"] = registry_namever + for key in list(config["wrap-file"].keys()): + if key.startswith("source"): + del config["wrap-file"][key] + + # replace existing directory with installed version + if os.path.exists(orig_dir): + subprocess.run( + ["meson", "subprojects", "purge", "--confirm", wrap_name], + cwd=self.top_srcdir, + env=env, + check=True, + ) + + with open(wrap_file, "w") as f: + config.write(f) + + if orig_dir == registry_namever: + print(f"Installing {orig_dir} from registry.") + else: + print(f"Replacing {orig_dir} with {registry_namever}.") + patch_dir = config["wrap-file"]["patch_directory"] + patch_dir = os.path.join("packagefiles", patch_dir) + _, ver = registry_namever.rsplit("-", 1) + subprocess.run( + ["meson", "rewrite", "kwargs", "set", "project", "/", "version", ver], + cwd=patch_dir, + env=env, + check=True, + ) + + subprocess.run( + ["meson", "subprojects", "download", wrap_name], + cwd=self.top_srcdir, + env=env, + check=True, + ) + self.changes += 1 + + @staticmethod + def parse_cmdline() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Replace Meson subprojects with packages in a Cargo registry" + ) + parser.add_argument( + "--cargo-registry", + default=os.environ.get("CARGO_REGISTRY"), + help="Path to Cargo registry (default: CARGO_REGISTRY env var)", + ) + parser.add_argument( + "--dry-run", + action="store_true", + default=False, + help="Do not actually replace anything", + ) + + args = parser.parse_args() + if not args.cargo_registry: + print("error: CARGO_REGISTRY environment variable not set and --cargo-registry not provided") + sys.exit(1) + + return args + + def __init__(self, args: argparse.Namespace): + self.cargo_registry = args.cargo_registry + self.dry_run = args.dry_run + self.top_srcdir = os.getcwd() + + def main(self) -> None: + if not os.path.exists("subprojects"): + print("'subprojects' directory not found, nothing to do.") + return + + os.chdir("subprojects") + for wrap_file in sorted(glob.glob("*-rs.wrap")): + namever = wrap_file[:-8] # Remove '-rs.wrap' + + registry_namever = self.find_installed_crate(namever) + if not registry_namever: + print(f"No installed crate found for {wrap_file}") + continue + + self.update_subproject(wrap_file, registry_namever) + + if self.changes: + if self.dry_run: + print("Rerun without --dry-run to apply changes.") + else: + print(f"✨ {self.changes} subproject(s) updated!") + else: + print("No changes.") + + +if __name__ == "__main__": + args = UpdateSubprojects.parse_cmdline() + UpdateSubprojects(args).main() |