mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 05:35:20 +00:00
scripts: Add consistency check script
Add `package-consistency-check.py` script to prevent #6809 and #6815 from happening. This script takes a string present in the repository field of packages to identify pacakges from a specific source. Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
This commit is contained in:
parent
675140f627
commit
337cbf3d33
83
scripts/package-consistency-check.py
Executable file
83
scripts/package-consistency-check.py
Executable file
@ -0,0 +1,83 @@
|
||||
#!/bin/env python3
|
||||
#
|
||||
# Copyright © 2024 Institute of Software, CAS. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import subprocess
|
||||
import json
|
||||
from argparse import ArgumentParser
|
||||
from collections import defaultdict
|
||||
|
||||
def get_cargo_metadata():
|
||||
result = subprocess.run(
|
||||
['cargo', 'metadata', '--format-version=1'],
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
if result.returncode != 0:
|
||||
exit(1)
|
||||
|
||||
metadata = json.loads(result.stdout)
|
||||
return metadata
|
||||
|
||||
def find_dependents_of_package(metadata, package_source):
|
||||
"""Find dependencies based on the provided source identifier and return related package info."""
|
||||
packages = defaultdict(list)
|
||||
direct_dependents = defaultdict(list)
|
||||
|
||||
# Identify packages from the given package source and record version
|
||||
for pkg in metadata['packages']:
|
||||
repository = pkg['repository'] or ''
|
||||
if package_source in repository:
|
||||
packages[pkg['name']].append(pkg['version'])
|
||||
|
||||
# Find packages that immediately depend on the identified source packages
|
||||
for node in metadata['resolve']['nodes']:
|
||||
current_pkg = next(pkg for pkg in metadata['packages'] if pkg['id'] == node['id'])
|
||||
current_pkg_name = current_pkg['name']
|
||||
current_pkg_version = current_pkg['version']
|
||||
|
||||
for dep_id in node['dependencies']:
|
||||
dep_pkg = next(pkg for pkg in metadata['packages'] if pkg['id'] == dep_id)
|
||||
dep_name = dep_pkg['name']
|
||||
dep_version = dep_pkg['version']
|
||||
|
||||
if dep_name in packages:
|
||||
direct_dependents[(dep_name, dep_version)].append((current_pkg_name, current_pkg_version))
|
||||
|
||||
return packages, direct_dependents
|
||||
|
||||
def check_for_version_conflicts(packages, direct_dependents):
|
||||
"""Check if there are multiple versions of dependencies, and return True if conflicts are found."""
|
||||
has_conflicts = False
|
||||
|
||||
for pkg_name, versions in packages.items():
|
||||
if len(set(versions)) > 1:
|
||||
has_conflicts = True
|
||||
print(f"Error: Multiple versions detected for {pkg_name}: {set(versions)}")
|
||||
for version in set(versions):
|
||||
print(f" Version {version} used by:")
|
||||
for dependent, dep_version in direct_dependents[(pkg_name, version)]:
|
||||
print(f" - {dependent} v{dep_version}")
|
||||
|
||||
return has_conflicts
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = ArgumentParser(description='Cargo dependency conflict checker.')
|
||||
parser.add_argument('package_source', type=str, help='A keyword used to match the repository URL field')
|
||||
args = parser.parse_args()
|
||||
|
||||
metadata = get_cargo_metadata()
|
||||
if metadata is None:
|
||||
print("Error: Metadata is empty")
|
||||
exit(1)
|
||||
|
||||
packages, direct_dependents = find_dependents_of_package(metadata, args.package_source)
|
||||
|
||||
has_conflicts = check_for_version_conflicts(packages, direct_dependents)
|
||||
|
||||
if has_conflicts:
|
||||
exit(1)
|
||||
|
Loading…
Reference in New Issue
Block a user