1b507bea4d
Previously, we escaped the old version in place for use in sed commands, and then had to use that in error messages. We can do better.
175 lines
5.6 KiB
Bash
Executable file
175 lines
5.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
||
set -e
|
||
|
||
scriptName=update-source-versions # do not use the .wrapped name
|
||
|
||
die() {
|
||
echo "$scriptName: error: $1" >&2
|
||
exit 1
|
||
}
|
||
|
||
usage() {
|
||
echo "Usage: $scriptName <attr> <version> [<new-source-hash>] [<new-source-url>]"
|
||
echo " [--version-key=<version-key>] [--system=<system>] [--file=<file-to-update>]"
|
||
}
|
||
|
||
args=()
|
||
|
||
for arg in "$@"; do
|
||
case $arg in
|
||
--system=*)
|
||
systemArg="--system ${arg#*=}"
|
||
;;
|
||
--version-key=*)
|
||
versionKey="${arg#*=}"
|
||
;;
|
||
--file=*)
|
||
nixFile="${arg#*=}"
|
||
if [ ! -f "$nixFile" ]; then
|
||
die "Could not find provided file $nixFile"
|
||
fi
|
||
;;
|
||
--ignore-same-hash)
|
||
ignoreSameHash="true"
|
||
;;
|
||
--help)
|
||
usage
|
||
exit 0
|
||
;;
|
||
--*)
|
||
echo "$scriptName: Unknown argument: " $arg
|
||
usage
|
||
exit 1
|
||
;;
|
||
*)
|
||
args["${#args[*]}"]=$arg
|
||
;;
|
||
esac
|
||
done
|
||
|
||
attr=${args[0]}
|
||
newVersion=${args[1]}
|
||
newHash=${args[2]}
|
||
newUrl=${args[3]}
|
||
|
||
if [ "${#args[*]}" -lt 2 ]; then
|
||
echo "$scriptName: Too few arguments"
|
||
usage
|
||
exit 1
|
||
fi
|
||
|
||
if [ "${#args[*]}" -gt 4 ]; then
|
||
echo "$scriptName: Too many arguments"
|
||
usage
|
||
exit 1
|
||
fi
|
||
|
||
if [ -z "$versionKey" ]; then
|
||
versionKey=version
|
||
fi
|
||
|
||
if [ -z "$nixFile" ]; then
|
||
nixFile=$(nix-instantiate $systemArg --eval --strict -A "$attr.meta.position" | sed -re 's/^"(.*):[0-9]+"$/\1/')
|
||
if [ ! -f "$nixFile" ]; then
|
||
die "Couldn't evaluate '$attr.meta.position' to locate the .nix file!"
|
||
fi
|
||
fi
|
||
|
||
oldHashAlgo=$(nix-instantiate $systemArg --eval --strict -A "$attr.src.drvAttrs.outputHashAlgo" | tr -d '"')
|
||
oldHash=$(nix-instantiate $systemArg --eval --strict -A "$attr.src.drvAttrs.outputHash" | tr -d '"')
|
||
|
||
if [ -z "$oldHashAlgo" -o -z "$oldHash" ]; then
|
||
die "Couldn't evaluate old source hash from '$attr.src'!"
|
||
fi
|
||
|
||
if [ $(grep -c "$oldHash" "$nixFile") != 1 ]; then
|
||
die "Couldn't locate old source hash '$oldHash' (or it appeared more than once) in '$nixFile'!"
|
||
fi
|
||
|
||
oldUrl=$(nix-instantiate $systemArg --eval -E "with import ./. {}; builtins.elemAt $attr.src.drvAttrs.urls 0" | tr -d '"')
|
||
|
||
if [ -z "$oldUrl" ]; then
|
||
oldUrl=$(nix-instantiate $systemArg --eval -E "with import ./. {}; $attr.src.url" | tr -d '"')
|
||
|
||
if [ -z "$oldUrl" ]; then
|
||
die "Couldn't evaluate source url from '$attr.src'!"
|
||
fi
|
||
fi
|
||
|
||
drvName=$(nix-instantiate $systemArg --eval -E "with import ./. {}; (builtins.parseDrvName $attr.name).name" | tr -d '"')
|
||
oldVersion=$(nix-instantiate $systemArg --eval -E "with import ./. {}; $attr.${versionKey} or (builtins.parseDrvName $attr.name).version" | tr -d '"')
|
||
|
||
if [ -z "$drvName" -o -z "$oldVersion" ]; then
|
||
die "Couldn't evaluate name and version from '$attr.name'!"
|
||
fi
|
||
|
||
if [ "$oldVersion" = "$newVersion" ]; then
|
||
echo "$scriptName: New version same as old version, nothing to do." >&2
|
||
exit 0
|
||
fi
|
||
|
||
# Escape regex metacharacter that are allowed in store path names
|
||
oldVersionEscaped=$(echo "$oldVersion" | sed -re 's|[.+]|\\&|g')
|
||
oldUrlEscaped=$(echo "$oldUrl" | sed -re 's|[${}.+]|\\&|g')
|
||
|
||
if [ $(grep -c -E "^\s*(let\b)?\s*$versionKey\s*=\s*\"$oldVersionEscaped\"" "$nixFile") = 1 ]; then
|
||
pattern="/\b$versionKey\b\s*=/ s|\"$oldVersionEscaped\"|\"$newVersion\"|"
|
||
elif [ $(grep -c -E "^\s*(let\b)?\s*name\s*=\s*\"[^\"]+-$oldVersionEscaped\"" "$nixFile") = 1 ]; then
|
||
pattern="/\bname\b\s*=/ s|-$oldVersionEscaped\"|-$newVersion\"|"
|
||
else
|
||
die "Couldn't figure out where out where to patch in new version in '$attr'!"
|
||
fi
|
||
|
||
# Replace new version
|
||
sed -i.bak "$nixFile" -re "$pattern"
|
||
if cmp -s "$nixFile" "$nixFile.bak"; then
|
||
die "Failed to replace version '$oldVersion' to '$newVersion' in '$attr'!"
|
||
fi
|
||
|
||
# Replace new URL
|
||
if [ -n "$newUrl" ]; then
|
||
sed -i "$nixFile" -re "s|\"$oldUrlEscaped\"|\"$newUrl\"|"
|
||
|
||
if cmp -s "$nixFile" "$nixFile.bak"; then
|
||
die "Failed to replace source URL '$oldUrl' to '$newUrl' in '$attr'!"
|
||
fi
|
||
fi
|
||
|
||
case "$oldHashAlgo" in
|
||
sha256) hashLength=64 ;;
|
||
sha512) hashLength=128 ;;
|
||
*) die "Unhandled hash algorithm '$oldHashAlgo' in '$attr'!" ;;
|
||
esac
|
||
|
||
# Make a temporary all-zeroes hash of $hashLength characters
|
||
tempHash=$(printf '%0*d' "$hashLength" 0)
|
||
|
||
sed -i "$nixFile" -re "s|\"$oldHash\"|\"$tempHash\"|"
|
||
if cmp -s "$nixFile" "$nixFile.bak"; then
|
||
die "Failed to replace source hash of '$attr' to a temporary hash!"
|
||
fi
|
||
|
||
# If new hash not given on the command line, recalculate it ourselves.
|
||
if [ -z "$newHash" ]; then
|
||
nix-build $systemArg --no-out-link -A "$attr.src" 2>"$attr.fetchlog" >/dev/null || true
|
||
# FIXME: use nix-build --hash here once https://github.com/NixOS/nix/issues/1172 is fixed
|
||
newHash=$(egrep -v "killing process|dependencies couldn't be built|wanted: " "$attr.fetchlog" | tail -n2 | sed "s~output path .* has .* hash ‘\(.*\)’ when .* was expected\|fixed-output derivation produced path '.*' with .* hash '\(.*\)' instead of the expected hash '.*'\| got: .*:\(.*\)~\1\2\3~" | head -n1)
|
||
fi
|
||
|
||
if [ -z "$newHash" ]; then
|
||
cat "$attr.fetchlog" >&2
|
||
die "Couldn't figure out new hash of '$attr.src'!"
|
||
fi
|
||
|
||
if [ -z "${ignoreSameHash}" ] && [ "$oldVersion" != "$newVersion" ] && [ "$oldHash" = "$newHash" ]; then
|
||
mv "$nixFile.bak" "$nixFile"
|
||
die "Both the old and new source hashes of '$attr.src' were equivalent. Please fix the package's source URL to be dependent on '\${version}'!"
|
||
fi
|
||
|
||
sed -i "$nixFile" -re "s|\"$tempHash\"|\"$newHash\"|"
|
||
if cmp -s "$nixFile" "$nixFile.bak"; then
|
||
die "Failed to replace temporary source hash of '$attr' to the final source hash!"
|
||
fi
|
||
|
||
rm -f "$nixFile.bak"
|
||
rm -f "$attr.fetchlog"
|