swiftpm2nix: reduce duplication in generated files

This commit is contained in:
Stéphan Kochen 2022-11-15 11:46:22 +01:00
parent 449e2f1b01
commit 9cb7163973
3 changed files with 69 additions and 41 deletions

View File

@ -1,4 +1,4 @@
{ lib, stdenv, makeWrapper, jq, nix-prefetch-git }:
{ lib, stdenv, callPackage, makeWrapper, jq, nix-prefetch-git }:
stdenv.mkDerivation {
name = "swiftpm2nix";
@ -15,6 +15,8 @@ stdenv.mkDerivation {
preferLocalBuild = true;
passthru = callPackage ./support.nix { };
meta = {
description = "Generate a Nix expression to fetch swiftpm dependencies";
maintainers = with lib.maintainers; [ dtzWill trepetti dduan trundle stephank ];

View File

@ -0,0 +1,56 @@
{ lib, fetchgit, formats }:
with lib;
let
json = formats.json { };
in rec {
# Derive a pin file from workspace state.
mkPinFile = workspaceState:
assert workspaceState.version == 5;
json.generate "Package.resolved" {
version = 1;
object.pins = map (dep: {
package = dep.packageRef.name;
repositoryURL = dep.packageRef.location;
state = dep.state.checkoutState;
}) workspaceState.object.dependencies;
};
# Make packaging helpers from swiftpm2nix generated output.
helpers = generated: let
inherit (import generated) workspaceStateFile hashes;
workspaceState = builtins.fromJSON (builtins.readFile workspaceStateFile);
pinFile = mkPinFile workspaceState;
in rec {
# Create fetch expressions for dependencies.
sources = listToAttrs (
map (dep: nameValuePair dep.subpath (fetchgit {
url = dep.packageRef.location;
rev = dep.state.checkoutState.revision;
sha256 = hashes.${dep.subpath};
})) workspaceState.object.dependencies
);
# Configure phase snippet for use in packaging.
configure = ''
mkdir -p .build/checkouts
ln -sf ${pinFile} ./Package.resolved
install -m 0600 ${workspaceStateFile} ./.build/workspace-state.json
''
+ concatStrings (mapAttrsToList (name: src: ''
ln -s '${src}' '.build/checkouts/${name}'
'') sources)
+ ''
# Helper that makes a swiftpm dependency mutable by copying the source.
swiftpmMakeMutable() {
local orig="$(readlink .build/checkouts/$1)"
rm .build/checkouts/$1
cp -r "$orig" .build/checkouts/$1
chmod -R u+w .build/checkouts/$1
}
'';
};
}

View File

@ -6,69 +6,39 @@
set -eu -o pipefail
shopt -s lastpipe
pinFile="Package.resolved"
stateFile=".build/workspace-state.json"
for file in $pinFile $stateFile; do
if [[ ! -f "$file" ]]; then
echo >&2 "Missing $file. Run 'swift package resolve' first."
exit 1
fi
done
if [[ "$(jq .version $pinFile)" != "1" ]]; then
echo >&2 "Unsupported $pinFile version"
if [[ ! -f "$stateFile" ]]; then
echo >&2 "Missing $stateFile. Run 'swift package resolve' first."
exit 1
fi
if [[ "$(jq .version $stateFile)" != "5" ]]; then
echo >&2 "Unsupported $stateFile version"
exit 1
fi
# Iterate dependencies and prefetch.
sources=""
hashes=""
jq -r '.object.dependencies[] | "\(.subpath) \(.packageRef.location) \(.state.checkoutState.revision)"' $stateFile \
| while read -r name url rev; do
echo >&2 "-- Fetching $name"
sha256="$(nix-prefetch-git $url $rev | jq -r .sha256)"
sources+="
\"$name\" = fetchgit {
url = \"$url\";
rev = \"$rev\";
sha256 = \"$sha256\";
};"
hashes+="
\"$name\" = \"$sha256\";"
echo >&2
done
sources+=$'\n'" "
hashes+=$'\n'" "
# Generate output.
mkdir -p nix
# Copy the pin file as-is.
cp $pinFile nix/Package.resolved
# Copy the workspace state, but clear 'artifacts'.
jq '.object.artifacts = []' < $stateFile > nix/workspace-state.json
# Build an expression for fetching sources, and preparing the working directory.
cat > nix/default.nix << EOF
# This file was generated by swiftpm2nix.
{ lib, fetchgit }: rec {
sources = {$sources};
configure = ''
mkdir -p .build/checkouts
ln -sf \${./Package.resolved} ./Package.resolved
install -m 0600 \${./workspace-state.json} ./.build/workspace-state.json
''
+ lib.concatStrings (lib.mapAttrsToList (name: src: ''
ln -s '\${src}' '.build/checkouts/\${name}'
'') sources)
+ ''
# Helper that makes a swiftpm dependency mutable by copying the source.
swiftpmMakeMutable() {
local orig="\$(readlink .build/checkouts/\$1)"
rm .build/checkouts/\$1
cp -r "\$orig" .build/checkouts/\$1
chmod -R u+w .build/checkouts/\$1
}
'';
{
workspaceStateFile = ./workspace-state.json;
hashes = {$hashes};
}
EOF
echo >&2 "-- Generated ./nix"