Files
coredesktop/version
T
davidandClaude Opus 5.5 ee7451600b
shellcheck / shellcheck (push) Failing after 19s
Show sibling projects' versions, and let version update them
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>
2026-11-08 10:26:51 -07:00

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