upd: avoid pulling the same repo twice, support arguments
This commit is contained in:
parent
3eaa2828ba
commit
94dfd777bc
1 changed files with 169 additions and 48 deletions
|
@ -1,33 +1,23 @@
|
|||
#!/bin/bash
|
||||
# updates some important repositories in my home folder (and elsewhere) that exist on multiple devices
|
||||
#!/bin/sh
|
||||
# Update dotfiles and some other common repositories.
|
||||
# This script accepts no arguments, but accepts additional repositories through the REPOS_TO_UPDATE environment variable
|
||||
|
||||
set -eu
|
||||
|
||||
# Check for git
|
||||
if ! command -v git > /dev/null; then
|
||||
echo "git is not installed, please install git and try again"
|
||||
exit 1
|
||||
fi
|
||||
#
|
||||
# Setup functions and variables
|
||||
#
|
||||
|
||||
# Set colors
|
||||
if command -v tput > /dev/null; then
|
||||
YELLOW="$(tput setaf 3)"
|
||||
GREEN="$(tput setaf 2)"
|
||||
NC="$(tput sgr0)"
|
||||
elif [ -n "$TERMUX_VERSION" ]; then
|
||||
YELLOW="[33m"
|
||||
GREEN="[32m"
|
||||
NC="(B[m"
|
||||
fi
|
||||
# global name of script
|
||||
script="${0##*/}"
|
||||
|
||||
# Avoiding copy pasting this over and over
|
||||
g() { git -C "$REPO" "$@"; }
|
||||
cleanup() {
|
||||
exit
|
||||
}
|
||||
|
||||
REPOS_TO_UPDATE="${REPOS_TO_UPDATE:-}"
|
||||
|
||||
# path_append from https://superuser.com/questions/39751/add-directory-to-path-if-its-not-already-there
|
||||
# update_list_append from https://superuser.com/questions/39751/add-directory-to-path-if-its-not-already-there
|
||||
# checks if a path is already in the PATH and if it exists
|
||||
path_append() {
|
||||
update_list_append() {
|
||||
if [ -d "$1" ]; then
|
||||
# shellcheck disable=SC3010
|
||||
if command '[[' > /dev/null 2>&1 && [[ ":$REPOS_TO_UPDATE:" != *":$1:"* ]]; then
|
||||
|
@ -38,31 +28,162 @@ path_append() {
|
|||
fi
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
REPO_ABBR='echo ${REPO/"$HOME"/"~"}'
|
||||
# Do the arguments contain a search?
|
||||
# Usage: contains search "${array[@]}"
|
||||
contains() {
|
||||
search="$1"; shift
|
||||
split="$1"; shift
|
||||
array="$1"; shift
|
||||
|
||||
path_append "${DOCS_DIR:-}"
|
||||
path_append "$HOME/bin"
|
||||
path_append "${NIXOS_DIR:-}"
|
||||
path_append "$HOME/code/faust-ideas"
|
||||
path_append "$HOME/code/nixvim-config"
|
||||
path_append "$HOME/.config/nvim"
|
||||
ifs="$IFS"
|
||||
IFS="$split"
|
||||
for str in $array; do
|
||||
if [ "$str" = "$search" ]; then
|
||||
IFS="$ifs"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
IFS="$ifs"
|
||||
return 1
|
||||
}
|
||||
|
||||
# `git pull` everything mentioned in the REPOS_TO_UPDATE variable
|
||||
IFS=: read -ra REPOS_TO_UPDATE_ARR <<< "${REPOS_TO_UPDATE:-}"
|
||||
for REPO in "${REPOS_TO_UPDATE_ARR[@]}"; do
|
||||
if [ -n "$REPO" ]; then
|
||||
if g rev-parse > /dev/null 2>&1; then
|
||||
echo " ${GREEN}Pulling $(eval "$REPO_ABBR")‥${NC}"
|
||||
g pull
|
||||
g diff --quiet || echo "${YELLOW}Warning: Working tree for $(eval "$REPO_ABBR") is dirty${NC}"
|
||||
# Shorten the repo name to use a ~ for the home dir instead of the absolute path
|
||||
pretty_path() {
|
||||
arg="$1"
|
||||
|
||||
case "$arg" in
|
||||
# If the arg starts with our home dir,
|
||||
"$HOME"*)
|
||||
# replace the home dir part with a ~
|
||||
printf '~%s' "$(printf '%s' "$arg" | sed -E 's/^.{'"${#HOME}"'}//')"
|
||||
;;
|
||||
|
||||
# Otherwise,
|
||||
*)
|
||||
# Just print the arg
|
||||
printf '%s' "${arg}"
|
||||
;;
|
||||
esac | # Pass through some other filters
|
||||
sed -E 's_/+$__' | # Remove trailing slash
|
||||
tr -s '/' # Remove duplicate slashes
|
||||
}
|
||||
|
||||
# Warn about incomplete changes to a repository
|
||||
do_checks() {
|
||||
repo_pretty="$1"
|
||||
shift
|
||||
|
||||
# Uncommitted changes
|
||||
if ! "$@" diff --quiet; then
|
||||
echo "${yellow}Warning: Working tree for $repo_pretty is dirty${nc}"
|
||||
fi
|
||||
|
||||
# Unpushed changes
|
||||
unpushed="$("$@" for-each-ref --format=" %(refname:short) %(push:track)" refs/heads)"
|
||||
if echo "$unpushed" | grep -Fq ahead; then
|
||||
printf '%s' "${yellow}Warning: Unpushed commits in $repo_pretty on branches:"
|
||||
printf '%s' "$unpushed" | tr '\n' ','
|
||||
echo "${nc}"
|
||||
fi
|
||||
}
|
||||
|
||||
do_pull() {
|
||||
update_dotfiles="${update_dotfiles:-false}"
|
||||
|
||||
# Which repos have we updated so far
|
||||
updated=''
|
||||
|
||||
#
|
||||
# Main loop: `git pull` everything mentioned in the REPOS_TO_UPDATE variable
|
||||
#
|
||||
|
||||
repo=''
|
||||
for repo in "$@"; do
|
||||
if [ -n "$repo" ]; then
|
||||
repo_pretty="$(pretty_path "$repo")"
|
||||
repo="$(realpath "$repo" 2>/dev/null)"
|
||||
repo="$(git -C "$repo" rev-parse --show-toplevel 2> /dev/null || true)"
|
||||
if [ -n "$repo" ]; then
|
||||
if ! contains "$repo" ':' "$updated"; then
|
||||
# Pull the repository
|
||||
echo " Pulling ${green}$repo_pretty${nc}‥"
|
||||
if ! timeout 10 git -C "$repo" pull; then
|
||||
exit=$#
|
||||
if [ "$ignore_git_errors" != true ]; then
|
||||
return "$exit"
|
||||
fi
|
||||
fi
|
||||
UPDATED_STUFF=true
|
||||
done
|
||||
|
||||
# check for dotfiles updates
|
||||
${UPDATED_STUFF:-false} && echo
|
||||
echo " ${GREEN}Updating dotfiles…${NC}"
|
||||
dotfiles pull
|
||||
dotfiles diff --quiet || echo "${YELLOW}Warning: Working tree for dotfiles is dirty${NC}"
|
||||
updated="$repo:$updated"
|
||||
|
||||
# Warn about incomplete changes to a repository
|
||||
do_checks "$repo_pretty" git -C "$repo"
|
||||
did_updates=true
|
||||
if [ "$update_dotfiles" = 'false' ]; then
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# update dotfiles repo separately bc it's a bare repo
|
||||
if [ "$update_dotfiles" = true ]; then
|
||||
# check for dotfiles updates
|
||||
${did_updates:-false} && echo
|
||||
echo " Updating ${green}dotfiles${nc}…"
|
||||
dotfiles pull
|
||||
do_checks "$(dotfiles rev-parse --git-dir)" dotfiles
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
trap cleanup INT
|
||||
|
||||
# Check for git
|
||||
if ! command -v git > /dev/null; then
|
||||
echo "$script: git is not installed, please install git and try again" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set colors
|
||||
if command -v tput > /dev/null; then
|
||||
yellow="$(tput setaf 3)"
|
||||
green="$(tput setaf 2)"
|
||||
nc="$(tput sgr0)"
|
||||
elif [ -n "$TERMUX_VERSION" ]; then
|
||||
yellow="[33m"
|
||||
green="[32m"
|
||||
nc="(B[m"
|
||||
fi
|
||||
|
||||
# Default repos to update
|
||||
ignore_git_errors=false
|
||||
if [ $# = 0 ]; then
|
||||
# Default paths to check
|
||||
REPOS_TO_UPDATE="${REPOS_TO_UPDATE:-}"
|
||||
|
||||
set -- "$@" \
|
||||
"${DOCS_DIR:-}" \
|
||||
"$HOME/bin" \
|
||||
"${NIXOS_DIR:-}" \
|
||||
"$HOME/code/faust-ideas" \
|
||||
"$HOME/code/nixvim-config" \
|
||||
"$HOME/.config/nvim"
|
||||
|
||||
split="$IFS"
|
||||
IFS=':'
|
||||
for dir in $REPOS_TO_UPDATE; do
|
||||
set -- "$dir" "$@"
|
||||
done
|
||||
IFS="$split"
|
||||
|
||||
update_dotfiles=true
|
||||
else
|
||||
ignore_git_errors="${IGNORE_GIT_ERRORS:-true}"
|
||||
fi
|
||||
|
||||
do_pull "$@"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue