summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Mike Burns <mike@mike-burns.com>2013-06-07 10:49:17 +0200
committerGravatar Mike Burns <mike@mike-burns.com>2013-06-07 10:49:17 +0200
commit3c6cbc343d19e221756be024ba8d5bf2632c38d7 (patch)
tree0283693945dd131924d6e0b005ca588ff201d9f1
Initial commit
This adds mkrc and rcup, along with a Makefile to handle installation. `rcup` is for installing files from the `~/.dotfiles` repo. It allows for tagged files and host-specific files, and can install/update one-off files. `mkrc` is for moving a normal file into the dotfiles repo.
-rw-r--r--Makefile7
-rwxr-xr-xbin/mkrc60
-rwxr-xr-xbin/rcup210
3 files changed, 277 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..df46731
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+PREFIX=/usr/local
+
+install:
+ install -m 0755 bin/mkrc $(PREFIX)/bin
+ install -m 0755 bin/rcup $(PREFIX)/bin
+
+.PHONY: install
diff --git a/bin/mkrc b/bin/mkrc
new file mode 100755
index 0000000..39714ec
--- /dev/null
+++ b/bin/mkrc
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+set -x
+
+DOTFILES=$HOME/.dotfiles
+MV=mv
+INSTALL=./install
+ROOT_DIR=$HOME
+
+
+destination() {
+ if [ $# -eq 1 ]; then
+ echo $DOTFILES/$1
+ else
+ echo $DOTFILES/tag-$2/$1
+ fi
+}
+
+install_dotfile() {
+ prior_wd=`pwd`
+ cd $DOTFILES
+ $INSTALL -t ${2:--} $1
+ cd $prior_wd
+}
+
+if [ $# -eq 0 ]; then
+ echo "Usage: dotfiles-add [-t tag] filename ..."
+ exit 1
+fi
+
+tag=
+verbosity=0
+while getopts vqt: opt; do
+ case "$opt" in
+ t) tag=$OPTARG;;
+ v) verbosity=$(($verbosity + 1));;
+ q) verbosity=$(($verbosity - 1));;
+ esac
+done
+shift $(($OPTIND-1))
+
+if [ $verbosity -ge 2 ]; then
+ MV="$MV -v"
+ INSTALL="$INSTALL -vv"
+elif [ $verbosity -eq 1 ]; then
+ MV="$MV -v"
+ INSTALL="$INSTALL -v"
+elif [ $verbosity -eq 0 ]; then
+ MV="$MV -v"
+else
+ INSTALL="$INSTALL -q"
+fi
+
+files=$@
+
+for file in $files; do
+ dotless=`echo $file | sed -e "s|$ROOT_DIR/||" | sed -e 's/^\.//'`
+ $MV $file `destination $dotless $tag`
+ install_dotfile $dotless $tag
+done
diff --git a/bin/rcup b/bin/rcup
new file mode 100755
index 0000000..65a2d0e
--- /dev/null
+++ b/bin/rcup
@@ -0,0 +1,210 @@
+#!/bin/sh
+
+#set -x
+
+REPLACE_ALL=0
+
+DEST_DIR=$HOME
+DOTFILES_DIR=$HOME/.dotfiles
+HOSTNAME=`hostname -s`
+HOST_FILES=$DOTFILES_DIR/host-$HOSTNAME
+DEBUG=:
+PRINT=echo
+VERBOSE=:
+PROMPT=echo
+DIRSTACK=":$DOTFILES_DIR"
+MKDIR=mkdir
+LN=ln
+RM=rm
+
+pushdir() {
+ DIRSTACK="$DIRSTACK:$PWD/$1"
+ $DEBUG "cd'ing to $1 from `pwd` with stack $DIRSTACK"
+ cd $1
+}
+
+popdir() {
+ current=`echo $DIRSTACK | sed -e 's/.*://g'`
+ prior=`echo $DIRSTACK | sed -e "s|:$current$||" | sed -e 's/.*://g'`
+ DIRSTACK=`echo $DIRSTACK | sed -e 's/:[^:]*$//'`
+ $DEBUG "cd'ing to $prior from `pwd` with stack $DIRSTACK"
+ cd $prior
+}
+
+build_path() {
+ local dest=$1
+ local file=$2
+ local dotted=$3
+
+ if [ $dotted -eq 1 ]; then
+ echo $dest/$file
+ else
+ echo $dest/.$file
+ fi
+}
+
+link_dir() {
+ local dir=$1
+ local dest_dir=$2
+ local dotfiles_dir=$3
+ local dotted=$4
+ local dest_path=`build_path $dest_dir $dir $dotted`
+
+ $VERBOSE "recurring on $dest_path"
+ $MKDIR -p $dest_path
+ pushdir $dir
+ for f in *; do
+ $DEBUG "handling the file $f"
+ handle_file $f $dest_path $3/$1 1
+ done
+ popdir
+}
+
+link_file() {
+ local file=$1
+ local dest_dir=$2
+ local dotfiles_dir=$3
+ local dotted=$4
+ local dest_file=`build_path $dest_dir $file $dotted`
+
+ $PRINT "linking $dest_file"
+ if [ -h $dest_file ]; then
+ rm -f $dest_file
+ fi
+ $LN -s $dotfiles_dir/$file $dest_file
+}
+
+replace_file() {
+ local file=$1
+ local dest_dir=$2
+ local dotfiles_dir=$3
+ local dotted=$4
+ local dest_file=`build_path $dest_dir $file $dotted`
+
+ $RM -rf $dest_file
+ link_file $file $dest_dir $dotfiles_dir $dotted
+}
+
+is_identical() {
+ diff -q -s $1 $2 > /dev/null
+}
+
+handle_file() {
+ local file=$1
+ local dest_dir=$2
+ local dotfiles_dir=$3
+ local dotted=$4
+
+ $DEBUG handle_file $1 $2 $3 $4
+
+ if [ ! -e $file ]; then
+ $VERBOSE "skipping non-existent file $file"
+ elif [ -d $file ]; then
+ link_dir $file $dest_dir $dotfiles_dir $dotted
+ else
+ dest_file=`build_path $dest_dir $file $dotted`
+ if [ -e "$dest_file" ]; then
+ if is_identical $file $dest_file; then
+ $VERBOSE "identical $dest_file"
+ elif [ $REPLACE_ALL -eq 1 ]; then
+ replace_file $file $dest_dir $dotfiles_dir $dotted
+ else
+ $PROMPT "overwrite ${dest_file}? [ynaq]"
+ read overwrite
+ case $overwrite in
+ a)
+ REPLACE_ALL=1
+ replace_file $file $dest_dir $dotfiles_dir $dotted
+ ;;
+ y) replace_file $file $dest_dir $dotfiles_dir $dotted
+ ;;
+ q) exit 1
+ ;;
+ *) $VERBOSE "skipping $dest_file"
+ ;;
+ esac
+ fi
+ else
+ link_file $file $dest_dir $dotfiles_dir $dotted
+ fi
+ fi
+}
+
+metafile() {
+ [ x$2 = 'xhost-' -o x$3 = 'xtag-' -o x$1 = "xRakefile" -o x$1 = "xinstall" ]
+}
+
+handle_command_line() {
+ arg_tags=""
+ verbosity=0
+ while getopts qvt: opt; do
+ case "$opt" in
+ t) arg_tags="$arg_tags $OPTARG";;
+ v) verbosity=$(($verbosity + 1));;
+ q) verbosity=$(($verbosity - 1));;
+ esac
+ done
+ shift $(($OPTIND-1))
+
+ if [ $verbosity -ge 2 ]; then
+ DEBUG=echo
+ VERBOSE=echo
+ PRINT=echo
+ elif [ $verbosity -eq 1 ]; then
+ DEBUG=:
+ VERBOSE=echo
+ PRINT=echo
+ elif [ $verbosity -eq 0 ]; then
+ DEBUG=:
+ VERBOSE=:
+ PRINT=echo
+ else
+ DEBUG=:
+ VERBOSE=:
+ PRINT=:
+ fi
+
+ if [ "x$arg_tags" != "x" ]; then
+ TAGS=$arg_tags
+ fi
+
+ FILES=$@
+}
+
+if [ -e $HOME/.rcrc ]; then
+ . $HOME/.rcrc
+fi
+
+handle_command_line $*
+
+cd $DOTFILES_DIR
+
+for file in ${FILES:-*}; do
+ host_portion=`echo $file | sed -e 's/host-.*/host-/'`
+ tag_portion=`echo $file | sed -e 's/tag-.*/tag-/'`
+ if ! metafile $file $host_portion $tag_portion; then
+ handle_file $file $DEST_DIR $DOTFILES_DIR 0
+ fi
+done
+
+cd $DOTFILES_DIR
+
+if [ -d $HOST_FILES ]; then
+ pushdir `basename $HOST_FILES`
+ for file in ${FILES:-*}; do
+ handle_file $file $DEST_DIR $HOST_FILES 0
+ done
+ popdir
+fi
+
+cd $DOTFILES_DIR
+
+for tag in $TAGS; do
+ if [ -d tag-$tag ]; then
+ pushdir `basename tag-$tag`
+ for file in ${FILES:-*}; do
+ handle_file $file $DEST_DIR $DOTFILES_DIR/tag-$tag 0
+ done
+ popdir
+ fi
+done