{ lib, curl, gawk, jq, nix, writeScript, }: { # location of file to modify fileLocation, previousVersion, versionUrl, # { # fileLocation: string?; # previousHash: string; # prefetchUrlLocation: { # file: string; # attrpath: 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, name ? if unpack then "source" else null, }: 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; mark = builtins.hashString "sha256" x.previousHash; markShellEscape = lib.escapeShellArg mark; markShellRegexEscape = lib.escapeShellArg (lib.escapeRegex mark); realFileLocation = builtins.toString x.fileLocation or fileLocation; realFileLocationShellEscape = lib.escapeShellArg realFileLocation; prefetchUrlLocationShellEscape = lib.mapAttrs (_: lib.escapeShellArg) x.prefetchUrlLocation; previousHashShellRegexEscape = lib.escapeShellArg (lib.escapeRegex x.previousHash); } // x) prefetchList; realFileLocation' = lib.escapeShellArg realFileLocation; versionUrl' = lib.escapeShellArg versionUrl; previousVersion'' = lib.escapeShellArg (lib.escapeRegex previousVersion); nixUnpack = lib.optionalString unpack "--unpack"; nixName = lib.optionalString (!builtins.isNull name) "--name \"${lib.escapeShellArg name}\""; path = lib.makeBinPath ([ curl gawk jq nix ] ++ extraPackages); in writeScript "den-http-get-updater" ('' PATH="${lib.escapeShellArg path}" prefetchFailed= newVersion=$(curl -L "${versionUrl'}") if [[ "$?" != 0 ]]; then echo "error: fetching new version failed" 1>&2 exit 1 fi newVersion=$(${contentParser}) awk -i inplace "{ sub(/${previousVersion''}/, \"$newVersion\") }1" "${realFileLocation'}" '' # invalidate hashes + lib.concatStringsSep "\n" (lib.map ({ markShellEscape, previousHash, previousHashShellRegexEscape, realFileLocationShellEscape, ... }: '' awk -i inplace "{ sub(/${previousHashShellRegexEscape}/, \"${markShellEscape}\") }1" "${realFileLocationShellEscape}" '') prefetchList') + lib.concatStringsSep "\n" (lib.map ({ fileLocation, markShellRegexEscape, prefetchUrlLocationShellEscape, realFileLocationShellEscape, ... }: '' nixUrlsResult=$(nix-instantiate --eval --json \ "${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}) if [[ -n $expectedHash ]]; then echo "prefetch succeeded!" echo "hash: $expectedHash" awk -i inplace "{ sub(/${markShellRegexEscape}/, \"$expectedHash\") }1" "${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 '')