lang-bootstrap/06/download.sh

86 lines
2.6 KiB
Bash
Raw Normal View History

2025-04-18 12:41:04 +01:00
#!/usr/bin/env bash
# Receives files as arguments, scans them for lines like
# #> FETCH dd16fb1d67bfab79a72f5e8390735c49e3e8e70b4945a15ab1f81ddb78658fb3
# #> FROM http://ftp.gnu.org/gnu/make/make-4.4.1.tar.gz
# #> AS make.tar.gz
# or
# #local = "/downloads/make.tar.gz";
# url = "http://ftp.gnu.org/gnu/make/make-4.4.1.tar.gz";
# sha256 = "dd16fb1d67bfab79a72f5e8390735c49e3e8e70b4945a15ab1f81ddb78658fb3";
# downloads to ./downloads if file's not present there yet, verifies hash,
# copies file over to $DESTDIR.
set -ue
: ${DESTDIR:=stage/downloads} # final location of putting the file
: ${ONLY:=all} # allow to limit to just a single file
mkdir -p downloads # first cached there, so that stage can be cleaned freely
fetch() {
hash=$1; url=$2; filename=${3:-$(basename "$url")}
if [[ -e "downloads/$filename" ]]; then
pushd downloads >/dev/null
echo "$hash $filename" | sha256sum -c
popd >/dev/null
else
mkdir -p downloads/.tmp$$
pushd downloads/.tmp$$ >/dev/null
wget -nv --show-progress "$url" -O "$filename"
echo "$hash $filename" | sha256sum -c --quiet
popd >/dev/null
mv "downloads/.tmp$$/$filename" downloads/
rm -d downloads/.tmp$$
fi
if [[ "${DESTDIR:-}" != downloads ]]; then
mkdir -p "$DESTDIR"
cp -a --reflink=auto "downloads/$filename" \
"$DESTDIR/$filename"
fi
}
REGEX_MAGIC='^#> '
REGEX_FETCH='^#> FETCH'
REGEX_FROM='^#> FROM'
REGEX_AS='^#> AS'
NIX_REGEX_FETCH='^[[:blank:]]*sha256[[:blank:]]*=[[:blank:]]*"(.*)";$'
NIX_REGEX_FROM='^[[:blank:]]*url[[:blank:]]*=[[:blank:]]*"(.*)";$'
NIX_REGEX_AS='^[[:blank:]]*#[[:blank:]]local[[:blank:]]*=[[:blank:]]*/downloads/(.*);$'
process_commands_in() {
hash=''; url=''; filename=''
while read -r line; do
if [[ "$line" =~ $REGEX_MAGIC ]]; then
if [[ "$line" =~ $REGEX_FETCH ]]; then
hash="${line##"#> FETCH"}"
elif [[ "$line" =~ $REGEX_FROM ]]; then
url="${line##'#> FROM '}"
elif [[ "$line" =~ $REGEX_AS ]]; then
filename="${line##'#> AS '}"
else
echo "### $0: malformed line '$line' in '$1'"
exit 2
fi
elif [[ "$line" =~ $NIX_REGEX_FETCH ]]; then
hash=${BASH_REMATCH[1]}
elif [[ "$line" =~ $NIX_REGEX_FROM ]]; then
url=${BASH_REMATCH[1]}
elif [[ "$line" =~ $NIX_REGEX_AS ]]; then
filename=${BASH_REMATCH[1]}
else
if [[ -n "$hash" && -n "$url" ]]; then
filename=${filename:-$(basename $url)}
if [[ "$ONLY" == all || \
"$ONLY" == "$filename" ]]; then
fetch "$hash" "$url" "$filename"
fi
fi
hash=''; url=''; filename=''
fi
done < $1
}
[[ $# == 0 ]] && files='recipes/*.sh recipes/*/*.sh' || files="$@"
for f in $files; do
process_commands_in $f
done