diff --git a/.bin/link-conf.sh b/.bin/link-conf.sh new file mode 100755 index 0000000..9e1b0f3 --- /dev/null +++ b/.bin/link-conf.sh @@ -0,0 +1,223 @@ +#!/bin/sh + +# (C) Copyright Collin Doering 2011 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# File: link-conf.sh +# Author: Collin J. Doering +# Date: Jun 4, 2011 + +# TODO: * add support for a 'interactive' option [ -i | --interactive ] +# * add support for a link-to option so you can link the given config-dir files to +# somewhere other then $HOME + +# lnfrec takes: +# $1: the config dir in question +# $2: the current directory in the recursive call (used internally to recurse the config dir) +# $3: boolean specifying option relink +# $4: boolean specifying option clean +# $5: boolean specifying option verbose +# $6: boolean specifying option force +# $7: boolean specifying option dry +function lnfrec () { + # for each file in $1 directory do link (default), relink ($3) or clean ($4) along with options + # verbose ($5) and force ($6) + for f in `ls -aA $1/$2`; do + case "$f" in + .) + ;; + ..) + ;; + */.) + ;; + */..) + ;; + *~) + ;; + .git) + ;; + .gitignore) + ;; + *) + # If the current file being recursed on from the given config dir ($1) is a directory + if [[ -d "$1$2/$f" ]]; then + # If the file currently being recursed on from the config dir ($1) in $HOME is not a directory + # (that is $HOME$2/$f); then create the directory $HOME$2/$f + if [[ ! -d "$HOME$2/$f" ]]; then + $5 && echo "Creating dir $HOME$2/$f" + ! $7 && mkdir "$HOME$2/$f" + fi + # recurse further into config dir to $1$2/$f + lnfrec "$1" "$2/$f" $3 $4 $5 $6 $7 + # If the current file being recursed on from the given config dir ($1) in $HOME is not a directory + # and is not a file or a link, then create a hardlink from $1$2/$f to $HOME$2/$f + elif [[ ! -e "$HOME$2/$f" && ! -L "$HOME$2/$f" ]]; then + $5 && echo "Linked $1$2/$f -> $HOME$2/$f" + ! $7 && ln "$1$2/$f" "$HOME$2/$f" + # Otherwise: the file exists ($HOME$2/$f) + else + NUM_LINKS=$(ls -al "$HOME$2/$f" | cut -d' ' -f2) + + # If the relink option is set + if $3; then + # check if the config file $HOME$2/$f has more then one hardlink; if so then relink + if [[ $NUM_LINKS -gt 1 ]]; then + $5 && echo "Re-linking $1$2/$f -> $HOME$2/$f" + ! $7 && rm "$HOME$2/$f" + ! $7 && ln "$1$2/$f" "$HOME$2/$f" + # if the force option is set (along with the relink option) + elif $6; then + echo "Warning! Removing regular file $HOME$2/$f" + ! $7 && rm "$HOME$2/$f" + $5 && echo "Re-linking $1$2/$f -> $HOME$2/$f" + ! $7 && ln "$1$2/$f" "$HOME$2/$f" + else + $5 && echo "$HOME$2/$f only has one file reference! Skipping.." + fi + # If the clean option is set + elif $4; then + # Check if the config file $HOME$2/$f has more then one hardlink; if so then clean the file from home + if [[ $NUM_LINKS -gt 1 ]]; then + $5 && echo "Cleaning $HOME$2/$f" + ! $7 && rm "$HOME$2/$f" + # If the force option is set (along with clean) + elif $6; then + echo "Warning! Forcing removal of $HOME$2/$f" + $5 && echo "Cleaning $HOME$2/$f" + ! $7 && rm "$HOME$2/$f" + else + $5 && echo "$HOME$2/$f only has one file reference! Skipping.." + fi + else + $5 && echo "$HOME$2/$f already linked! Skipping.." + fi # will fault if not given proper arguments! Internal usage only! + fi + ;; + esac + done +} + +function displayHelp () { + echo "Usage: link-conf [-r|--relink] [-f|--force] [-c|--clean] [-v|--verbose] [-d|--dry] [-h|--help] config-dir" +} + +# Option variables set when parsing cli parameters +RELINK=false +CLEAN=false +VERBOSE=false +FORCE=false +DRY=false +CONFIG_DIR="" + +# Use getopt to parse given cli arguments +args=`getopt -n link-conf -o rcfvdh -l relink,clean,force,verbose,dry,help -- $*` +if [ ! $? ]; then + echo "Failed to parse arguments!" + displayHelp + exit 1 +fi + +# Set arguments to the new ones done by using getopt +set -- $args + +while true; do + case "$1" in + -r | --relink) + if $CLEAN; then + echo "Error! Cannot specify relink and clean at once!" + exit 1 + elif [ !$RELINK ]; then + RELINK=true + else + echo "Error! -r | --relink used more then once!" + exit 1 + fi + ;; + -c | --clean) + if $RELINK; then + echo "Error! Cannot specify relink and clean at once!" + exit 1 + elif [ !$CLEAN ]; then + CLEAN=true + else + echo "Error! -c | --clean used more then once!" + exit 1 + fi + ;; + -v | --verbose) + if [ !$VERBOSE ]; then + VERBOSE=true + else + echo "Error! -v | --verbose used more then once!" + exit 1 + fi + ;; + -f | --force) + if [ !$FORCE ]; then + FORCE=true + else + echo "Error! -f | --force used more then once!" + exit 1 + fi + ;; + -d | --dry) + if [ !$DRY ]; then + DRY=true + else + echo "Error! -d | --dry used more then once!" + exit 1 + fi + ;; + -h | --help) + displayHelp + exit 0 + ;; + --) + shift + for arg; do + maybe_dir=$(echo $arg | sed "s/^\([\']\)\(.*\)\1\$/\2/g") + if [ "$CONFIG_DIR" == "" ]; then + if [[ -d "$maybe_dir" ]]; then + CONFIG_DIR="$maybe_dir" + else + echo "Error! The path given \"$maybe_dir\" is not a valid directory!" + exit 1 + fi + else + echo "Error! More then one config dir was given!" + displayHelp + exit 1 + fi + done + break + ;; + *) + echo "Internal error!" + exit 1 + ;; + esac + shift +done + +# Notify the user if it is a dry run +if $DRY; then + echo "Dry run.." +fi + +# Run the recursive hard linking algorithm +lnfrec "$CONFIG_DIR" "" $RELINK $CLEAN $VERBOSE $FORCE $DRY + +# exit gracefully +exit 0