chiark / gitweb /
makelinks script seems to work
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 9 Dec 2015 00:24:52 +0000 (00:24 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 9 Dec 2015 00:24:52 +0000 (00:24 +0000)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
infra/makelinks [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..b25c15b
--- /dev/null
@@ -0,0 +1 @@
+*~
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e75ca3f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+#
+
+install:
+       infra/makelinks setup
+
+import:
+       infra/makelinks import
+
+.PHONY: install
diff --git a/infra/makelinks b/infra/makelinks
new file mode 100755 (executable)
index 0000000..0fd38dc
--- /dev/null
@@ -0,0 +1,109 @@
+#!/bin/bash
+#
+# To start tracking a file,
+#   cp ~/.screenrc dot/screenrc
+#
+# To sort out symlinks when things are clean
+#   infra/makelinks install
+
+set -e -o posix -o pipefail
+
+badusage () {
+    echo >&2 "usage: $0 [-n|-v] list|setup|import|clean"
+    exit 18
+}
+
+real_act=''
+
+while true; do
+    if [ $# = 0 ]; then break; fi
+    case "$1" in
+    -n) real_act=log_only ;;
+    -v) real_act=with_log ;;
+    -*) badusage ;;
+    *) break ;;
+    esac
+    shift
+done
+
+case "$#.$1" in
+1.list|1.setup|1.import|1.clean) ;;
+*)  badusage ;;
+esac
+
+mode=$1; shift
+
+dots=$( find dot -type f -name '[0-9a-zA-Z]*[0-9a-zA-Z]' )
+
+basepath=$(pwd)
+basepath=${basepath#$HOME/}
+
+estatus=0
+
+show () {
+    printf "%s\n" "$1"
+}
+
+good () {
+    if [ $mode = list ]; then
+       show "good: $dot: $1"
+    fi
+}
+
+bad () {
+    estatus=16
+    show "bad: $dot: $1" >&2
+}
+
+needs () {
+    if [ $mode = $1 ]; then
+       act=$real_act
+    else
+       show "needs $1: $prhome: $2"
+       act=:
+    fi
+}
+
+log_only () {
+    echo "x $*"
+}
+
+with_log () {
+    log_only "$@"
+    "$@"
+}
+
+for dot in $dots; do
+    underhome=".${dot#dot/}"
+    inhome="$HOME/$underhome"
+    prhome="~/$underhome"
+    if [ "$inhome" -ef "$dot" ]; then
+       good "already symlinked here"
+    elif [ -h "$inhome" ]; then
+        bad "wrong symlink target"
+    elif ! [ -e "$inhome" ]; then
+       needs setup "absent here"
+       $act ln -s "$basepath/$dot" "$inhome"
+    elif [ -f "$inhome" ] && cmp -s "$dot" "$inhome"; then
+       needs setup "identical here but not yet symlinked"
+       $act rm -f "$inhome"~
+       $act ln -s "$basepath/$dot" "$inhome"~
+       $act mv -f "$inhome"~ "$inhome"
+    else
+       needs import "modified here"
+       $act rm -f "$dot"~
+       $act cp "$inhome" "$dot"~
+       $act mv -f "$dot"~ "$dot"
+    fi
+done
+
+brokens=$(
+    cd $HOME
+    find -L .[0-9a-zA-Z]* -xdev -type l -lname "$basepath/dot/*"
+)
+for underhome in $brokens; do
+    inhome="$HOME/$underhome"
+    prhome="~/$underhome"
+    needs clean "symlink to removed file in dot/"
+    $act rm -f "$inhome"
+done