diff --git a/pkgs/development/tools/swiftpm2nix/default.nix b/pkgs/development/tools/swiftpm2nix/default.nix index d115a6d5373b..25d6b06ef98b 100644 --- a/pkgs/development/tools/swiftpm2nix/default.nix +++ b/pkgs/development/tools/swiftpm2nix/default.nix @@ -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 ]; diff --git a/pkgs/development/tools/swiftpm2nix/support.nix b/pkgs/development/tools/swiftpm2nix/support.nix new file mode 100644 index 000000000000..94076517ebfc --- /dev/null +++ b/pkgs/development/tools/swiftpm2nix/support.nix @@ -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 + } + ''; + + }; + +} diff --git a/pkgs/development/tools/swiftpm2nix/swiftpm2nix.sh b/pkgs/development/tools/swiftpm2nix/swiftpm2nix.sh index 13e8a42a7dd7..72051b4e448d 100755 --- a/pkgs/development/tools/swiftpm2nix/swiftpm2nix.sh +++ b/pkgs/development/tools/swiftpm2nix/swiftpm2nix.sh @@ -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"