-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinstall.sh
executable file
·175 lines (154 loc) · 5.42 KB
/
install.sh
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/bin/bash
set -u -e
# reads a file of links to set up relative to a source and dest folder
# the filenames are relative to the source and dest folders (to make it possible
# to test it without trashing the real files). If unspecified the dest is $HOME
# and the source is the same folder that the script is in
# existing files will get backed up to $dest/backups
# default the source to be the same as the script
readonly thisdir=$( cd `dirname $0` && pwd )
srcdir="$thisdir"
# default dest to be home
destdir="$HOME"
config="install.cfg"
dryRun=
copyMode="link"
readonly backupname=$(date +"backups/%Y%m%d-%H%M%S")
verbose=
host=$( hostname -s 2> /dev/null || hostname )
os=$( uname )
function usage()
{
cat <<END
Usage: $0 -nv -s source_dir -d dest_dir -m hostname -o os configfile
-n dry run, don't make any changes
-s source dirrectory. Defaults to $thisdir
-d destination directory. Defaults to $HOME
-c copy files instead of linking
-v verbose output
-m override machine hostname (defaults to $host)
-o override operating system (defaults to $os)
-h display this message
configfile is a colon seperated list of destination:source:host_pattern:os_pattern
.bashrc:my_bashrc.bash:satur.*:Linux|Darwin
will link/copy source_dir/my_bashrc.bash to dest_dir/.bashrc if the hostname
begins with satur (saturday, saturn etc..) and uname is either Darwin or Linux.
Patterns are passed to grep -E an empty pattern will match any host/platform
END
}
function process_args()
{
while getopts ":s:d:o:m:nvhc" flag ; do
case $flag in
s) srcdir=${OPTARG%/} ;;
d) destdir=${OPTARG%/} ;;
n) dryRun=1 ;;
c) copyMode='copy' ;;
v) verbose=1 ;;
o) os=${OPTARG} ;;
m) host=${OPTARG} ;;
h) usage ; exit 1 ;;
:) echo "ERROR: missing argument to flag [-$OPTARG]" ; usage ; exit 5 ;;
\?) echo "ERROR: Invalid Option [-$OPTARG]" ; usage ; exit 5 ;;
esac
done
shift $((OPTIND-1))
[[ -z ${1:-} ]] && { echo "ERROR: missing config file" ; usage ; exit 5 ; }
config="$1"
}
function linker()
{
local src="$1"
local dest="$2"
if [[ $copyMode == copy ]] ; then
echo COPY: "$@"
[[ $dryRun ]] || cp -R "$src" "$dest"
elif echo "$os" | grep -qE "MINGW" ; then
mingw_linker "$@"
else
posix_linker "$@"
fi
}
function posix_linker()
{
local src="$1"
local dest="$2"
echo LINK: "$@"
[[ $dryRun ]] || { remove "$dest" && ln -s "$src" "$dest" ; }
}
function mingw_linker()
{
local src="$1"
local dest="$2"
local wdest=$( cmd.exe //c echo "$dest" | sed 's,/,\\,g' )
local wsrc=$( cmd.exe //c echo "$src" | sed 's,/,\\,g' )
if [[ -d "$src" ]] ; then
echo JUNC: "$wsrc" "$wdest"
[[ $dryRun ]] || { remove "$dest" && cmd.exe //c mklink //j "$wdest" "$wsrc" ; }
else
echo HRDL: "$src" "$dest"
[[ $dryRun ]] || { remove "$dest" && cmd.exe //c mklink //h "$wdest" "$wsrc" ; }
fi
}
function remove()
{
if [[ -L "$@" ]] ; then
log "REMOVE LINK: $@"
[[ $dryRun ]] || rm "$@"
elif [[ -e "$@" ]] ; then
log "BACKUP: $@"
[[ $dryRun ]] || { mkdir -p "$destdir/$backupname" ; mv -f "$@" "$destdir/$backupname/" ; }
fi
}
function log()
{
if [[ $verbose ]] ; then
echo "$*"
fi
}
function createdir()
{
# dont print anything during dryrun or we get repeated messages about the same dir
if [[ ! -d "$@" ]] ; then
[[ $dryRun ]] || { log "CREATE: $@" ; mkdir -p "$@" ; }
fi
}
function main() {
log "destdir: $destdir"
log "srcdir: $srcdir"
log "config: $config"
log "dryRun: $dryRun"
log "link: $copyMode"
log "os: $os "
log "host: $host"
[[ -r "$config" ]] || { echo "ERROR: cannot read config: $config" ; exit 6 ; }
[[ -d "$srcdir" ]] || { echo "ERROR: source dir not a dir?: $srcdir" ; exit 7 ; }
[[ -d "$destdir" ]] || { echo "ERROR: dest dir not a dir?: $destdir" ; exit 7 ; }
IFS=':'
grep -v '^#' "$config" | while read dest src hostpattern ospattern; do
[[ $dryRun ]] || log "========================"
[[ ! -z "$src" && ! -z "$dest" ]] || continue
echo "$host" | grep -qE "$hostpattern" || { log "SKIP: $src -> $dest no match for $host =~ $hostpattern" ; continue; }
echo "$os" | grep -qE "$ospattern" || { log "SKIP: $src -> $dest no match for $os =~ $ospattern" ; continue; }
local srcfile="$srcdir/$src"
if [[ "$dest" = /* ]] ; then
local destfile="$dest"
else
local destfile="$destdir/$dest"
fi
[[ -r "$srcfile" ]] || { echo "ERROR: $src -> $dest sourcefile $srcfile is not readable" ; continue ; }
if [[ -e "$destfile" || -L "$destfile" ]] ; then
if [[ "$srcfile" -ef "$destfile" ]] ; then
log "SKIP: $src -> $dest dest $destfile is already linked to sourcefile: $srcfile"
continue
fi
else
local dir="${destfile%/*}"
createdir "$dir"
fi
[[ $verbose ]] && { echo diff "$srcfile" "$destfile" ; diff "$destfile" "$srcfile" || true ; }
linker "$srcfile" "$destfile"
done
}
process_args "$@"
main "$@"