Skip to content

Instantly share code, notes, and snippets.

@matthewd
Last active December 17, 2015 14:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewd/5625126 to your computer and use it in GitHub Desktop.
Save matthewd/5625126 to your computer and use it in GitHub Desktop.
.common/setup
#!/bin/bash
COMMON=.common
if [ ! -d "$HOME/$COMMON" ]; then
if ! which git >/dev/null 2>&1; then
if which apt-get >/dev/null 2>&1 && which sudo >/dev/null 2>&1; then
if ! sudo apt-get install git-core; then
echo "Failed to install git; can't check out files" >&2
exit 1
fi
else
echo "Don't know how to install git; can't check out files" >&2
exit 1
fi
fi
echo "Checking out config files... this will probably only work if you have"
echo "an SSH key available via key forwarding or something."
if ! git clone gitosis@sierra.trebex.net:config.git "$HOME/$COMMON"; then
echo "Failed to check out files" >&2
exit 1
fi
fi
cd "$HOME/$COMMON"
if readlink -e . >/dev/null 2>&1; then
normpath() {
readlink -e "$1"
}
else
normpath() {
python -c 'import sys; import os.path; print os.path.normpath(sys.argv[1])' "$1"
}
fi
dolink() {
cmn="$COMMON"
base="$2"
until [ "$(dirname "$base")" = . ]; do
base="$(dirname "$base")"
cmn="../$cmn"
done
target="$cmn/$1"
if [ ! -e "$HOME/$COMMON/$1" ]; then
echo "Can't find link target '$COMMON/$1'"
return
fi
if [ ! -d "$HOME/$(dirname "$2")" ]; then
mkdir -p "$HOME/$(dirname "$2")"
fi
if [ -L "$HOME/$2" ]; then
curr="$(normpath "$HOME/$2")"
xtarget="$(normpath "$HOME/$COMMON/$1")"
if [ "$curr" = "$xtarget" ]; then
return
fi
echo "# '~/$2' currently links to '$curr'"
fi
if [ ! -e "$HOME/$2" ]; then
echo ln -s "$target" "$HOME/$2"
elif [ -f "$HOME/$2" ] && which diff >/dev/null 2>&1; then
if diff -q "$HOME/$COMMON/$1" "$HOME/$2" >/dev/null 2>&1; then
if [ -e "$HOME/$2" ]; then echo mv "$HOME/$2" "$HOME/$2.prev"; fi
echo ln -s "$target" "$HOME/$2"
else
echo "# Files ~/$COMMON/$1 and ~/$2 differ:"
printf '## diff -u ~/%q ~/%q\n' "$2" "$COMMON/$1"
printf '## mv ~/%q ~/%q.prev && ln -s %q ~/%q\n' "$2" "$2" "$target" "$2"
fi
else
echo "# Unable to compare ~/$COMMON/$1 and ~/$2; skipping:"
printf '## mv ~/%q ~/%q.prev && ln -s %q ~/%q\n' "$2" "$2" "$target" "$2"
fi
}
for i in $(ls -A "$HOME/$COMMON"); do
case "$i" in
.|..|.git) : ;;
.*) dolink "$i" "$i" ;;
esac
done
dolink "subversion.config" ".subversion/config"
dolink "ssh.authorized_keys" ".ssh/authorized_keys"
dolink "bin.sudo-ssh" "bin/sudo-ssh"
dolink "global.gitignore" ".gitignore"
dolink "gem.credentials" ".gem/credentials"
if [ -w ~ -a -d ~/.common/.git ] && which git >/dev/null 2>&1 && [ -n "$SSH_AUTH_SOCK" -o -s ~/.ssh/id_dsa ]; then
(
echo ".common: Checking status"
cd ~/.common
UNCOMMITTED=""
if ! git diff --quiet 2>&1 | env grep -q 'usage:'; then
if ! git diff --quiet; then
UNCOMMITTED=yes
fi
else
# git-diff is too old for --quiet; git-status will obviously
# behave as we expect.
if git status | env grep -q '^#'; then
UNCOMMITTED=yes
fi
fi
if [ -n "$UNCOMMITTED" ]; then
echo "Uncommitted changes in .common/"
git status
echo
else
echo ".common: Checking for outdated fetch"
DATEARG=.git/FETCH_HEAD
if ! date -r "$DATEARG" >/dev/null 2>&1; then
# Nasty: if we don't have 'date -r FILENAME', assume we have a
# Mac OS X compatible (BSD compatible?) stat on the path. (But
# avoid the zsh builtin.)
DATEARG=`env stat -f '%Dm' "$DATEARG"`
fi
if [ ! -f .git/FETCH_HEAD ] || [ "$(date -r "$DATEARG" '+%Y%W')" -ne "$(date '+%Y%W')" ]; then
echo "Pulling config files: "
git pull
if [ -x ~/.common/setup ]; then
~/.common/setup
fi
echo
fi
echo ".common: Checking for unpushed changes"
orig=$(if [ -f .git/refs/remotes/origin/master -o -f .git/remotes/origin/master ]; then
echo 'origin/master'
else
echo 'origin'
fi)
if ! git diff --quiet 2>&1 | env grep -q 'usage:'; then
if ! git diff --quiet "$orig" master ; then
echo "Changes to .common/ not pushed"
git diff --stat "$orig" master
echo
fi
else
if git diff "$orig" master | env grep -q .; then
echo "Changes to .common/ not pushed"
git diff --stat "$orig" master
echo
fi
fi
fi
echo ".common: All done"
) | cat >&2 # 'cat' is so git doesn't see the tty
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment