Skip to content

Instantly share code, notes, and snippets.

@ntpeters
Last active January 2, 2020 09:12
Dotfile Status Script
#!/usr/bin/env/bash
# This is a simple script to check the current local/remote status of your
# dotfiles, and prompt to update them if needed.
#
# Update the contents of the 'sync_dotfiles' function below to change the
# method for performing dotfile updates.
#
# You must set the 'LOCAL_DOTFILES_REPOSITORY' environment variable
# to point to the path of your local dotfiles repo prior to executing this script.
#
# The core portion of this script is taken from a general solution for checking
# the status of local/remote git repos posted by Neil Mayhew on StackOverflow:
# http://stackoverflow.com/a/3278427/1428743
# Syncs dotfile changes
# NOTE TO USER:
# Modify this function to use your desired mothod of syncing dotfiles
function sync_dotfiles() {
# Currently using updot (https://github.com/ntpeters/updot) for dotfile sync
# Ensure Python is installed
if ! prog_loc="$(type -p "python")" || [ -z "$prog_loc" ] || [ "$prog_loc" == *"not found"* ]; then
echo "ERROR: Python does not exist in path! Updot requires Python. Please ensure Python is installed, and try again."
return
fi
# Try executing updot from its default location
if [ -f $HOME/.updot/updot.py ]; then
python $HOME/.updot/updot.py
else
echo "ERROR: updot not found! Aborting sync!"
fi
}
# Checks the status of local and remote dotfiles repos to determine if they
# need to be synced up.
function check_dotfiles_status() {
# Make sure the path we were given is a git repo
if [ ! -d ./.git ]; then
echo "ERROR: Provided dotfile directory is not a git repository!"
return
fi
# Check if git is available
if ! prog_loc="$(type -p "git")" || [ -z "$prog_loc" ] || [ "$prog_loc" == *"not found"* ]; then
echo "ERROR: Git does not exist in path! Please ensure git is installed, and try again."
return
fi
# Check for active internet connection
echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1
if [ $? -eq 1 ]; then
echo "ERROR: Failed to get status of remote dotfiles. No active internet connection detected!"
return
fi
# Get remote branch info
$(git fetch > /dev/null 2>&1)
# Retrieve hashes from git
local LOCAL=$(git rev-parse @)
local REMOTE=$(git rev-parse @\{u\})
local BASE=$(git merge-base @ @\{u\})
# Check for uncommitted changes
$(! git diff-index --quiet HEAD --)
local UNCOMMITTED=$?
# Flag to determine if an update may need to be done
local update=true
# Determine status of dotfiles
if [ -z $LOCAL ] || [ -z $REMOTE ] || [ -z $BASE ]; then
echo "ERROR: Failed to get status of local dotfiles!"
update=false
elif [ $UNCOMMITTED = 0 ]; then
echo "Local dotfiles have uncommitted changes."
elif [ $LOCAL = $REMOTE ]; then
echo "Dotfiles up-to-date."
update=false
elif [ $LOCAL = $BASE ]; then
echo "Remote dotfiles have changed."
elif [ $REMOTE = $BASE ]; then
echo "Local dotfiles have changed."
else
echo "WARNING: Local and remote dotfiles have diverged. You may experience merge conflicts!"
fi
# See if the user wants to sync dotfiles
if $update; then
read -p "Sync dotfiles now? [y/n] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo
# Execute the defined method of syncing dotfiles
sync_dotfiles
fi
fi
}
# Check if other shell instances are currently running
# Only check dotfile status on initial shell open
cur_shell_instances=$(pgrep -f `ps -p $$ -ocomm= | cut -d'/' -f 3` | wc -l | tr -d ' ')
default_shell_instances=$(pgrep -f ${SHELL##*/} | wc -l | tr -d ' ')
total_shell_instances=$(( $cur_shell_instances + $default_shell_instances ))
if (( $total_shell_instances > 1 )); then
exit 1
fi
# Ensure a path to the local dotfiles repo has been provided
if [ -z ${LOCAL_DOTFILES_REPOSITORY+x} ]; then
echo "ERROR: Must set the 'LOCAL_DOTFILES_REPOSITORY' variable with path to your dotfiles directory!"
else
# Ensure path to dotfiles repo has expanded tilde for home dir
# Not sure how portable this method is...
local_dotfiles_repo=$(eval "echo $LOCAL_DOTFILES_REPOSITORY")
# Check if dotfiles need to be updated
( cd ${local_dotfiles_repo} && check_dotfiles_status )
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment