{ lib, curl, gnused, jq, nix, writeScript, }: { # location of file to modify fileLocation, previousVersion, versionUrl, # { # fileLocation: string?; # previousHash: string; # prefetchUrlLocation: { # file: string; # attrpath: string[]' # }; # prefetchHash: string?; # targetHash: string?; # unpack: bool?; # name: string?; # }[] # prefetchList ? [], # extra packages to add to the path extraPackages ? [], # change newVersion variable in it, if the contents of the page # is not plaintext version # (json for example) contentParser ? "echo \"$newVersion\"", unpack ? true, hashAlgo ? "sha256", hashFormat ? "sri", }: let realFileLocation = builtins.toString fileLocation; prefetchList' = lib.map (x: assert builtins.isNull x.prefetchUrlLocation || lib.isAttrs x.prefetchUrlLocation; assert lib.isAttrs x.prefetchUrlLocation && ( lib.isString x.prefetchUrlLocation.file or null || lib.isPath x.prefetchUrlLocation.file or null ); assert lib.isAttrs x.prefetchUrlLocation && lib.isString x.prefetchUrlLocation.attrpath or null; rec { inherit fileLocation hashAlgo hashFormat unpack; name = if x.unpack or unpack then "source" else null; mark = builtins.hashString "sha256" x.previousHash; markRegexEscape = lib.escapeRegex mark; realFileLocation = builtins.toString x.fileLocation or fileLocation; realFileLocationShellEscape = lib.escapeShellArg realFileLocation; prefetchUrlLocationShellEscape = lib.mapAttrs (_: lib.escapeShellArg) x.prefetchUrlLocation; previousHashRegexEscape = lib.escapeRegex x.previousHash; } // x) prefetchList; realFileLocationShellEscape = lib.escapeShellArg realFileLocation; versionUrlShellEscape = lib.escapeShellArg versionUrl; previousVersionRegexEscape = lib.escapeRegex previousVersion; path = lib.makeBinPath ([ curl gnused jq nix ] ++ extraPackages); in writeScript "den-http-get-updater" ('' PATH="${lib.escapeShellArg path}" prefetchFailed= newVersion=$(curl -L "${versionUrlShellEscape}") if [[ "$?" != 0 ]]; then echo "error: fetching new version failed" 1>&2 exit 1 fi newVersion=$(${contentParser}) sed -Ei "s!${previousVersionRegexEscape}!$newVersion!g" "${realFileLocationShellEscape}" '' # invalidate hashes + lib.concatStringsSep "\n" (lib.map ({ mark, previousHash, previousHashRegexEscape, realFileLocationShellEscape, ... }: '' sed -Ei "s!${previousHashRegexEscape}!${mark}!g" "${realFileLocationShellEscape}" '') prefetchList') + lib.concatStringsSep "\n" (lib.map ({ fileLocation, markRegexEscape, name, prefetchUrlLocationShellEscape, realFileLocationShellEscape, unpack, ... }: let nixUnpack = lib.optionalString unpack "--unpack"; nixName = lib.optionalString (!builtins.isNull name) "--name \"${lib.escapeShellArg name}\""; in '' nixUrlsResult=$(nix-instantiate --eval --json --strict \ "${prefetchUrlLocationShellEscape.file}" \ -A "${prefetchUrlLocationShellEscape.attrpath}" ) urlsType=$(jq -rc 'type' <<< "$nixUrlsResult") if [ "$urlsType" = "array" ]; then readarray -t prefetchUrls < <( jq -rc '.[]' <<< "$nixUrlsResult" ) elif [ "$urlsType" = "string" ]; then readarray -t prefetchUrls < <( jq -rc '.' <<< "$nixUrlsResult" ) fi prefetchSucceeded=1 for url in "''${prefetchUrls[@]}"; do echo "trying prefetch '$url'..."; expectedHash=$(nix-prefetch-url "$url" ${nixUnpack} ${nixName} --type "${hashAlgo}") expectedHash=$(nix --extra-experimental-features "nix-command" hash convert \ --hash-algo "${hashAlgo}" \ --to "${hashFormat}" \ "$expectedHash" ) if [[ -n $expectedHash ]]; then echo "prefetch succeeded!" echo "hash: $expectedHash" sed -Ei "s!${markRegexEscape}!$expectedHash!g" "${realFileLocationShellEscape}" prefetchSucceeded= break fi done if [[ -n "$prefetchSucceeded" ]]; then echo "warning: prefetch failed" 1>&2 prefetchFailed=1 fi '') (lib.filter (x: !builtins.isNull x.prefetchUrlLocation) prefetchList')) + '' if [[ -n "$prefetchFailed" ]]; then exit 1 fi '')