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
|
#!/bin/env python3
# SPDX-FileCopyrightText: 2023 Debian Rust Maintainers
# SPDX-License-Identifier: MIT
import toml
import os
import sys
from typing import Dict, List, Any
def flatten_features(feature: str, pool: Dict[str, List[str]]) -> List[str]:
my_features = pool.get(feature)
flattened = []
if my_features is None:
return [feature]
for f in my_features:
child_feature = pool.get(f)
if child_feature is None:
flattened.append(f)
# a crate dependency, not a feature
continue
flattened.extend(flatten_features(f, pool))
return flattened
def load_toml(path: str) -> Dict[str, Any]:
with open(path, "r") as f:
return toml.load(f)
def flatten_local_crates(path: str) -> str:
toml_data = load_toml(os.path.join(path, "Cargo.toml"))
local_crates = {}
for k, v in toml_data["dependencies"].items():
if "path" in v:
crate_path = os.path.join(path, v["path"], "Cargo.toml")
local_crates[k] = load_toml(crate_path)
ws_crates = toml_data["dependencies"].keys()
# scan features for references to local crates
for k, v in toml_data["features"].items():
for feature in v:
if "/" not in feature:
continue
crate, feature_name = feature.split("/", 1)
if crate not in local_crates:
continue
# replace the references with concrete features
flattened = flatten_features(
feature_name, local_crates[crate]["features"])
for i in flattened:
if i in ws_crates:
flattened.remove(i)
toml_data["features"][k] = flattened
# merge local crate dependencies with workspace dependencies
for crate in local_crates.values():
for k, v in crate["dependencies"].items():
if k in ws_crates:
continue
toml_data["dependencies"][k] = v
# remove local crates that in the workspace
for local_crate in local_crates.keys():
del toml_data["dependencies"][local_crate]
return toml.dumps(toml_data)
if __name__ == "__main__":
if len(sys.argv) not in (2, 3):
print(f"Usage: python3 {sys.argv[0]} <path/to/crate/root> [output/Cargo.toml]")
exit(1)
modified = flatten_local_crates(sys.argv[1])
modified_file = sys.argv[2] if len(sys.argv) == 3 else os.path.join(sys.argv[1], "Cargo.toml")
with open(modified_file, "w") as f:
f.write(modified)
|