Skip to content

Instantly share code, notes, and snippets.

@yrps
Last active July 5, 2017 02:07
Show Gist options
  • Save yrps/59728323e3d4c7c50a9d1fc9224f7586 to your computer and use it in GitHub Desktop.
Save yrps/59728323e3d4c7c50a9d1fc9224f7586 to your computer and use it in GitHub Desktop.
Get the latest LineageOS build
#!/bin/bash
set -eu
max_days=5
dev=hammerhead
cachedir="$XDG_CACHE_HOME/lineageos"
builds="$dev.builds"
dlpage=https://download.lineageos.org/
targetdir=/data/data/org.lineageos.updater/app_updates/
sigurl=https://github.com/LineageOS/lineage_wiki/raw/master/pages/meta/verifying_builds.md
usage() {
cat << USAGE
Synopsis: Download, verify, and push the latest Lineage OS build.
Usage: $(basename "$0") [ -d DEVICE ] [ -m MAX_DAYS ] ACTION1 [ ACTION2 ... ]
DEVICE is a supported device codename. Default $dev.
See $dlpage for availability.
The cache file is updated if MAX_DAYS have passed since the latest build shown
in it. Default $max_days. An update is always done if it is missing.
The cache file and downloads are located in $cachedir.
Supported ACTIONs are:
dl
Download the latest build listed in the cache file.
check
Verify downloaded builds against the sha256s given in the cache file.
Implied by dl.
keycheck
Verifies the PGP signature in the latest build against the one on
LineageOS's Github repository. Requires the Java keytool utility.
push
"adb push" the latest build to the device.
The zip is placed where the updater app expects to find it.
check_adb
"adb sha256sum" the zip file on the device. Implied by push.
clean
Delete all builds except the newest from the cache directory.
clean_adb
Delete all builds except the newest from the device.
The adb commands (push, check_adb, clean_adb) require the device to be
connected, and adbd on the host that is allowed root on the device.
USAGE
exit "${1:-0}"
}
while getopts m:d:h opt; do
case $opt in
d) dev="$OPTARG" ;;
m) max_days="$OPTARG" ;;
h) usage ;;
?) usage 2 ;;
esac
done
shift $((OPTIND - 1))
[ $# -gt 0 ] || usage 1
_getzipurl() {
# Get the download url for the latest zip.
local cachedate cacheage
_getvars() {
zipurl="$(sed 1q "$builds")"
zipfile="$(basename "$zipurl")"
sha256="${zipfile%.zip}.sha256"
}
_getsha256() {
# Get the latest build list and the sha256sum file of the latest build.
curl --silent --show-error --location "$dlpage$dev" |
sed -n '/sha256/ s/.*"\(https.*\.zip\)".*/\1/p' > "$builds"
[ -s "$builds" ] || {
>&2 echo "Couldn't get the cache. Page scraper may need updating."
exit 1
}
_getvars
curl "$zipurl"'?sha256' > "$sha256"
}
_cacheinvalid() {
# Assert that there is a date in line 1 of the build list and extract it.
cachedate="$(awk '
NF == 1 && $1 ~ /^https:\/\/[^/]*lineageos.org\// {
print( substr( $1, match( $1, /[^0-9][0-9]{8}[^0-9]/) + 1, 8 ) )
}
NR == 1 { exit }' "$builds")"
[ -z "$cachedate" ]
}
_cacheold() {
# Check if $cachedate is over $max_days old.
cacheage=$(( ( $(date +%s) - $(date -d "$cachedate" +%s) ) / ( 24 * 60 * 60 ) ))
echo "Latest build in cachefile is $cacheage-day-old $cachedate."
[ "$cacheage" -gt "$max_days" ]
}
if [ ! -s "$builds" ]; then
echo "No cache; downloading..."
_getsha256
elif _cacheinvalid; then
echo "No date found in $sha256; downloading..."
_getsha256
elif _cacheold; then
echo "Cache stale; downloading..."
_getsha256
else
echo "Cache good..."
_getvars
fi
[ -n "$zipurl" ]
}
dl() {
if check; then
echo "Already have $zipfile downloaded."
return
fi
echo "Downloading $zipfile..."
curl --location --remote-name --continue - "$zipurl"
}
check() {
[ -e "$zipfile" ] || {
echo "Latest build $zipfile is not in cache."
return 1
}
sha256sum --check "$sha256"
}
keycheck() {
local zipsig srcsig
zipsig="$(keytool -list -printcert -jarfile "$zipfile" |
sed -n '/^Certificate fingerprints:/,+3 s/^\s*//p')"
printf "%s:\n%s\n\n" "$zipfile" "$zipsig"
srcsig="$(curl -sL "$sigurl" |
sed -n '/^Certificate fingerprints:/,+3 s/^\s*//p')"
printf "%s:\n%s\n\n" "$sigurl" "$srcsig"
[ "$zipsig" = "$srcsig" ]
}
push() {
if check_adb; then
echo "Already have $zipfile on the device."
return
fi
echo "Pushing $zipfile to $targetdir..."
adb push "$zipfile" "$sha256" "$targetdir"
# De-root the pushed files.
adb shell "
cd $targetdir &&
chmod 600 lineage-*-$dev-signed.* &&
chown \$(stat -c %U:%G .) lineage-*-$dev-signed.*"
}
check_adb() {
adb root || return
adb shell "
cd $targetdir || exit 1
[ -e $zipfile ] || {
echo 'Latest build $zipfile is not on device.'
exit 1
}
sha256sum -c $sha256"
}
clean() {
echo "Removing old builds and checksums from cache..."
find "$cachedir" -maxdepth 1 \( -name "lineage-*-$dev-signed.zip" -o \
-name "lineage-*-$dev-signed.sha256" \) \
! -name "$zipfile" ! -name "$sha256" -delete -print
}
clean_adb() {
adb root || return
adb shell "
echo 'Removing old builds and checksums from device...'
find $targetdir -maxdepth 1 \( -name 'lineage*-$dev-signed.zip' -o \
-name 'lineage*-$dev-signed.sha256' \) \
-not -name $zipfile -not -name $sha256 -delete -print"
}
mkdir -p "$cachedir"
(
cd "$cachedir" || exit
_getzipurl || exit
for arg; do
"$arg" || exit
done
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment