From aea4cf150c198525185a533d107163e9c3ac6a44 Mon Sep 17 00:00:00 2001 From: Geoffrey Frogeye Date: Sun, 4 Dec 2016 14:16:21 +0100 Subject: [PATCH] Dotfiles handling! --- config/.dfrecur | 0 dotsync | 1 - scripts/dotfiles.sh | 166 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 config/.dfrecur delete mode 160000 dotsync create mode 100644 scripts/dotfiles.sh diff --git a/config/.dfrecur b/config/.dfrecur new file mode 100644 index 0000000..e69de29 diff --git a/dotsync b/dotsync deleted file mode 160000 index 54bcb2a..0000000 --- a/dotsync +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 54bcb2ac28d2c2a49caa1b78a0cceee9ae041122 diff --git a/scripts/dotfiles.sh b/scripts/dotfiles.sh new file mode 100644 index 0000000..6bd104a --- /dev/null +++ b/scripts/dotfiles.sh @@ -0,0 +1,166 @@ +#!/usr/bin/env bash + +# Handles dotfiles +# Yes there are tons of similar scipts yet I wanted no more nor less than what I needed +# (sourceable) + +# Config + +if [ -z "$DOTHOME" ]; then + DOTHOME="$HOME" +fi +if [ -z "$DOTREPO" ]; then + DOTREPO="$HOME/.dotfiles" +fi + +# Common functions + +# From http://stackoverflow.com/a/12498485 +function relativePath { + # both $1 and $2 are absolute paths beginning with / + # returns relative path to $2/$target from $1/$source + source=$1 + target=$2 + + common_part=$source # for now + result="" # for now + + while [[ "${target#$common_part}" == "${target}" ]]; do + # no match, means that candidate common part is not correct + # go up one level (reduce common part) + common_part="$(dirname $common_part)" + # and record that we went back, with correct / handling + if [[ -z $result ]]; then + result=".." + else + result="../$result" + fi + done + + if [[ $common_part == "/" ]]; then + # special case for root (no common path) + result="$result/" + fi + + # since we now have identified the common part, + # compute the non-common part + forward_part="${target#$common_part}" + + + # and now stick all parts together + if [[ -n $result ]] && [[ -n $forward_part ]]; then + result="$result$forward_part" + elif [[ -n $forward_part ]]; then + # extra slash removal + # result="${forward_part:1}" # Removes the . in the beginning... + result="${forward_part#/}" + fi + + echo "$result" +} + + +# Script common functions + +function _dotfiles-install-dir { # dir + local dir + local absSource + local absTarget + local relTarget + + dir="${1%/}" + dir="${dir#/}" + + /bin/ls -A "$DOTREPO/$dir" | while read file; do + if [[ -z "$dir" && $(echo $file | grep '^\(\.\|LICENSE\|README\)') ]]; then + continue + fi + if [[ $(echo $file | grep '^.dfrecur$') ]]; then + continue + fi + + if [ -z "$dir" ]; then + absSource="$DOTHOME/.$file" + absTarget="$DOTREPO/$file" + else + absSource="$DOTHOME/.$dir/$file" + absTarget="$DOTREPO/$dir/$file" + fi + relTarget="$(relativePath "$DOTHOME/$dir" "$absTarget")" + recurIndicator="$absTarget/.dfrecur" + + if [[ -h "$absTarget" ]]; then + if [ -e "$absSource" ]; then + if [ -h "$absSource" ]; then + cmd="cp --no-dereference --force $absTarget $absSource" + if [ $DRY_RUN ]; then + echo $cmd + else + yes | $cmd + fi + else + echo "[ERROR] $absSource already exists, but is not a link" + fi + else + cmd="cp --no-dereference --force $absTarget $absSource" + if [ $DRY_RUN ]; then + echo $cmd + else + yes | $cmd + fi + fi + elif [[ -f "$absTarget" || ( -d $absTarget && ! -f $recurIndicator ) ]]; then + if [ -e "$absSource" ]; then + if [ -h "$absSource" ]; then + cmd="ln --symbolic --no-dereference --force $relTarget $absSource" + if [ $DRY_RUN ]; then + echo $cmd + else + $cmd + fi + else + echo "[ERROR] $absSource already exists, but is not a symbolic link" + fi + else + cmd="ln --no-dereference --symbolic $relTarget $absSource" + if [ $DRY_RUN ]; then + echo $cmd + else + $cmd + fi + fi + elif [[ -d "$absTarget" && -f $recurIndicator ]]; then + if [ -e "$absSource" ]; then + if [ -d "$absSource" ]; then + # echo "Directory $absSource already exists" + _dotfiles-install-dir $dir/$file + else + echo "[ERROR] $absSource already exists, but is not a directory" + fi + else + cmd="mkdir $absSource" + if [ $DRY_RUN ]; then + echo $cmd + else + $cmd + fi + _dotfiles-install-dir $dir/$file + fi + else + echo "[WARNING] Skipped $absTarget" + fi + done + +} + +# Script functions + +function dotfiles-install { + _dotfiles-install-dir / +} + +# TODO dotfiles-{link,unlink,clean,uninstall} +# Link and Unlink should have a clever behavior regarding +# recusive folders +# Ex : linking config/i3 should make config recursible +# Ex : linking config if some files in it are linked should unlink those