-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbootstrap.sh
executable file
·226 lines (181 loc) · 4.94 KB
/
bootstrap.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
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
#!/usr/bin/env bash
#
# Arch based bootstrapping script
#
# PURPOSE: Automate the setup of a new Arch installation by installing
# predefined packages and running configuration scripts.
## Environment variables
default_config="http://config.b00t.me"
LOGFILE=install.log
export DEBUG=1
## Main function
main() {
if [ $(id -u) = 0 ] ; then
whiptail \
--title 'Error' \
--msgbox "Please avoid running this as root" \
10 40
exit 1
fi
# cache password
sudo -v
preprocess
sleep 2
setup
read_config $config
for choice in $choices ; do
run_job "${job_list[$choice]}"
done
}
## Pre-processing - install build packages and AUR helper
preprocess() {
log running prerequisites
log refreshing package databases
catch sudo pacman --noconfirm -Syy
prereq=(dialog curl git base-devel binutils make gcc pkg-config fakeroot rsync)
whiptail --title "Preprocess" \
--yesno \
--yes-button "Continue" \
--no-button "Exit" \
"The following required packages will be installed:\n\n$(printf ' • %s\n' "${prereq[@]}")" \
0 0 3>&1 1>&2 2>&3 3>&1- || exit
for pkg in ${prereq[@]} ; do
install_pkg $pkg
done
if [ ! $(pacman -Qq yay 2>/dev/null) ] ; then
install_git yay https://aur.archlinux.org/yay.git
yay -Y --gendb
yay -Syu --devel
fi
}
## Setup configuration
setup() {
while true ; do
config_file=$(
whiptail \
--title "Config File" \
--inputbox "\nPlease enter the config file location. This can be a local file or a hosted file (starting with http(s)://): " \
0 78 ${1:-$default_config} \
3>&1 1>&2 2>&3 3>&1-
) || exit
if [[ "${config_file:=$default_config}" =~ ^https?:// ]] ; then
config=$(mktemp)
curl -sSfL "$config_file" > $config && break
elif [ -f "$config_file" ] ; then
config=$config_file
break
fi
whiptail \
--title 'Error' \
--msgbox "Unable to access file/url:\n\n$config_file" \
10 40
done
}
## Process the configuration file
read_config() {
[ -r "${1:?not set}" ] || { log -e cannot find $1 ; exit 1 ; }
_dlg() {
choices+=$(
dialog --keep-tite \
--backtitle "Arch Bootstrap Installation Script" \
--separate-output \
--checklist \
"$cat" \
0 0 0 \
"${options[@]}" \
2>&1 >/dev/tty)" " || exit
}
while IFS=, read -r tag name cmd desc ; do
[[ $tag == "=CMD" ]] && break;
if [[ $tag =~ ^= ]] ; then
[[ "$options" ]] && _dlg
options=()
cat=${tag/=/}
continue
fi
[[ ! $tag =~ ^[PAC] ]] && continue
job_list[$((++id))]=$id,$tag,$cat,$name,$desc,$cmd
options+=($id "${desc:-$name}" ${checkbox:-off})
done < $1
# extract custom scripts
scriptdir=$(mktemp -d)
gawk -F'[: ]' -v sd="$scriptdir/" '
match($0, /=CMD ([^:]*):(.*)/, a) { print a[2] > sd a[1] }
/^=CMD/ { script=$2 ; next }
/^=/ && script { script="" }
script { print $0 > sd script ; next }
' $1
[[ "$options" ]] && _dlg
clear
}
## Run jobs based on tag
run_job() {
IFS=',' read -r id tag cat name desc cmd <<< "$@"
case $tag in
P) install_pkg $name ;;
A) install_pkg -A $name ;;
C) cmd=${cmd:-$name} ;;
esac
[ "$cmd" ] && run_script $cmd
}
## Run Pacman/AUR helper
install_pkg() {
[ "$1" == "-A" ] && { aur=yay ; shift ; }
for pkg in "$@" ; do
if [ ! $(pacman -Qq $pkg 2>/dev/null) ] ; then
log installing ${aur:+AUR} package "\e[1;96m$pkg\e[0m"
catch ${aur:-sudo pacman} --noconfirm --needed -S "$pkg"
else
log package "\e[1;96m$pkg\e[0m" is already installed
fi
done
}
## Install from git repository
install_git() {
log installing package "\e[1;96m$1\e[0m"
git_dir="$(mktemp -d)"
git clone "$2" $git_dir >/dev/null 2>&1
(cd $git_dir && catch makepkg -csi --noconfirm)
}
## Run custom script
run_script() {
log running script "\e[1;96m$1\e[0m"
[ ! -f "${scriptdir:?not set}/$1" ] && { log -e script \'$1\' is not defined ; return ; }
catch source "${scriptdir:?not set}/$1"
}
## Script cleanup
cleanup() {
sleep 1
rm -rf $err $dbg $scriptdir $git_dir 2>/dev/null
tput rmcup
printf "FINISHED\nlogfile: %s\n" "$LOGFILE"
kill $(jobs -p)
exit
}
## Logging and error handling
log() {
case $1 in
-d) (($DEBUG)) || return ; l=DEBUG ; shift ;;
-e) l=ERROR ; shift ;;
-w) l=WARNING ; shift ;;
*) l=INFO ;;
esac
printf "[$(date --rfc-3339=seconds)] $l: "
echo -e $*
}
> $LOGFILE
exec > >(tee -a $LOGFILE)
exec 2>&1
tput smcup
trap 'cleanup' 1 2 EXIT
export -f log
{ err="$(mktemp -u /tmp/err-pipe.XXX)" ; dbg="$(mktemp -u /tmp/dbg-pipe.XXX)"; } && mkfifo $err $dbg
cat <> $err 2>/dev/null | while IFS= read line ; do log -w $line ; done &
cat <> $dbg 2>/dev/null | while IFS= read line ; do log -d $line ; done &
catch() { $@ >>$dbg 2>>$err; }
## Run main function
declare -a job_list
declare -a categories
declare -a choices
declare -i id=0
main $*