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
|
#!/bin/sh
|
||||||
# updates some important repositories in my home folder (and elsewhere) that exist on multiple devices
|
# 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
|
set -eu
|
||||||
|
|
||||||
# Check for git
|
#
|
||||||
if ! command -v git > /dev/null; then
|
# Setup functions and variables
|
||||||
echo "git is not installed, please install git and try again"
|
#
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Set colors
|
# global name of script
|
||||||
if command -v tput > /dev/null; then
|
script="${0##*/}"
|
||||||
YELLOW="$(tput setaf 3)"
|
|
||||||
GREEN="$(tput setaf 2)"
|
|
||||||
NC="$(tput sgr0)"
|
|
||||||
elif [ -n "$TERMUX_VERSION" ]; then
|
|
||||||
YELLOW="[33m"
|
|
||||||
GREEN="[32m"
|
|
||||||
NC="(B[m"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Avoiding copy pasting this over and over
|
cleanup() {
|
||||||
g() { git -C "$REPO" "$@"; }
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
REPOS_TO_UPDATE="${REPOS_TO_UPDATE:-}"
|
# update_list_append from https://superuser.com/questions/39751/add-directory-to-path-if-its-not-already-there
|
||||||
|
|
||||||
# path_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
|
# checks if a path is already in the PATH and if it exists
|
||||||
path_append() {
|
update_list_append() {
|
||||||
if [ -d "$1" ]; then
|
if [ -d "$1" ]; then
|
||||||
# shellcheck disable=SC3010
|
# shellcheck disable=SC3010
|
||||||
if command '[[' > /dev/null 2>&1 && [[ ":$REPOS_TO_UPDATE:" != *":$1:"* ]]; then
|
if command '[[' > /dev/null 2>&1 && [[ ":$REPOS_TO_UPDATE:" != *":$1:"* ]]; then
|
||||||
|
@ -38,31 +28,162 @@ path_append() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# shellcheck disable=SC2016
|
# Do the arguments contain a search?
|
||||||
REPO_ABBR='echo ${REPO/"$HOME"/"~"}'
|
# Usage: contains search "${array[@]}"
|
||||||
|
contains() {
|
||||||
|
search="$1"; shift
|
||||||
|
split="$1"; shift
|
||||||
|
array="$1"; shift
|
||||||
|
|
||||||
path_append "${DOCS_DIR:-}"
|
ifs="$IFS"
|
||||||
path_append "$HOME/bin"
|
IFS="$split"
|
||||||
path_append "${NIXOS_DIR:-}"
|
for str in $array; do
|
||||||
path_append "$HOME/code/faust-ideas"
|
if [ "$str" = "$search" ]; then
|
||||||
path_append "$HOME/code/nixvim-config"
|
IFS="$ifs"
|
||||||
path_append "$HOME/.config/nvim"
|
return 0
|
||||||
|
|
||||||
# `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}"
|
|
||||||
fi
|
fi
|
||||||
fi
|
done
|
||||||
UPDATED_STUFF=true
|
IFS="$ifs"
|
||||||
done
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
# check for dotfiles updates
|
# Shorten the repo name to use a ~ for the home dir instead of the absolute path
|
||||||
${UPDATED_STUFF:-false} && echo
|
pretty_path() {
|
||||||
echo " ${GREEN}Updating dotfiles…${NC}"
|
arg="$1"
|
||||||
dotfiles pull
|
|
||||||
dotfiles diff --quiet || echo "${YELLOW}Warning: Working tree for dotfiles is dirty${NC}"
|
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="$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