forked from eclipse-opensovd/cicd-workflows
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck_cargo_lints.py
More file actions
executable file
·168 lines (128 loc) · 4.89 KB
/
check_cargo_lints.py
File metadata and controls
executable file
·168 lines (128 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: 2026 The Contributors to Eclipse OpenSOVD (see CONTRIBUTORS)
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
"""Compare Cargo.toml [workspace.lints] with shared-lints.toml."""
import sys
import tomllib
from pathlib import Path
from typing import Any
def normalize_lint_config(config: Any) -> dict[str, Any]:
"""
Normalize a lint configuration to a consistent format.
Args:
config: Either a string level or a dict with level and optional priority
Returns:
Dict with 'level' and optionally 'priority'
"""
if isinstance(config, dict):
return config
else:
return {"level": config}
def load_shared_lints(shared_lints_path: Path) -> dict[str, dict[str, Any]]:
"""
Load and normalize lints from shared-lints.toml.
Args:
shared_lints_path: Path to shared-lints.toml
Returns:
Dict mapping lint name to normalized config
"""
with open(shared_lints_path, "rb") as f:
data = tomllib.load(f)
return {lint: normalize_lint_config(config) for lint, config in data.items()}
def load_cargo_lints(cargo_toml_path: Path) -> dict[str, dict[str, Any]]:
"""
Load lints from Cargo.toml [workspace.lints.clippy] section.
Args:
cargo_toml_path: Path to Cargo.toml
Returns:
Dict mapping lint name to normalized config
"""
with open(cargo_toml_path, "rb") as f:
data = tomllib.load(f)
# Navigate to workspace.lints.clippy if exists, otherwise
# assume this is a non workspace Cargo.toml and look for lints at the top level
if "workspace" in data:
workspace = data["workspace"]
else:
workspace = data
lints = workspace.get("lints", {})
clippy_lints = lints.get("clippy", {})
return {
lint: normalize_lint_config(config) for lint, config in clippy_lints.items()
}
def compare_lints(
shared_lints: dict[str, dict[str, Any]], cargo_lints: dict[str, dict[str, Any]]
) -> tuple[list[str], list[tuple[str, dict, dict]]]:
"""
Compare shared lints with cargo lints.
Args:
shared_lints: Lints from shared-lints.toml
cargo_lints: Lints from Cargo.toml
Returns:
Tuple of (missing_lints, mismatched_lints)
- missing_lints: List of lint names in shared but not in cargo
- mismatched_lints: List of (lint_name, shared_config, cargo_config) tuples
"""
missing = []
mismatched = []
for lint_name, shared_config in shared_lints.items():
if lint_name not in cargo_lints:
missing.append(lint_name)
elif cargo_lints[lint_name] != shared_config:
mismatched.append((lint_name, shared_config, cargo_lints[lint_name]))
return missing, mismatched
def main():
"""Main entry point."""
if len(sys.argv) < 2:
print("Usage: check_cargo_lints.py <path/to/Cargo.toml>", file=sys.stderr)
print(
"\nChecks if Cargo.toml [workspace.lints.clippy] contains all lints",
file=sys.stderr,
)
print("from shared-lints.toml with matching configurations.", file=sys.stderr)
sys.exit(1)
cargo_toml_path = Path(sys.argv[1])
if not cargo_toml_path.exists():
print(f"Error: {cargo_toml_path} not found", file=sys.stderr)
sys.exit(1)
# Default to shared-lints.toml in the same directory as this script
script_dir = Path(__file__).parent
shared_lints_path = script_dir / "shared-lints.toml"
if not shared_lints_path.exists():
print(f"Error: {shared_lints_path} not found", file=sys.stderr)
sys.exit(1)
# Load lints
shared_lints = load_shared_lints(shared_lints_path)
cargo_lints = load_cargo_lints(cargo_toml_path)
# Compare
missing, mismatched = compare_lints(shared_lints, cargo_lints)
# Report results
if not missing and not mismatched:
print(
f"✓ All {len(shared_lints)} shared lints are correctly configured in {cargo_toml_path}"
)
return 0
exit_code = 0
if missing:
print(f"✗ Missing {len(missing)} lint(s) in {cargo_toml_path}:")
for lint in missing:
config = shared_lints[lint]
print(f" - {lint} = {config}")
exit_code = 1
if mismatched:
print(f"\n✗ {len(mismatched)} lint(s) have different configurations:")
for lint, shared_config, cargo_config in mismatched:
print(f" - {lint}:")
print(f" Shared: {shared_config}")
print(f" Cargo: {cargo_config}")
exit_code = 1
return exit_code
if __name__ == "__main__":
sys.exit(main())