2026-07-27 10:55:58 +02:00
|
|
|
# Background repository maintenance shared by desktop and server shells.
|
|
|
|
|
|
|
|
|
|
update_dotfiles() {
|
|
|
|
|
local repo="$HOME/dotfiles"
|
|
|
|
|
local cache_dir="${ZDOTDIR:-$HOME}/.cache/zsh"
|
|
|
|
|
local notice_file="$cache_dir/dotfiles-update-notice"
|
|
|
|
|
local notice_tmp="$notice_file.$$.tmp"
|
|
|
|
|
local -a TO; (( $+commands[timeout] )) && TO=(timeout -k 5 15)
|
|
|
|
|
GIT_SSH_COMMAND='ssh -o BatchMode=yes -o ConnectTimeout=5 -o ControlMaster=no -o ControlPath=none' \
|
|
|
|
|
$TO git -C "$repo" fetch --quiet </dev/null 2>/dev/null || return
|
|
|
|
|
git -C "$repo" rev-parse --abbrev-ref '@{u}' >/dev/null 2>&1 || return
|
|
|
|
|
git -C "$repo" merge-base --is-ancestor '@{u}' HEAD 2>/dev/null && return
|
2026-07-27 11:09:40 +02:00
|
|
|
if git -C "$repo" merge --ff-only --quiet '@{u}' 2>/dev/null; then
|
|
|
|
|
local notice="⬆ dotfiles updated — run: exec zsh"
|
|
|
|
|
mkdir -p "$cache_dir" || return
|
|
|
|
|
print -r -- "$notice" >| "$notice_tmp" || return
|
|
|
|
|
mv -f "$notice_tmp" "$notice_file"
|
|
|
|
|
return
|
|
|
|
|
fi
|
2026-07-27 10:55:58 +02:00
|
|
|
local notice="⚠ dotfiles: $(git -C "$repo" symbolic-ref --short HEAD) can't fast-forward to @{u} — run: git -C ~/dotfiles pull"
|
|
|
|
|
mkdir -p "$cache_dir" || return
|
|
|
|
|
print -r -- "$notice" >| "$notice_tmp" || return
|
|
|
|
|
mv -f "$notice_tmp" "$notice_file"
|
|
|
|
|
}
|
|
|
|
|
update_dotfiles &!
|
|
|
|
|
|
|
|
|
|
check_tools_repo() {
|
|
|
|
|
local repo branch remote mergeref remote_sha local_sha cmd notice
|
|
|
|
|
local cache_dir="${ZDOTDIR:-$HOME}/.cache/zsh"
|
|
|
|
|
local notice_file="$cache_dir/tools-update-notice"
|
|
|
|
|
local notice_tmp="$notice_file.$$.tmp"
|
|
|
|
|
local -a TO; (( $+commands[timeout] )) && TO=(timeout -k 5 10)
|
|
|
|
|
for repo in /opt/tools "$HOME/tools" "$HOME/tools/tools-repo"; do
|
|
|
|
|
local -a g=(git -c 'safe.directory=*' -C "$repo")
|
|
|
|
|
$g rev-parse --is-inside-work-tree >/dev/null 2>&1 || continue
|
|
|
|
|
branch=$($g symbolic-ref --short HEAD 2>/dev/null) || return
|
|
|
|
|
remote=$($g config "branch.$branch.remote" 2>/dev/null) || return
|
|
|
|
|
mergeref=$($g config "branch.$branch.merge" 2>/dev/null) || return
|
|
|
|
|
remote_sha=$(GIT_SSH_COMMAND='ssh -o BatchMode=yes -o ConnectTimeout=5 -o ControlMaster=no -o ControlPath=none' \
|
|
|
|
|
$TO $g ls-remote "$remote" "$mergeref" </dev/null 2>/dev/null | awk '{print $1}')
|
|
|
|
|
local_sha=$($g rev-parse HEAD 2>/dev/null)
|
|
|
|
|
[[ -n "$remote_sha" && -n "$local_sha" ]] || return
|
|
|
|
|
[[ "$remote_sha" == "$local_sha" ]] && return
|
|
|
|
|
$g merge-base --is-ancestor "$remote_sha" HEAD 2>/dev/null && return
|
|
|
|
|
[[ -w "$repo/.git" ]] && cmd="git -C $repo pull" || cmd="sudo git -C $repo pull"
|
|
|
|
|
notice="⬆ tools: updates available in $repo — run: $cmd"
|
|
|
|
|
mkdir -p "$cache_dir" || return
|
|
|
|
|
print -r -- "$notice" >| "$notice_tmp" || return
|
|
|
|
|
mv -f "$notice_tmp" "$notice_file"
|
|
|
|
|
return
|
|
|
|
|
done
|
|
|
|
|
}
|
|
|
|
|
check_tools_repo &!
|
|
|
|
|
|
|
|
|
|
show_update_notices() {
|
|
|
|
|
local cache_dir="${ZDOTDIR:-$HOME}/.cache/zsh"
|
|
|
|
|
local notice_file claimed_notice
|
|
|
|
|
for notice_file in "$cache_dir"/{dotfiles,tools}-update-notice; do
|
|
|
|
|
[[ -s "$notice_file" ]] || continue
|
|
|
|
|
claimed_notice="$notice_file.$$.show"
|
|
|
|
|
mv "$notice_file" "$claimed_notice" 2>/dev/null || continue
|
|
|
|
|
command cat "$claimed_notice"
|
|
|
|
|
command rm -f "$claimed_notice"
|
|
|
|
|
done
|
|
|
|
|
}
|
|
|
|
|
autoload -Uz add-zsh-hook
|
|
|
|
|
add-zsh-hook precmd show_update_notices
|