nixos-configuration/pkgs/by-name/de/den-http-get-updater/package.nix

170 lines
4.5 KiB
Nix

{
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 ''
for i in {{ 1..30 }}; do
nixUrlsResult=$(nix-instantiate --eval --json --strict \
"${prefetchUrlLocationShellEscape.file}" \
-A "${prefetchUrlLocationShellEscape.attrpath}"
)
if [[ "$?" == "0" ]]; then
break
elif [[ "$i" == 30 ]]; then
echo "error: prefetchUrlLocation failed - attempts exhausted" 1>&2
exit 1
fi
echo "prefetchUrlLocation failed (attempt $i)" 1>&2
sleep 2
done
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
'')