-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscripts-setup
executable file
·340 lines (306 loc) · 8.4 KB
/
scripts-setup
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
#!/bin/bash
#
# Setup or update an account with the scripts.
#
# Requires: git, sed
#
REPO="https://github.com/dang/scripts.git"
SCRIPTDIR="${HOME}/.scripts"
# Set usage output
USAGE="[-h |--help] [-f | --fixup] [-b <filename> | --braindead <filename> ] [-r <repo> | --repository <repo> [<directory>]"
LONGUSAGE="\t-h, --help\n\t\tPrint this help message
\t-f, --fixup\n\t\tFix up homedir for new links/copies
\t-b <filename>, --braindead <filename>\n\t\tGenerate a setup script for braindead systems
\t-r <repo>, --repository <repo>\n\t\tUse source repo <repo>. Default: ${REPO}
\t<directory>\n\t\tScripts directory. Defaults to ${SCRIPTDIR}"
# Standard functions
is_interactive() {
case $- in
*i*)
# Don't die in interactive shells
return 0
;;
*)
return 1
;;
esac
}
can_die() {
if (( BASH_SUBSHELL > 0 )); then
return 0
fi
if ! is_interactive; then
return 0
fi
return 1
}
die() {
echo "Failed: $@"
if [ ! -z "$(declare -F | grep "DFGcleanup")" ]; then
DFGcleanup "$@"
fi
if can_die; then
exit 1
fi
}
usage() {
local myusage;
if [ -n "${USAGE}" ]; then
myusage=${USAGE}
else
myusage="No usage given"
fi
if [ -n "$1" ]; then
echo "$@"
fi
echo ""
echo "Usage:"
echo "`basename $0` ${myusage}"
if [ -n "${LONGUSAGE}" ]; then
echo -e "${LONGUSAGE}"
fi
exit 1
}
# Script name
ME=$(basename $0)
# Parse arguments
ARGS=`getopt -o hb:fr: --long help,braindead:,fixup,repository: -n "${ME}" -- "$@"`
if [ $? != 0 ] ; then
usage
fi
eval set -- "$ARGS"
while true ; do
case "$1" in
-h|--help) usage; shift ;;
-f|--fixup) FIXUP="yes"; shift ;;
-b|--braindead) BRAINDEAD="$2"; shift 2 ;;
-r|--repository) REPO="$2"; shift 2 ;;
--) shift ; break ;;
* ) usage "Invalid argument $1";;
esac
done
# Remaining arguments are in $1, $2, etc. as normal
if [ -n "${1}" ]; then
if [ "$1" == "." ]; then
SCRIPTDIR=${PWD}
else
SCRIPTDIR=$1
fi
fi
# Array formats are: array["<targetpath>"] = "<file> [<file>...]"
# Each entry is found in $SCRIPTDIR/cfg/<targetpath>/<file> and is installed into ${HOME}/<targetpath>/<file>
# These are items that should be symlinked to the scripts dir, so they're always up-to-date.
declare -A LNSET=(
["."]=".ackrc .atoolrc .bashrc .cvsrc .face .gdbinit .gitignore .gvimrc .inputrc .lesskey .pentadactylrc .profile .rpmmacros .tigrc .tmux.conf .toprc .vim .vim:.config/nvim .vimrc .vrapperrc .xinitrc"
[".cgdb"]="cgdbrc"
[".config"]="awesome luakit hypr waybar"
[".config/xfce4"]="terminal"
)
# These are copied, so that they can be locally modified
declare -A CPSET=(
["."]=".gitconfig"
[".ssh"]="config"
[".bashrc.d/env"]="00defaults prompt python-virtualenv user-path"
[".bashrc.d/actions"]="aliases"
)
# These have changed location and need to be moved
declare -A MVSET=(
[".bashrc.d/00defaults"]=".bashrc.d/env/00defaults"
[".bashrc.d/prompt"]=".bashrc.d/env/prompt"
[".bashrc.d/python-virtualenv"]=".bashrc.d/env/python-virtualenv"
[".bashrc.d/user-path"]=".bashrc.d/env/user-path"
[".bashrc.d/aliases"]=".bashrc.d/actions/aliases"
)
WANTPROGS="atool tmux clipit nvim"
umask 0077
function cmd_exists {
which $1 > /dev/null 2>&1
}
# getsrcdst ${entry} src dst
#
# Get a source/destination pair from a variable of the from "foo[:bar]"
# Result will be in local variables src and dst
#
function getsrcdst {
local __entry=$1
local __resultsrc=$2
local __resultdst=$3
IFS=':' read -ra colon <<< "${__entry}"
local __src=${colon[0]}
local __dst=${__src}
if [ -n "${colon[1]}" ]; then
__dst=${colon[1]}
fi
if [[ "$__resultsrc" ]]; then
eval $__resultsrc="'${__src}'"
eval $__resultdst="'${__dst}'"
fi
}
# checkexists ASSOC_ARRAY || die "failed"
#
# Check if the entries in the array exist
#
# Note: do *not* dereference the array in the call
function checkexists {
local _str_arr="$(declare -p $1)"
eval "local -A array=${_str_arr#*=}"
local src dst
for k in "${!array[@]}"; do
for f in ${array[$k]}; do
getsrcdst "${f}" src dst
if [ -a "${HOME}/${k}/${dst}" ]; then
die "${HOME}/${k}/${dst} exists; not continuing" || return 1
fi
done
done
}
# braindead ASSOC_ARRAY $outfile [$copy]
#
# Generate a script $outfile that will install scripts on a braindead system
# that doesn't handle associative arrays properly. If $copy is given and true,
# copy files. Otherwise, symlink them
#
# Note: do *not* dereference the array in the call
function braindead {
local _str_arr="$(declare -p $1)"
eval "local -A array=${_str_arr#*=}"
local outfile=$2
local copy=$3
if [ -z "${outfile}" ]; then
die "No outfile" || return 1
fi
for k in "${!array[@]}"; do
local base="${k}/"
if [ "$k" == "." ]; then
# no extra ./
base=""
fi
for f in ${array[$k]}; do
local src dst
getsrcdst "${f}" src dst
local basedir=$(dirname ${base}${dst}})
echo mkdir -p "${HOME}/${basedir}" >> "${outfile}"
if [ -z "${copy}" ]; then
if [ -n "${FIXUP}" ]; then
echo rm "${HOME}/${base}${dst}}" >> "${outfile}"
fi
echo ln -s "${HOME}/.scripts/cfg/${base}${src}" "${HOME}/${base}${dst}}" \|\| die "failed to link ${base}${src}" >> "${outfile}"
else
if [ -n "${FIXUP}" ]; then
# Skip existing files
echo if [ ! -e "${HOME}/${base}${dst}}" ]\; then >> "${outfile}"
echo cp -a "${HOME}/.scripts/cfg/${base}${src}" "${HOME}/${base}${dst}}" \|\| die "failed to copy ${base}${src}" >> "${outfile}"
echo fi >> "${outfile}"
fi
fi
done
done
}
# install ASSOC_ARRAY [$copy]
#
# Install the entries in the array. If copy is given and not empty, copy them.
# Otherwise, symlink them
#
# Note: do *not* dereference the array in the call
function install {
local _str_arr="$(declare -p $1)"
eval "local -A array=${_str_arr#*=}"
local copy=$2
for k in "${!array[@]}"; do
local base="${k}/"
if [ "$k" == "." ]; then
# no extra ./
base=""
fi
for f in ${array[$k]}; do
local src dst
getsrcdst "${f}" src dst
local basedir=$(dirname ${base}${src})
mkdir -p "${HOME}/${basedir}"
if [ -z "${copy}" ]; then
if [ -n "${FIXUP}" ]; then
rm "${HOME}/${base}${dst}"
fi
# Makes sure any target directories exist
local tgtdir=$(dirname ${dst})
mkdir -p "${HOME}/${base}/${tgtdir}"
ln -s "${HOME}/.scripts/cfg/${base}${src}" "${HOME}/${base}${dst}" || die "failed to link ${base}${src}" || return 1
else
if [ -n "${FIXUP}" ]; then
# Skip existing files
if [ -e "${HOME}/${base}${dst}" ]; then
continue
fi
fi
cp -a "${HOME}/.scripts/cfg/${base}${src}" "${HOME}/${base}${dst}" || die "failed to copy ${base}${src}" || return 1
fi
done
done
}
cmd_exists sed || die "You don't have sed installed, sorry"
if [ -n "${BRAINDEAD}" ]; then
rm "${BRAINDEAD}"
echo "#!/bin/bash" > "${BRAINDEAD}"
echo 'die() { echo "Failed: $@"; exit 1; }' >> "${BRAINDEAD}"
braindead LNSET "${BRAINDEAD}"
braindead CPSET "${BRAINDEAD}"
echo "Wrote ${BRAINDEAD}"
exit
fi
if [ -z "${FIXUP}" ]; then
# Check for conflicts
checkexists LNSET || die "Not overriting symlink files"
checkexists CPSET || die "Not overriting copy files"
if [ ! -d "${SCRIPTDIR}/.git" ]; then
SAVEDIR=${PWD}
cmd_exists git || die "You don't have git installed, sorry"
cd $(dirname "${SCRIPTDIR}")
git clone ${REPO} $(basename ${SCRIPTDIR})
cd $(basename "${SCRIPTDIR}")
git submodule update --init --recursive
cd "${SAVEDIR}"
fi
fi
if [ ! -d "${SCRIPTDIR}/.git" ]; then
echo "Failed to clone scripts repo from ${REPO}"
exit 2
fi
cd ${HOME}
# Set up .scripts symlink
ln -s ${SCRIPTDIR} .scripts
if [ -h "${SCRIPTDIR}/.scripts" ]; then
# installed into .scripts; remove extra symlink
rm "${SCRIPTDIR}/.scripts"
fi
# Special setup: fix moved files
if [ -n "${FIXUP}" ]; then
for k in "${!MVSET[@]}"; do
for f in ${MVSET[$k]}; do
if [ -e "${HOME}/${k}" ]; then
basedir=$(dirname $f{})
mkdir -p "${HOME}/${basedir}"
mv "${HOME}/${k}" "${HOME}/${f}"
fi
done
done
fi
# Install files
install LNSET || die "Failed to install symlink files"
install CPSET "copy" || die "Failed to install copy files"
# Set up less
lesskey
# Initialize the flavor
export SCRIPTS_SETUP="yes"
. ${SCRIPTDIR}/bashrc.d/env/flavor
if [ -f "${SCRIPTDIR}/bashrc.d/flavor/${FLAVOR}/setup" ]; then
. ${SCRIPTDIR}/bashrc.d/flavor/${FLAVOR}/setup
fi
# Look to see if my desired programs are installed
for i in ${WANTPROGS}; do
cmd_exists || NEEDPROGS="$i ${NEEDPROGS}"
done
echo "Done."
echo "You need to edit ${HOME}/.bashrc.d/* for your your local settings"
if [ -n "${NEEDPROGS}" ]; then
echo "Please install ${NEEDPROGS}"
fi