crane/lib/downloadCargoPackageFromGit.nix
Ivan Petkov 00564437f3
Properly handle workspace inheritance in git dependencies (#224)
Crates from git repos are vendored in a flattened directory where each crate shows up at the root of the vendor directory. Since the vendoring step effectively breaks workspace structures, any crates which use workspace inheritance (e.g. package.version.workspace = true will fail to resolve.

To work around this we inspect the crate's workspace manifest (if it exists) and attempt to manually merge the values while copying the contents to the vendor directory.
2023-01-21 16:46:32 -08:00

56 lines
1.2 KiB
Nix

{ cargo
, craneUtils
, jq
, lib
, runCommandLocal
}:
{ git
, rev
, ref ? null
, allRefs ? ref == null
}:
let
maybeRef = lib.optionalAttrs (ref != null) { inherit ref; };
repo = builtins.fetchGit (maybeRef // {
inherit allRefs rev;
url = git;
submodules = true;
});
deps = {
nativeBuildInputs = [
cargo
craneUtils
jq
];
};
in
runCommandLocal "cargo-git" deps ''
mkdir -p $out
existing_crates=()
while read -r cargoToml; do
local crate=$(
cargo metadata --format-version 1 --no-deps --manifest-path "$cargoToml" |
jq -r '.packages[] | select(.manifest_path == "'"$cargoToml"'") | "\(.name)-\(.version)"'
)
if [ -n "$crate" ]; then
if [[ " ''${existing_crates[*]} " =~ " $crate " ]]; then
>&2 echo "warning: skipping duplicate package $crate found at $cargoToml"
continue
fi
local dest="$out/$crate"
cp -r "$(dirname "$cargoToml")" "$dest"
chmod +w "$dest"
echo '{"files":{}, "package":null}' > "$dest/.cargo-checksum.json"
crane-resolve-workspace-inheritance "$cargoToml" > "$dest/Cargo.toml.resolved" &&
mv "$dest/Cargo.toml"{.resolved,}
existing_crates+=("$crate")
fi
done < <(find ${repo} -name Cargo.toml)
''