File: flatten-local-crates.py

package info (click to toggle)
rustup 1.27.1-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 3,596 kB
  • sloc: sh: 856; python: 233; javascript: 183; makefile: 27
file content (76 lines) | stat: -rwxr-xr-x 2,556 bytes parent folder | download | duplicates (2)
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)