chiark / gitweb /
Pseudo-merge of mariner/msriner
[ian-dotfiles.git] / infra / makelinks
index 0fd38dc..46c901e 100755 (executable)
@@ -9,7 +9,7 @@
 set -e -o posix -o pipefail
 
 badusage () {
-    echo >&2 "usage: $0 [-n|-v] list|setup|import|clean"
+    echo >&2 "usage: $0 [-n|-v] list|setup|dirimport|dirmove|clean"
     exit 18
 }
 
@@ -27,14 +27,12 @@ while true; do
 done
 
 case "$#.$1" in
-1.list|1.setup|1.import|1.clean) ;;
+1.list|1.setup|1.import|1.dirimport|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/}
 
@@ -46,18 +44,19 @@ show () {
 
 good () {
     if [ $mode = list ]; then
-       show "good: $dot: $1"
+       show "good: $prhome: $1"
     fi
 }
 
 bad () {
     estatus=16
-    show "bad: $dot: $1" >&2
+    show "bad: $prhome: $1" >&2
 }
 
 needs () {
     if [ $mode = $1 ]; then
        act=$real_act
+       show "DOING $1: $prhome ($2)"
     else
        show "needs $1: $prhome: $2"
        act=:
@@ -73,33 +72,96 @@ with_log () {
     "$@"
 }
 
-for dot in $dots; do
-    underhome=".${dot#dot/}"
+process_object () {
     inhome="$HOME/$underhome"
     prhome="~/$underhome"
-    if [ "$inhome" -ef "$dot" ]; then
+    linktarget="$basepath/$ours"
+    chompy="$underhome"
+    while true; do
+       case "$chompy" in
+        *?/?*)
+           linktarget="../$linktarget"
+           chompy="${chompy%/*}"
+           ;;
+       *)
+           break
+           ;;
+       esac
+    done
+    if [ "$inhome" -ef "$ours" ]; 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"
+       $act ln -s "$linktarget" "$inhome"
+    elif [ -f "$inhome" ] && [ -f "$ours" ]; then
+       if cmp -s "$ours" "$inhome"; then
+           needs setup "identical in this ~ but not yet symlinked"
+           $act rm -f "$inhome"~
+           $act ln -s "$linktarget" "$inhome"~
+           $act mv -f "$inhome"~ "$inhome"
+       else
+           needs import "modified here"
+           $act rm -f "$ours"~
+           $act cp "$inhome" "$ours"~
+           $act mv -f "$ours"~ "$ours"
+       fi
+    elif [ -d "$inhome" ] && [ -d "$ours" ]; then
+       needs dirimport "directory in this ~, not yet symlinked"
+       $act mv "$ours" "$ours~"
+       $act ln -s "$linktarget" "$inhome"~
+       $act mv "$inhome" "$ours"
+       $act mv "$inhome~" "$inhome"
+       $act rm -rf "$ours~"
     else
-       needs import "modified here"
-       $act rm -f "$dot"~
-       $act cp "$inhome" "$dot"~
-       $act mv -f "$dot"~ "$dot"
+       bad "mismatched file types"
     fi
+}
+
+dots=$( find dot -mindepth 1 -maxdepth 1 -name '[0-9a-zA-Z]*[0-9a-zA-Z]' )
+
+for ours in $dots; do
+    underhome=".${ours#dot/}"
+    process_object
+done
+
+nondots=$( find home -mindepth 1 -maxdepth 1 -name '[0-9a-zA-Z]*[0-9a-zA-Z]' )
+
+for ours in $nondots; do
+    underhome="${ours#home/}"
+    process_object
+done
+
+exec 3<correspondences
+while read <&3 ours underhome; do
+    case "$ours" in
+    ''|'#'*) ;;
+    *)
+       case "$underhome" in
+       */*)
+           parent=${underhome%/*}
+           punderhome="$HOME/$parent"
+           prhome="~/${underhome%/*}"
+           if [ -d "$punderhome" ]; then
+               good "directory exists"
+           elif ! [ -e "$punderhome" ]; then
+               needs setup "directory does not exist"
+               $act mkdir -p "$punderhome"
+           else
+               bad "ought to be director but isn't"
+           fi
+           ;;
+       esac
+       process_object
+       ;;
+    esac
 done
 
 brokens=$(
     cd $HOME
-    find -L .[0-9a-zA-Z]* -xdev -type l -lname "$basepath/dot/*"
+    find -L .[0-9a-zA-Z]* -maxdepth 0 -xdev -type l \
+        \( -lname "$basepath/dot/*" -o -lname "$basepath/home/*" \)
 )
 for underhome in $brokens; do
     inhome="$HOME/$underhome"