1 # This script implements the workspace inheritance mechanism described
2 # here: https://doc.rust-lang.org/cargo/reference/workspaces.html#the-package-table
4 # Please run `mypy --strict`, `black`, and `isort --profile black` on this after editing, thanks!
13 def load_file(path
: str) -> dict[str, Any
]:
14 with
open(path
, "rb") as f
:
18 # This replicates the dependency merging logic from Cargo.
19 # See `inner_dependency_inherit_with`:
20 # https://github.com/rust-lang/cargo/blob/4de0094ac78743d2c8ff682489e35c8a7cafe8e4/src/cargo/util/toml/mod.rs#L982
22 workspace_manifest
: dict[str, Any
], table
: dict[str, Any
], section
: str, key
: str
25 isinstance(table
[key
], dict)
26 and "workspace" in table
[key
]
27 and table
[key
]["workspace"] is True
29 print("replacing " + key
)
31 local_dep
= table
[key
]
32 del local_dep
["workspace"]
34 workspace_dep
= workspace_manifest
[section
][key
]
36 if section
== "dependencies":
37 if isinstance(workspace_dep
, str):
38 workspace_dep
= {"version": workspace_dep
}
40 final
: dict[str, Any
] = workspace_dep
.copy()
42 merged_features
= local_dep
.pop("features", []) + workspace_dep
.get("features", [])
44 final
["features"] = merged_features
46 local_default_features
= local_dep
.pop("default-features", None)
47 workspace_default_features
= workspace_dep
.get("default-features")
49 if not workspace_default_features
and local_default_features
:
50 final
["default-features"] = True
52 optional
= local_dep
.pop("optional", False)
54 final
["optional"] = True
57 raise Exception(f
"Unhandled keys in inherited dependency {key}: {local_dep}")
60 elif section
== "package":
61 table
[key
] = workspace_dep
68 def replace_dependencies(
69 workspace_manifest
: dict[str, Any
], root
: dict[str, Any
]
73 for key
in ["dependencies", "dev-dependencies", "build-dependencies"]:
75 for k
in root
[key
].keys():
76 changed |
= replace_key(workspace_manifest
, root
[key
], "dependencies", k
)
82 top_cargo_toml
= load_file(sys
.argv
[2])
84 if "workspace" not in top_cargo_toml
:
85 # If top_cargo_toml is not a workspace manifest, then this script was probably
86 # ran on something that does not actually use workspace dependencies
87 print(f
"{sys.argv[2]} is not a workspace manifest, doing nothing.")
90 crate_manifest
= load_file(sys
.argv
[1])
91 workspace_manifest
= top_cargo_toml
["workspace"]
93 if "workspace" in crate_manifest
:
98 for key
in crate_manifest
["package"].keys():
99 changed |
= replace_key(
100 workspace_manifest
, crate_manifest
["package"], "package", key
103 changed |
= replace_dependencies(workspace_manifest
, crate_manifest
)
105 if "target" in crate_manifest
:
106 for key
in crate_manifest
["target"].keys():
107 changed |
= replace_dependencies(
108 workspace_manifest
, crate_manifest
["target"][key
]
112 "lints" in crate_manifest
113 and "workspace" in crate_manifest
["lints"]
114 and crate_manifest
["lints"]["workspace"] is True
116 crate_manifest
["lints"] = workspace_manifest
["lints"]
121 with
open(sys
.argv
[1], "wb") as f
:
122 tomli_w
.dump(crate_manifest
, f
)
125 if __name__
== "__main__":