Last active
July 5, 2017 02:07
-
-
Save yrps/59728323e3d4c7c50a9d1fc9224f7586 to your computer and use it in GitHub Desktop.
Get the latest LineageOS build
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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