1#!/usr/bin/env python3 2 3from pathlib import Path 4from typing import List 5import json 6import os 7import shutil 8import shutil 9import subprocess 10import sys 11import tempfile 12 13 14def run_subprocess(command: List[str]) -> subprocess.CompletedProcess[str]: 15 proc = subprocess.run(command, capture_output=True) 16 17 if proc.returncode: 18 print("Subcommand exited with error", proc.returncode, file=sys.stderr) 19 print("Args:", proc.args, file=sys.stderr) 20 print("stderr:", proc.stderr.decode("utf-8"), file=sys.stderr) 21 print("stdout:", proc.stdout.decode("utf-8"), file=sys.stderr) 22 exit(proc.returncode) 23 24 return proc 25 26 27if __name__ == "__main__": 28 29 workspace_root = Path( 30 os.environ.get("BUILD_WORKSPACE_DIRECTORY", 31 str(Path(__file__).parent.parent.parent.parent.parent))) 32 metadata_dir = workspace_root / "crate_universe/test_data/metadata" 33 cargo = os.getenv("CARGO", "cargo") 34 35 with tempfile.TemporaryDirectory() as temp_dir: 36 temp_dir_path = Path(temp_dir) 37 temp_dir_path.mkdir(parents=True, exist_ok=True) 38 39 for test_dir in metadata_dir.iterdir(): 40 41 # Check to see if the directory contains a Cargo manifest 42 real_manifest = test_dir / "Cargo.toml" 43 if not real_manifest.exists(): 44 continue 45 46 # Copy the test directory into a temp directory (and out from under a Cargo workspace) 47 manifest_dir = temp_dir_path / test_dir.name 48 shutil.copytree(test_dir, manifest_dir) 49 50 manifest = manifest_dir / "Cargo.toml" 51 lockfile = manifest_dir / "Cargo.lock" 52 53 if lockfile.exists(): 54 proc = run_subprocess([cargo, "update", "--manifest-path", str(manifest), "--workspace"]) 55 else: 56 # Generate Lockfile 57 proc = run_subprocess([cargo, "generate-lockfile", "--manifest-path", str(manifest)]) 58 59 if not lockfile.exists(): 60 print("Faield to generate lockfile") 61 print("Args:", proc.args, file=sys.stderr) 62 print("stderr:", proc.stderr.decode("utf-8"), file=sys.stderr) 63 print("stdout:", proc.stdout.decode("utf-8"), file=sys.stderr) 64 exit(1) 65 66 shutil.copy2(str(lockfile), str(test_dir / "Cargo.lock")) 67 68 # Generate metadata 69 proc = subprocess.run( 70 [cargo, "metadata", "--format-version", "1", "--manifest-path", str(manifest)], 71 capture_output=True) 72 73 if proc.returncode: 74 print("Subcommand exited with error", proc.returncode, file=sys.stderr) 75 print("Args:", proc.args, file=sys.stderr) 76 print("stderr:", proc.stderr.decode("utf-8"), file=sys.stderr) 77 print("stdout:", proc.stdout.decode("utf-8"), file=sys.stderr) 78 exit(proc.returncode) 79 80 cargo_home = os.environ.get("CARGO_HOME", str(Path.home() / ".cargo")) 81 82 # Replace the temporary directory so package IDs are predictable 83 metadata_text = proc.stdout.decode("utf-8") 84 metadata_text = metadata_text.replace(temp_dir, "{TEMP_DIR}") 85 metadata_text = metadata_text.replace(cargo_home, "{CARGO_HOME}") 86 87 # Write metadata to disk 88 metadata = json.loads(metadata_text) 89 output = test_dir / "metadata.json" 90 output.write_text(json.dumps(metadata, indent=4, sort_keys=True) + "\n") 91