summaryrefslogtreecommitdiff
path: root/bin/lt
blob: f09f3b7a696a768afaca7dba94c297cd79db3c74 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/bin/sh

# link tree

lt_version='lt-0.1'
unset CDPATH
export LC_ALL=C IFS='   
'

help() {
	echo "Lt is a tool for creating link trees.

Usage:
	lt [-Vn] src dest

Options:
	-V	print version and exit
	-n	print actions but not execute"
}

# ca returns the common ancestor between 2 paths
# i.e. ca /h/u/a/b /h/u/c/d => /h/u
ca() {
	ca_p1=${1#/} ca_p2=${2#/} ca_r1='' ca_r2='' R1=/
	while true; do
		[ "$ca_p1" ] || [ "$ca_p2" ] || break
		ca_r1=$ca_r1/${ca_p1%%/*} ca_p1=${ca_p1#*/}
		ca_r2=$ca_r2/${ca_p2%%/*} ca_p2=${ca_p2#*/}
		[ "$ca_r1" != "$ca_r2" ] && break
		R1=$ca_r1
	done
}

# pp returns the relative path from child to parent
# i.e. pp /h/u/a /h/u => ..
pp() {
	pp_s=$1 pp_b=$2 R1=''
	while true; do
		[ "$pp_b" = "$pp_s" ] && break
		pp_s=${pp_s%/*}
		[ "$R1" ] && R1=$R1/.. || R1=..
	done
}

# rp returns the relative path between src and base
# i.e. rp /h/u/a/b/f /h/u/b/f [/h/u] ../a/b/f
rp() {
	rp_s=$1 rp_d=$2 rp_c=$3
	! [ "$rp_c" ] && ca "$1" "$2" && rp_c=$R1
	rp_bs=${rp_s#$rp_c/}
	pp "$rp_d" "$rp_c" && R1=$R1/$rp_bs && R1=${R1#../}
}

skip=".git .gitignore .*.swp Makefile README.md"

# lt links src tree to dest (each file is a link)
lt() {
	d=$(mkdir -p "$2" && cd "$2" && pwd)
	cd "$1" && s=$PWD &&
	find . ! -type d -print | {
		cd "$d" &&
		while read -r f; do
			for k in $skip; do
				case $f in (./$k|./$k/*) continue 2;; esac
			done
			f=${f#./}; fd=$d/$f; fd=${fd%/*}
			test -d "$fd" || $trace mkdir -p "$fd"
			rp "$s/$f" "$d/$f" && $trace ln -sf "$R1" "$d/$f"
		done
	}
}

while getopts :nvV opt; do
	case $opt in
	(n) trace='echo' ;;
	(V) echo "$lt_version"; exit ;;
	(*) help; exit 1;;
	esac
done
shift $((OPTIND -1))

lt "$1" "$2"

#echo $1 $2 $3 && $1 $2 $3 && echo $R1

# Shell coding style:
# - standard POSIX shell, to be used as-is on Unix, Linux (busybox), *BSD*
# - no bashism, GNUism, etc.
# - local variables in same process are prefixed with function name, to avoid collisions
# - same process functions return values in R1, R2, ... global vars.
# - self-documented, self-tested