From 11eaff99d3027e313434000f82063fee9cad5c39 Mon Sep 17 00:00:00 2001 From: "Collin J. Doering" Date: Thu, 23 Oct 2014 04:47:10 -0400 Subject: [PATCH] Add link-conf program to project itself link-conf is a little shell script I wrote to recursively hard-link and make directories following the structure of a "config directory". This allows me to have a "clean" working git repository but edit config files as usual ignoring the fact they are part of a git project and located in another place. Use "link-conf.sh --help" to see how the program is called. If you are unsure you can always use the "-d -v" options together to see what the program would propose to link, create, and safely remove. There is an option "-f" that will force removal of files while it recursively links. This is in the case where the config dir and the target exist as files and the target file is not referenced by any hard-link and thus if removed will be gone forever. Do not use "-f" or "--force" if you don't know what you're doing. This program could be cleaned up a bit and it would be nice if it was run after every commit (use a git hook in .git/hooks/). Signed-off-by: Collin J. Doering --- .bin/link-conf.sh | 223 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100755 .bin/link-conf.sh 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