Add script to sync Cargo.lock with ebuild files

This is a simple python script to uprev ebuild files where Cargo.lock
has a newer version, and vice versa.

The script is run to fix up some libraries that got out of sync.
The protobuf dependencies should be upreved, but newer versions
have deprecated some of the methods we use, causing clippy warnings.

BUG=b:175120466
TEST=Tests in Kokoro and CQ pass

Cq-Depend: chromium:2704533
Change-Id: I1485fbffba61e72502f8398320094dfe2c7ffeea
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2705681
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: kokoro <noreply+kokoro@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Dennis Kempin <denniskempin@google.com>
This commit is contained in:
Dennis Kempin 2021-02-17 13:38:15 -08:00 committed by Commit Bot
parent 229cbead14
commit de8c806279
2 changed files with 163 additions and 8 deletions

16
Cargo.lock generated
View file

@ -125,9 +125,9 @@ dependencies = [
[[package]]
name = "bitflags"
version = "1.1.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "cc"
@ -425,9 +425,9 @@ dependencies = [
[[package]]
name = "gdbstub"
version = "0.4.0"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "347c27d24b8ac4a2bcad3ff3d0695271a0510c020bd8134b53d189e973ed58bf"
checksum = "224c17cf54ffe7e084343f25c7f2881a399bea69862ecaf5bc97f0f6586ba0dc"
dependencies = [
"cfg-if",
"log",
@ -770,9 +770,9 @@ checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e"
[[package]]
name = "proc-macro2"
version = "1.0.8"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
@ -883,9 +883,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "syn"
version = "1.0.14"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
dependencies = [
"proc-macro2",
"quote",

155
bin/sync_ebuild_files Executable file
View file

@ -0,0 +1,155 @@
#!/usr/bin/env python3
# Copyright 2021 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Run inside `cros_sdk` to uprev dependency versions between Cargo.lock and
# chromiumos-overlay ebuild files.
import re
import glob
import os
import sys
import subprocess
from distutils.version import StrictVersion
from datetime import datetime
# Ideally we would install a toml parser, but this will do for a quick little
# tool.
CARGO_LOCK_REGEX = re.compile(
r"""name = "([^"]+)"
version = "([^"]+)"
source ="""
)
IGNORED_PACKAGES = ["pin-utils", "pkg-config"]
DEV_RUST_PATH = "../../third_party/chromiumos-overlay/dev-rust"
EBUILD_FILE_GLOB = f"{DEV_RUST_PATH}/*/*.ebuild"
EBUILD_FILE_REGEX = re.compile(r"([\w\-_]+)-([0-9\.]+)\.ebuild")
YEAR = datetime.today().year
def ebuild_template(package: str):
return f"""\
# Copyright {YEAR} The Chromium OS Authors. All rights reserved.
# Distributed under the terms of the GNU General Public License v2
EAPI="7"
CROS_RUST_REMOVE_DEV_DEPS=1
inherit cros-rust
DESCRIPTION="Build file for the {package} crate."
HOMEPAGE="https://crates.io/crates/{package}"
SRC_URI="https://crates.io/api/v1/crates/${{PN}}/${{PV}}/download -> ${{P}}.crate"
LICENSE="|| ( MIT Apache-2.0 )"
SLOT="${{PV}}/${{PR}}"
KEYWORDS="*"
# TODO: Add crate dependencies
DEPEND=""
"""
def ebuild_file_path(package: str, version: str):
return f"{DEV_RUST_PATH}/{package}/{package}-{version}.ebuild"
def parse_cargo_lock():
"""Parses Cargo.lock file and returns (package, version) pairs."""
with open("Cargo.lock", "r") as lock_file:
lock_str = lock_file.read()
for match in CARGO_LOCK_REGEX.finditer(lock_str):
yield (match.group(1), match.group(2))
def all_ebuild_versions():
"""Returns (package, version) pairs of ebuild files in dev-rust."""
for ebuild_path in glob.glob(EBUILD_FILE_GLOB):
ebuild_name = os.path.basename(ebuild_path)
match = EBUILD_FILE_REGEX.match(ebuild_name)
if match:
yield (match.group(1), match.group(2))
def ebuild_versions_dict():
"""Returns a dict of package versions of all ebuild files in dev-rust."""
versions: dict[str, list[str]] = {}
for (package, version) in all_ebuild_versions():
if package in versions:
versions[package].append(version)
versions[package].sort(key=StrictVersion)
else:
versions[package] = [version]
return versions
def update_manifest(package: str, version: str):
"""Regenerate ebuild manifest for the provided package/version."""
cmd = ["ebuild", ebuild_file_path(package, version), "manifest"]
print(" ", " ".join(cmd))
subprocess.run(cmd)
def uprev_ebuild(package: str, new_version: str, old_version: str):
"""Updates the ebuild file from `old_version` to `new_version`."""
old_path = ebuild_file_path(package, old_version)
new_path = ebuild_file_path(package, new_version)
print(f" {old_path} -> {new_path}")
os.rename(old_path, new_path)
update_manifest(package, new_version)
def add_ebuild(package: str, version: str):
"""Creates a new ebuild file for the provided package."""
ebuild_path = ebuild_file_path(package, version)
print(f" Writing {ebuild_path}")
open(ebuild_path, "w").write(ebuild_template(package))
update_manifest(package, version)
def update_cargo(package: str, latest_version: str):
"""Runs `cargo update` to update the version in Cargo.lock."""
cmd = ["cargo", "update", "-p", package, "--precise", latest_version]
print(" ", " ".join(cmd))
subprocess.run(cmd)
def confirm(question: str):
print(f"{question} [y/N]")
return sys.stdin.readline().strip().lower() == "y"
def main():
ebuild_packages = ebuild_versions_dict()
for (package, cargo_version) in parse_cargo_lock():
ebuild_versions = ebuild_packages.get(package, [])
if package in IGNORED_PACKAGES:
continue
if cargo_version in ebuild_versions:
continue
if not ebuild_versions:
print(f"{package}: No ebuild file.")
if confirm("Create ebuild?"):
add_ebuild(package, cargo_version)
elif StrictVersion(ebuild_versions[-1]) > StrictVersion(cargo_version):
print(
f"{package}: Cargo version {cargo_version} is older than "
f"latest ebuild version ({', '.join(ebuild_versions)})."
)
if confirm("Update Cargo.lock?"):
update_cargo(package, ebuild_versions[-1])
else:
print(
f"{package}: Ebuild versions ({', '.join(ebuild_versions)}) "
f"are older than cargo version {cargo_version}."
)
if confirm("Uprev ebuild?"):
uprev_ebuild(package, cargo_version, ebuild_versions[-1])
if __name__ == "__main__":
main()