Created
July 29, 2025 10:45
-
-
Save ryancdotorg/4ed1f1e2760043cac813dfc190495947 to your computer and use it in GitHub Desktop.
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 | |
# SPDX-License-Identifier: 0BSD OR MIT-0 OR CC0-1.0+ | |
# Copyright © 2025 Ryan Castellucci <[email protected]> | |
# | |
# vim_pack_update.sh | |
# | |
# A script to update all vim plugins managed by the native package manager. | |
# It handles plugins on a branch (fast-forward pull) and plugins on a tag | |
# (checks out the latest tag). | |
# | |
# USAGE: | |
# Save this script in `~/.vim/pack` and run it from there. | |
# | |
# Enable a combination of various unoffical bash 'strict' modes | |
# http://redsymbol.net/articles/unofficial-bash-strict-mode/ | |
# https://disconnected.systems/blog/another-bash-strict-mode/ | |
set -uo pipefail | |
trap 's=$?; echo ": Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR | |
IFS='\n\t' | |
GIT_BIN="$(which git)" | |
# Helper function to run git commands in the correct directory. | |
# Although git has a -C option to change directory, this is more robust. | |
function git_in_dir { | |
# save the target directory | |
local dir="$1" | |
# remove the target directory argument | |
shift | |
# use the directory stack to enter the target directory, then return | |
pushd "$dir" > /dev/null 2> /dev/null | |
"$GIT_BIN" "$@" | |
popd > /dev/null 2> /dev/null | |
} | |
# Find all plugins which are git repos by looking for the `.git` directory. | |
# NOTE Assumes your current working directory is already e.g. ~/.vim/pack | |
find . -mindepth 4 -maxdepth 4 -type d -name '.git' | while read -r d | |
do | |
# Extract the plugin directory path from the .git path. | |
DIR="$(dirname "$d")" | |
# Check if the repository is on a branch or a tag (detached HEAD). | |
BRANCH="$(git_in_dir "$DIR" branch --show-current)" | |
if [[ ! -z "$BRANCH" ]]; then | |
# --- Handle repositories on a branch --- | |
printf 'Updating %s:%s... ' "$DIR" "$BRANCH" | |
# Fetch the latest changes and perform a fast-forward-only pull. | |
# This is a safe way to update without creating merge commits. | |
# '|| true' prevents the script from exiting if the pull fails | |
# (e.g., already up to date). | |
git_in_dir "$DIR" fetch \ | |
&& git_in_dir "$DIR" pull --ff-only \ | |
|| true | |
else | |
# --- Handle repositories on a tag (detached HEAD) --- | |
CURRENT_TAG="$(git_in_dir "$DIR" describe --tags)" | |
printf 'Updating %s@%s... ' "$DIR" "$CURRENT_TAG" | |
# Fetch all new tags from the remote. | |
git_in_dir "$DIR" fetch --tags \ | |
|| true | |
# Find the commit hash of the most recent tag. | |
REV="$(git_in_dir "$DIR" rev-list --tags --max-count=1)" | |
# Get the name of the most recent tag from its commit hash. | |
LATEST_TAG="$(git_in_dir "$DIR" describe --tags $REV)" | |
# If the current tag is not the latest tag, check out the latest tag. | |
if [ "$CURRENT_TAG" != "$LATEST_TAG" ]; then | |
printf 'checking out %s...\n' "$LATEST_TAG" | |
git_in_dir "$DIR" checkout "$LATEST_TAG" \ | |
|| true | |
else | |
echo Already up to date. | |
fi | |
fi | |
done | |
printf 'All plugins checked.\n' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment