131 lines
3.5 KiB
Bash
Executable File
131 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# This file is part of I38.
|
|
#
|
|
# I38 is free software: you can redistribute it and/or modify it under the terms
|
|
# of the GNU General Public License as published by the Free Software
|
|
# Foundation, either version 3 of the License, or (at your option) any later
|
|
# version.
|
|
|
|
set -u
|
|
|
|
remoteUrl="${I38_UPDATE_REMOTE_URL:-https://git.stormux.org/storm/I38}"
|
|
remoteRef="${I38_UPDATE_REMOTE_REF:-refs/heads/master}"
|
|
initialDelay="${I38_UPDATE_INITIAL_DELAY:-90}"
|
|
checkInterval="${I38_UPDATE_CHECK_INTERVAL:-21600}"
|
|
notifyInterval="${I38_UPDATE_NOTIFY_INTERVAL:-604800}"
|
|
networkTimeout="${I38_UPDATE_NETWORK_TIMEOUT:-20}"
|
|
|
|
scriptDir="$(unset CDPATH; cd -- "$(dirname -- "$0")" && pwd)"
|
|
i3Dir="$(dirname -- "$scriptDir")"
|
|
versionFile="${I38_VERSION_FILE:-${i3Dir}/i38-version}"
|
|
stateDir="${XDG_STATE_HOME:-${HOME}/.local/state}/I38"
|
|
notifyState="${stateDir}/update-check-notified"
|
|
runtimeDir="${XDG_RUNTIME_DIR:-/tmp}"
|
|
lockDir="${runtimeDir}/i38-update-check"
|
|
|
|
valid_commit() {
|
|
[[ "${1:-}" =~ ^[0-9a-fA-F]{40}$ ]]
|
|
}
|
|
|
|
read_installed_commit() {
|
|
local commit
|
|
|
|
[[ -r "$versionFile" ]] || return 1
|
|
IFS= read -r commit < "$versionFile" || return 1
|
|
valid_commit "$commit" || return 1
|
|
printf '%s\n' "$commit"
|
|
}
|
|
|
|
read_remote_commit() {
|
|
local output commit
|
|
|
|
if command -v timeout > /dev/null; then
|
|
output="$(timeout "$networkTimeout" git ls-remote "$remoteUrl" "$remoteRef" 2> /dev/null)" || return 1
|
|
else
|
|
output="$(git ls-remote "$remoteUrl" "$remoteRef" 2> /dev/null)" || return 1
|
|
fi
|
|
commit="${output%%[[:space:]]*}"
|
|
valid_commit "$commit" || return 1
|
|
printf '%s\n' "$commit"
|
|
}
|
|
|
|
already_notified() {
|
|
local remoteCommit="$1"
|
|
local lastCommit lastTime now
|
|
|
|
[[ -r "$notifyState" ]] || return 1
|
|
{
|
|
IFS= read -r lastCommit
|
|
IFS= read -r lastTime
|
|
} < "$notifyState" || return 1
|
|
|
|
[[ "$lastCommit" == "$remoteCommit" ]] || return 1
|
|
[[ "$lastTime" =~ ^[0-9]+$ ]] || return 1
|
|
now="$(date +%s)"
|
|
(( now - lastTime < notifyInterval ))
|
|
}
|
|
|
|
remember_notification() {
|
|
local remoteCommit="$1"
|
|
|
|
mkdir -p "$stateDir" || return 0
|
|
{
|
|
printf '%s\n' "$remoteCommit"
|
|
date +%s
|
|
} > "$notifyState" 2> /dev/null || true
|
|
}
|
|
|
|
send_update_notification() {
|
|
local remoteCommit="$1"
|
|
|
|
notify-send \
|
|
"I38 update available" \
|
|
"A newer I38 version is available. Update your checkout, then run i38.sh -u or rerun i38.sh to refresh your setup." \
|
|
2> /dev/null || return 1
|
|
remember_notification "$remoteCommit"
|
|
}
|
|
|
|
stop_update_check() {
|
|
rm -rf "$lockDir"
|
|
exit 0
|
|
}
|
|
|
|
if ! command -v git > /dev/null || ! command -v notify-send > /dev/null; then
|
|
exit 0
|
|
fi
|
|
|
|
if [[ -d "$lockDir" ]]; then
|
|
if [[ -f "${lockDir}/pid" ]]; then
|
|
IFS= read -r existingPid < "${lockDir}/pid" || existingPid=""
|
|
if [[ "$existingPid" =~ ^[0-9]+$ ]] && kill -0 "$existingPid" 2> /dev/null; then
|
|
exit 0
|
|
fi
|
|
fi
|
|
rm -rf "$lockDir"
|
|
fi
|
|
|
|
if ! mkdir "$lockDir" 2> /dev/null; then
|
|
exit 0
|
|
fi
|
|
printf '%s\n' "$$" > "${lockDir}/pid"
|
|
trap 'rm -rf "$lockDir"' EXIT
|
|
trap stop_update_check INT TERM
|
|
|
|
sleep "$initialDelay"
|
|
|
|
while :; do
|
|
installedCommit="$(read_installed_commit)" || exit 0
|
|
remoteCommit="$(read_remote_commit)"
|
|
remoteStatus=$?
|
|
|
|
if [[ $remoteStatus -eq 0 && "$remoteCommit" != "$installedCommit" ]]; then
|
|
if ! already_notified "$remoteCommit"; then
|
|
send_update_notification "$remoteCommit"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
sleep "$checkInterval"
|
|
done
|