Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1# This script implements the workspace inheritance mechanism described 2# here: https://doc.rust-lang.org/cargo/reference/workspaces.html#the-package-table 3# 4# Please run `mypy --strict`, `black`, and `isort --profile black` on this after editing, thanks! 5 6import sys 7from typing import Any 8 9import tomli 10import tomli_w 11 12 13def load_file(path: str) -> dict[str, Any]: 14 with open(path, "rb") as f: 15 return tomli.load(f) 16 17 18def replace_key( 19 workspace_manifest: dict[str, Any], table: dict[str, Any], section: str, key: str 20) -> bool: 21 if ( 22 isinstance(table[key], dict) 23 and "workspace" in table[key] 24 and table[key]["workspace"] is True 25 ): 26 print("replacing " + key) 27 28 replaced = table[key] 29 del replaced["workspace"] 30 31 workspace_copy = workspace_manifest[section][key] 32 33 if section == "dependencies": 34 crate_features = replaced.get("features") 35 36 if type(workspace_copy) is str: 37 replaced["version"] = workspace_copy 38 else: 39 replaced.update(workspace_copy) 40 41 merged_features = (crate_features or []) + ( 42 workspace_copy.get("features") or [] 43 ) 44 45 if len(merged_features) > 0: 46 # Dictionaries are guaranteed to be ordered (https://stackoverflow.com/a/7961425) 47 replaced["features"] = list(dict.fromkeys(merged_features)) 48 elif section == "package": 49 table[key] = replaced = workspace_copy 50 51 return True 52 53 return False 54 55 56def replace_dependencies( 57 workspace_manifest: dict[str, Any], root: dict[str, Any] 58) -> bool: 59 changed = False 60 61 for key in ["dependencies", "dev-dependencies", "build-dependencies"]: 62 if key in root: 63 for k in root[key].keys(): 64 changed |= replace_key(workspace_manifest, root[key], "dependencies", k) 65 66 return changed 67 68 69def main() -> None: 70 top_cargo_toml = load_file(sys.argv[2]) 71 72 if "workspace" not in top_cargo_toml: 73 # If top_cargo_toml is not a workspace manifest, then this script was probably 74 # ran on something that does not actually use workspace dependencies 75 print(f"{sys.argv[2]} is not a workspace manifest, doing nothing.") 76 return 77 78 crate_manifest = load_file(sys.argv[1]) 79 workspace_manifest = top_cargo_toml["workspace"] 80 81 if "workspace" in crate_manifest: 82 return 83 84 changed = False 85 86 for key in crate_manifest["package"].keys(): 87 changed |= replace_key( 88 workspace_manifest, crate_manifest["package"], "package", key 89 ) 90 91 changed |= replace_dependencies(workspace_manifest, crate_manifest) 92 93 if "target" in crate_manifest: 94 for key in crate_manifest["target"].keys(): 95 changed |= replace_dependencies( 96 workspace_manifest, crate_manifest["target"][key] 97 ) 98 99 if not changed: 100 return 101 102 with open(sys.argv[1], "wb") as f: 103 tomli_w.dump(crate_manifest, f) 104 105 106if __name__ == "__main__": 107 main()