Commit f80228a8 authored by K900's avatar K900
Browse files

build-support/rust: rewrite workspace dependency inheritance

This fixes at least one bug with default-features, and also
just aligns us more with what Cargo actually does.

Also some Python style fixes and a bit less mutating state.
parent d42c1c8d
Loading
Loading
Loading
Loading
+27 −15
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@ def load_file(path: str) -> dict[str, Any]:
        return tomli.load(f)


# This replicates the dependency merging logic from Cargo.
# See `inner_dependency_inherit_with`:
# https://github.com/rust-lang/cargo/blob/4de0094ac78743d2c8ff682489e35c8a7cafe8e4/src/cargo/util/toml/mod.rs#L982
def replace_key(
    workspace_manifest: dict[str, Any], table: dict[str, Any], section: str, key: str
) -> bool:
@@ -25,28 +28,37 @@ def replace_key(
    ):
        print("replacing " + key)

        replaced = table[key]
        del replaced["workspace"]
        local_dep = table[key]
        del local_dep["workspace"]

        workspace_copy = workspace_manifest[section][key]
        workspace_dep = workspace_manifest[section][key]

        if section == "dependencies":
            crate_features = replaced.get("features")
            if isinstance(workspace_dep, str):
                workspace_dep = {"version": workspace_dep}

            if type(workspace_copy) is str:
                replaced["version"] = workspace_copy
            else:
                replaced.update(workspace_copy)
            final: dict[str, Any] = workspace_dep.copy()

                merged_features = (crate_features or []) + (
                    workspace_copy.get("features") or []
                )
            merged_features = local_dep.pop("features", []) + workspace_dep.get("features", [])
            if merged_features:
                final["features"] = merged_features

            local_default_features = local_dep.pop("default-features", None)
            workspace_default_features = workspace_dep.get("default-features")

            if not workspace_default_features and local_default_features:
                final["default-features"] = True

            optional = local_dep.pop("optional", False)
            if optional:
                final["optional"] = True

            if local_dep:
                raise Exception(f"Unhandled keys in inherited dependency {key}: {local_dep}")

                if len(merged_features) > 0:
                    # Dictionaries are guaranteed to be ordered (https://stackoverflow.com/a/7961425)
                    replaced["features"] = list(dict.fromkeys(merged_features))
            table[key] = final
        elif section == "package":
            table[key] = replaced = workspace_copy
            table[key] = workspace_dep

        return True