shellcheck / shellcheck (push) Failing after 19s
A sibling's version is its latest git tag (v1.4.0, or v1.4.0+3 for commits after it), or, without tags, its commit's date and short hash, like CoreDesktop's own. The version shown as available is that of the newest commit on the default branch, which is what update installs. sibling list shows each sibling's version. sibling check fetches every sibling at once and shows which have a newer version, and sibling update [name...] updates the named siblings or all of them. 71-siblings.sh now runs sibling update, so update and version share one way of updating. version lists the installed siblings with any newer version and, when run in a terminal, asks for each one whether to update it now. version --check and the update notification still only look at CoreDesktop. The sibling skill docs describe how to release a version by tagging it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
177 lines
5.9 KiB
Bash
Executable File
177 lines
5.9 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Purpose : Show which version of CoreDesktop this machine is running
|
|
#
|
|
# CoreDesktop is a rolling release, so its version is the date of the commit
|
|
# the local checkout is on, plus the short hash to tell same-day commits apart,
|
|
# e.g. 2026.10.22 (c5f0651). The kernel and video driver are shown separately
|
|
# because they come from Arch, not CoreDesktop, along with any newer release of
|
|
# either that update would install.
|
|
#
|
|
# Sibling projects (see sibling) are listed with their versions too. If any has
|
|
# a newer version, version asks, for each one, whether to update it now.
|
|
#
|
|
# version --check prints the newer version and exits 0 if one is available,
|
|
# exits 1 if this machine is up to date, or 2 if it couldn't check.
|
|
|
|
COREDESKTOP="$HOME/.local/share/coredesktop"
|
|
|
|
source "$COREDESKTOP/utils.sh"
|
|
|
|
if ! git -C "$COREDESKTOP" rev-parse --git-dir &> /dev/null; then
|
|
echo "CoreDesktop isn't installed in $COREDESKTOP."
|
|
exit 2
|
|
fi
|
|
|
|
# Version string for a commit, e.g. 2026.10.22 (c5f0651)
|
|
describe() {
|
|
git -C "$COREDESKTOP" log -1 --format='%cd (%h)' --date=format:%Y.%m.%d "$1"
|
|
}
|
|
|
|
# Print the newer version if the remote has commits this checkout doesn't.
|
|
# Returns 1 if up to date, 2 if the remote couldn't be reached.
|
|
newer_version() {
|
|
GIT_TERMINAL_PROMPT=0 timeout 30 git -C "$COREDESKTOP" fetch --quiet &> /dev/null || return 2
|
|
local behind
|
|
behind="$(git -C "$COREDESKTOP" rev-list --count 'HEAD..@{upstream}' 2> /dev/null)" || return 2
|
|
(( behind > 0 )) || return 1
|
|
describe '@{upstream}'
|
|
}
|
|
|
|
if [ "$1" = "--check" ]; then
|
|
newer_version
|
|
exit
|
|
fi
|
|
|
|
version="$(describe HEAD)"
|
|
|
|
# Local edits to the checkout mean this isn't exactly the version above
|
|
if [ -n "$(git -C "$COREDESKTOP" status --porcelain --untracked-files=no)" ]; then
|
|
version="$version, modified"
|
|
fi
|
|
|
|
if latest="$(newer_version)"; then
|
|
version="$version, $latest is available (run update)"
|
|
fi
|
|
|
|
# A version without its epoch and pkgrel, e.g. 1:26.2.6-1 is 26.2.6. Arch's
|
|
# kernel puts its suffix in the version too (7.2.14.arch1), so drop that.
|
|
upstream() {
|
|
local v="${1#*:}"
|
|
v="${v%-*}"
|
|
echo "${v%.arch*}"
|
|
}
|
|
|
|
# Packages with a newer version in the repos, as "name old -> new" lines.
|
|
# checkupdates syncs a copy of the package database, so it needs no root and
|
|
# doesn't leave a partial upgrade behind. Empty if it couldn't check.
|
|
pending=""
|
|
if command -v checkupdates &> /dev/null; then
|
|
pending="$(timeout 30 checkupdates 2> /dev/null)"
|
|
fi
|
|
|
|
# Print the newer upstream version of package $1 if the repos have one. A
|
|
# rebuild of the same version (only the pkgrel changed) doesn't count.
|
|
newer_package() {
|
|
local name old _ new
|
|
while read -r name old _ new; do
|
|
[ "$name" = "$1" ] || continue
|
|
[ "$(upstream "$old")" != "$(upstream "$new")" ] && upstream "$new"
|
|
return
|
|
done <<< "$pending"
|
|
return 1
|
|
}
|
|
|
|
kernel="$(uname -r)"
|
|
# The package the running kernel came from (linux, linux-lts, ...)
|
|
kernel_pkg="$(cat "/usr/lib/modules/$kernel/pkgbase" 2> /dev/null)"
|
|
case "$kernel" in
|
|
*-lts) kernel_pkg="${kernel_pkg:-linux-lts}" ;;
|
|
*-zen) kernel_pkg="${kernel_pkg:-linux-zen}" ;;
|
|
*-hardened) kernel_pkg="${kernel_pkg:-linux-hardened}" ;;
|
|
*) kernel_pkg="${kernel_pkg:-linux}" ;;
|
|
esac
|
|
|
|
# If the running kernel's modules are gone, a newer kernel was installed
|
|
if [ ! -d "/usr/lib/modules/$kernel" ]; then
|
|
kernel="$kernel (newer kernel installed, reboot to use it)"
|
|
fi
|
|
if latest="$(newer_package "$kernel_pkg")"; then
|
|
kernel="$kernel, $latest is available (run update)"
|
|
fi
|
|
|
|
# NVIDIA's driver if nvidia.sh installed it, otherwise Mesa, which drives
|
|
# Intel and AMD graphics (vulkan-intel and vulkan-radeon are built with it)
|
|
driver=""
|
|
for pkg in nvidia-utils nvidia-580xx-utils mesa; do
|
|
if installed="$(pacman -Q "$pkg" 2> /dev/null)"; then
|
|
case "$pkg" in
|
|
nvidia*) driver="NVIDIA $(upstream "${installed#* }")" ;;
|
|
*) driver="Mesa $(upstream "${installed#* }")" ;;
|
|
esac
|
|
if latest="$(newer_package "$pkg")"; then
|
|
driver="$driver, $latest is available (run update)"
|
|
fi
|
|
break
|
|
fi
|
|
done
|
|
|
|
# 10-pacman.sh rewrites this log on every update
|
|
if [ -f "$PACMAN_UPDATE_LOG" ]; then
|
|
last_update="$(date -r "$PACMAN_UPDATE_LOG" '+%Y-%m-%d %H:%M')"
|
|
else
|
|
last_update="never"
|
|
fi
|
|
|
|
echo "CoreDesktop $version"
|
|
echo "Kernel $kernel"
|
|
[ -n "$driver" ] && echo "Video driver $driver"
|
|
echo "Last update $last_update"
|
|
|
|
# Sibling projects, as "name<TAB>installed<TAB>available" lines (see sibling)
|
|
siblings="$(bash "$COREDESKTOP/sibling" check --porcelain 2> /dev/null)"
|
|
newer_siblings=()
|
|
if [ -n "$siblings" ]; then
|
|
echo
|
|
echo "Sibling projects"
|
|
width=0
|
|
while IFS=$'\t' read -r name _; do
|
|
(( ${#name} > width )) && width=${#name}
|
|
done <<< "$siblings"
|
|
while IFS=$'\t' read -r name installed available; do
|
|
case "$available" in
|
|
"") ;;
|
|
"?") installed="$installed, couldn't check for a newer version" ;;
|
|
*)
|
|
installed="$installed, $available is available"
|
|
newer_siblings+=("$name"$'\t'"$available")
|
|
;;
|
|
esac
|
|
printf ' %-*s %s\n' "$width" "$name" "$installed"
|
|
done <<< "$siblings"
|
|
fi
|
|
|
|
# Packages newer than the mirror's last sync aren't shown above, or installed
|
|
if age="$(mirror_age_hours)" && (( age >= MIRROR_STALE_HOURS )); then
|
|
if (( age >= 48 )); then ago="$(( age / 24 )) days"; else ago="$age hours"; fi
|
|
echo
|
|
echo -e "\e[33mYour package mirror ($(first_mirror)) last synced with Arch $ago ago, so"
|
|
echo -e "newer packages may be missing. Run update to switch to up-to-date mirrors.\e[0m"
|
|
fi
|
|
|
|
# Offer each newer sibling, but only to someone at the terminal to answer
|
|
if (( ${#newer_siblings[@]} > 0 )) && [ -t 0 ] && [ -t 1 ]; then
|
|
echo
|
|
chosen=()
|
|
for sibling in "${newer_siblings[@]}"; do
|
|
IFS=$'\t' read -r name available <<< "$sibling"
|
|
read -rp "Update $name to $available? [y/N] " response
|
|
[[ "$response" =~ ^[yY]([eE][sS])?$ ]] && chosen+=("$name")
|
|
done
|
|
if (( ${#chosen[@]} > 0 )); then
|
|
echo
|
|
bash "$COREDESKTOP/sibling" update "${chosen[@]}"
|
|
exit
|
|
fi
|
|
fi
|