From 1726304559622bcd20c8e3b7006b41a09bada599 Mon Sep 17 00:00:00 2001 From: GGG Date: Thu, 5 Dec 2024 19:18:03 -0300 Subject: [PATCH] nuget-to-json: init --- .../by-name/nu/nuget-to-json/nuget-to-json.sh | 119 ++++++++++++++++++ pkgs/by-name/nu/nuget-to-json/package.nix | 37 ++++++ 2 files changed, 156 insertions(+) create mode 100755 pkgs/by-name/nu/nuget-to-json/nuget-to-json.sh create mode 100644 pkgs/by-name/nu/nuget-to-json/package.nix diff --git a/pkgs/by-name/nu/nuget-to-json/nuget-to-json.sh b/pkgs/by-name/nu/nuget-to-json/nuget-to-json.sh new file mode 100755 index 000000000000..ff29f414d5b9 --- /dev/null +++ b/pkgs/by-name/nu/nuget-to-json/nuget-to-json.sh @@ -0,0 +1,119 @@ +#!@runtimeShell@ +# shellcheck shell=bash + +set -euo pipefail +shopt -s nullglob + +export SSL_CERT_FILE=@cacert@/etc/ssl/certs/ca-bundle.crt +export PATH="@binPath@:$PATH" +# used for glob ordering of package names +export LC_ALL=C + +if [ $# -eq 0 ]; then + >&2 echo "Usage: $0 [path to a file with a list of excluded packages] > deps.json" + exit 1 +fi + +pkgs=$1 +tmp=$(realpath "$(mktemp -td nuget-to-json.XXXXXX)") +trap 'rm -r "$tmp"' EXIT + +excluded_list=$(realpath "${2:-/dev/null}") + +export DOTNET_NOLOGO=1 +export DOTNET_CLI_TELEMETRY_OPTOUT=1 + +mapfile -t sources < <(dotnet nuget list source --format short | awk '/^E / { print $2 }') +wait "$!" + +declare -a remote_sources +declare -A base_addresses + +for index in "${sources[@]}"; do + if [[ -d "$index" ]]; then + continue + fi + + remote_sources+=("$index") + + base_address=$( + curl --compressed --netrc -fsL "$index" | + jq -r '.resources[] | select(."@type" == "PackageBaseAddress/3.0.0")."@id"' + ) + if [[ ! "$base_address" == */ ]]; then + base_address="$base_address/" + fi + base_addresses[$index]="$base_address" +done + +( + echo '[' + + first=true + cd "$pkgs" + for package in *; do + [[ -d "$package" ]] || continue + cd "$package" + for version in *; do + id=$(xmlstarlet sel -t -v /_:package/_:metadata/_:id "$version"/*.nuspec) + + if grep -qxF "$id.$version.nupkg" "$excluded_list"; then + continue + fi + + # packages in the nix store should have an empty metadata file + used_source="$(jq -r '.source // ""' "$version"/.nupkg.metadata)" + found=false + + if [[ -z "$used_source" || -d "$used_source" ]]; then + continue + fi + + for source in "${remote_sources[@]}"; do + url="${base_addresses[$source]}$package/$version/$package.$version.nupkg" + if [[ "$source" == "$used_source" ]]; then + hash="$(nix-hash --type sha256 --flat --sri "$version/$package.$version".nupkg)" + found=true + break + else + if hash=$(nix-prefetch-url "$url" 2>"$tmp"/error); then + hash="$(nix-hash --to-sri --type sha256 "$hash")" + # If multiple remote sources are enabled, nuget will try them all + # concurrently and use the one that responds first. We always use the + # first source that has the package. + echo "$package $version is available at $url, but was restored from $used_source" 1>&2 + found=true + break + else + if ! grep -q 'HTTP error 404' "$tmp/error"; then + cat "$tmp/error" 1>&2 + exit 1 + fi + fi + fi + done + + if [[ $found = false ]]; then + echo "couldn't find $package $version" >&2 + exit 1 + fi + + if [[ $first = false ]]; then + echo ' , {' + else + echo ' {' + fi + echo " \"pname\": \"$id\"" + echo " , \"version\": \"$version\"" + echo " , \"hash\": \"$hash\"" + if [[ "$source" != https://api.nuget.org/v3/index.json ]]; then + echo " , \"url\": \"$url\"" + fi + echo ' }' + first=false + done + cd .. + done + + echo ']' +) | jq . diff --git a/pkgs/by-name/nu/nuget-to-json/package.nix b/pkgs/by-name/nu/nuget-to-json/package.nix new file mode 100644 index 000000000000..6a2be3060576 --- /dev/null +++ b/pkgs/by-name/nu/nuget-to-json/package.nix @@ -0,0 +1,37 @@ +{ + lib, + runtimeShell, + substituteAll, + nix, + coreutils, + jq, + xmlstarlet, + curl, + gnugrep, + gawk, + cacert, +}: + +substituteAll { + name = "nuget-to-json"; + dir = "bin"; + + src = ./nuget-to-json.sh; + isExecutable = true; + + inherit runtimeShell cacert; + binPath = lib.makeBinPath [ + nix + coreutils + jq + xmlstarlet + curl + gnugrep + gawk + ]; + + meta = { + description = "Convert a nuget packages directory to a lockfile for buildDotnetModule"; + mainProgram = "nuget-to-json"; + }; +}