-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·243 lines (215 loc) · 8.04 KB
/
install.sh
File metadata and controls
executable file
·243 lines (215 loc) · 8.04 KB
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#!/bin/bash
# GLOBALS
g_BACKUPPATH="$HOME/.config_backed_up"
# USER-PROVIDED
u_NOINSTALL=false
u_NOBACKUP=false
u_DEBUG=true #add switch
function print_help(){
echo -e "\n---Dots setup---"
echo -e "Sets up the dotfiles, configure them in config.json"
echo -e "Arguments:"
echo -e "-h/--help - this help"
echo -e "-c/--collection <coll_name> - (required) what to set up"
for coll in "${!mapped_packages[@]}";do
echo -e "\t$coll - ${mapped_packages[$coll]}"
done
echo -e "-ni/--no-install - by default this tool tries to install the programs for which config is copied. This option disables that"
echo -e "-nb/--no-backup - by default this tool backups any previously present config to ~/.config_backed_up/ folder. This option disables that"
}
function debug(){
if [ $u_DEBUG = true ]; then
echo -e "$1"
fi
}
function os_detect(){
if [[ -f /etc/os-release ]]; then
. /etc/os-release
if [[ -n $ID_LIKE ]]; then
echo "$ID_LIKE"
elif [[ -n $ID ]]; then
echo "$ID"
else
echo "unknown"
fi
else
echo "unknown"
fi
}
function field_exists(){
# $1 is searched field, $2 is array of fields
local search_field="$1"
shift
local array=("$@")
for item in "${array[@]}"; do
if [[ "$item" == "$search_field" ]]; then
return 0
fi
done
return 1
}
function dirmk(){
if [ ! -d $1 ]; then
echo "Folder $1 does not exist, creating"
mkdir -p $1
fi
}
#set -e
#set -u
trap 'echo "Something went horribly wrong on line $LINENO"; exit 1' ERR
# parse opts
while [[ "$#" -gt 0 ]]; do
case $1 in
-h|--help) print_help
exit 0
;;
--collection=*) u_COLL="${1#*=}"
shift
;;
-c|--collection) u_COLL="$2"
shift
shift
;;
-ni|--no-install) u_NOINSTALL=true
shift
;;
-nb|--no-backup) u_NOBACKUP=true
shift
;;
*) echo "Unknown parameter passed: $1"
print_help
exit 1
;;
esac
done
# check some prerequisites
if [ ! -f "$PWD/config.json" ];then
echo "Looks like you've forgotten the config.json"
fi
# detect OS to decide installer
if [[ "$u_NOINSTALL" == "false" ]]; then
detected_os=$(os_detect)
case "$detected_os" in
debian)
echo "Debian detected, apt will be used"
sudo apt update
g_INSTALLER="sudo DEBIAN_FRONTEND=noninteractive apt install -y "
;;
arch)
echo "Arch detected, pacman will be used"
g_INSTALLER="sudo pacman -S --noconfirm "
;;
unknown)
echo "Couldn't identify OS. Only configs will be moved, handle installation yourself."
u_NOINSTALL=true
;;
*)
echo "Unsupported OS detected. Only configs will be moved, handle installation yourself."
u_NOINSTALL=true
;;
esac
fi
# check if jq is present
rc=0
command -v jq >/dev/null 2>&1 || rc=$? #hack to avoid triggering set -e (man set)
if [ "$rc" -ne 0 ]; then
if [ "$u_NOINSTALL" = true ]; then
echo "No jq present and you refuse installs. Breaking"
exit 1
fi
echo "No jq present, you are going to need it anyway. Installing..."
eval "${g_INSTALLER}jq"
fi
# parse packages in config
available_colls=($(jq -r '.collections|keys[]' config.json))
declare -A mapped_packages
for coll in "${available_colls[@]}"; do
while read -r package; do
mapped_packages[$coll]="${mapped_packages[$coll]} $package"
done < <(jq -r ".collections.${coll}[]" config.json)
done
# check if selected collection is supported (present in config)
if [[ ! " ${!mapped_packages[@]} " =~ [[:space:]]${u_COLL}[[:space:]] ]]; then
echo -e "No such collection!"
print_help
exit 1
fi
# prepare backup space
if [ "$u_NOBACKUP" = true ]; then
echo -e "Running without backup, waiting 2s for your interrupt"
sleep 2
else
if [ -d "$g_BACKUPPATH" ]; then
echo -e "Dropping old backup folder at $g_BACKUPPATH"
rm -rf "$g_BACKUPPATH"
fi
dirmk "$g_BACKUPPATH"
fi
declare -a faulty_packages
for desired_package in ${mapped_packages[$u_COLL]}; do
declare -A pkg_info=()
declare -a pkg_fields=()
declare tmp_res
# check whether the package is actually defined
debug "Parsing pkg $desired_package"
tmp_res=$(jq -r ".packages|has(\"$desired_package\")" config.json)
if [ $tmp_res == "false" ]; then
echo "Missing package $desired_package definition in config.json"
faulty_packages+=($desired_package)
continue
fi
# check whether the package definition contains any fields
debug "Parsing fields of $desired_package"
tmp_res=$(jq -r ".packages.$desired_package // empty" config.json)
if [[ -z $tmp_res ]]; then
echo "Missing fields in package $desired_package definition in config.json"
faulty_packages+=($desired_package)
continue
fi
# parse the package and get the field keys
debug "Getting field keys of $desired_package"
while read -r field; do
pkg_fields+=($field)
done < <(jq -r ".packages.${desired_package}|keys[]" config.json)
# get field values
for field in "${pkg_fields[@]}"; do
while read -r val; do
pkg_info[$field]="$val"
done< <(jq -r ".packages.${desired_package}.${field}" config.json)
done
# backup old config
if field_exists "confSrcPath" "${pkg_fields[@]}" && field_exists "confTgtPath" "${pkg_fields[@]}" ;then
pkg_info[confTgtPath]=$(eval echo "${pkg_info[confTgtPath]}") #terrible hack to evaluate variables in config
if [ "$u_NOBACKUP" = false ]; then
if [ -d "${pkg_info[confTgtPath]}" ]; then
echo -e "Backing up old config at ${g_BACKUPPATH}${pkg_info[confTgtPath]}"
dirmk "${g_BACKUPPATH}${pkg_info[confTgtPath]}"
cp -Lr "${pkg_info[confTgtPath]}" "${g_BACKUPPATH}${pkg_info[confTgtPath]}"
fi
fi
# try creating the whole directory tree and remove the top one. Ensures that both root directory exists and old config is purged at the same time
dirmk "${pkg_info[confTgtPath]}"
rm -rf "${pkg_info[confTgtPath]}"
else
echo "$desired_package lacks confSrcPath and confTgtPath"
faulty_packages+=($desired_package)
continue
fi
# install package (if needed)
if [ "$u_NOINSTALL" = false ] && field_exists "pkgMgrName" "${pkg_fields[@]}";then
debug "Running installation of $desired_package"
eval "${g_INSTALLER}${pkg_info[pkgMgrName]}"
fi
# remove colliding configs created by installers and link our config
if [ -d "${pkg_info[confTgtPath]}" ]; then
debug "Removing installer's default config for ${desired_package}"
rm -rf "${pkg_info[confTgtPath]}"
fi
debug "Linking config for ${desired_package}"
ln -s "$PWD/${pkg_info[confSrcPath]}" "${pkg_info[confTgtPath]}"
echo "Package ${desired_package} done!"
done
echo -e "The following packages failed the installation: "
for package in ${faulty_packages[@]}; do
echo -e "\t-$package"
done