-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmakeln
More file actions
executable file
·467 lines (420 loc) · 12.1 KB
/
makeln
File metadata and controls
executable file
·467 lines (420 loc) · 12.1 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
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
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
#! /bin/bash
source ./functions
[[ $TCSHRC_DEBUG ]] && echo "mklnDEBUG: starting pre-main checks"
if [[ ! $mydir -ef $PWD ]]
then
die "sorry; must run from $mydir"
fi
# Probably $LOCALHOSTNAME is already set, but it's pretty tragic if it's not. Better safe than
# sorry. Note that this utilizes the same method that rc/tcshrc does.
: ${LOCALHOSTNAME:=`$mydir/root/lbin/localhostname`}
# Determine what type of machine we're on:
# "personal" : we have free rein to do whatever we want
# "work" : also free rein, but there are a few extra things to set up
# "vagrant" : a work virt that has some constraints
# "ec2" : an EC2 server for work that has a *lot* of constraints
# "ec2-sandbox" : an EC2 server for work that has way fewer constraints
[[ -d ~/.vagrant.d/boxes/ce-dev-sandbox ]] && MACHINE_TYPE="work"
[[ $(id -un) == "vagrant" ]] && MACHINE_TYPE="vagrant"
is-ec2 && [[ $LOCALHOSTNAME != "quin-"* ]] && MACHINE_TYPE="ec2"
is-ec2 && [[ $LOCALHOSTNAME == "quin-"* ]] && MACHINE_TYPE="ec2-sandbox"
[[ "in all other cases ..." && ! $MACHINE_TYPE ]] && MACHINE_TYPE="personal"
[[ $1 == refresh ]] && echo "$0: full refresh for $MACHINE_TYPE machine"
###########################
# Pre-initialization for EC2 sandboxes
###########################
if [[ $MACHINE_TYPE == "ec2-sandbox" ]]
then
# first the stuff we can always do
mkdir -p ~/local/data
mkdir -p ~/local/fortunes
make_link $mydir/local/vagrant-sandbox/bin $HOME/local/bin
make_link ~/work/vimS $HOME/local/data/vimS
# then the stuff we should only do if specifically requested
if [[ $1 == refresh ]]
then
# backup bog-standard config files so we can replace them with personalized ones
for conf in ~/.vctools/vctools.conf ~/.bash_aliases
do
if [[ -e $conf && ! -L $conf ]]
then
# still have the original VCtools config from the sandbox build
# have to move that out of the way so we can bring in our symlink
mv $conf $conf.orig
fi
done
# set up local Perl directory
_localperl=~/perl5
if ! [[ -d $_localperl ]]
then
perl -Mlocal::lib -le "local::lib->ensure_dir_structure_for('$_localperl')"
myperl-cpm bootstrap
fi
# ensure `vagrant` project is set up
if [[ ! -d /var/tmp/launch-projects/vagrant ]]
then
launch PREPARE $CHEOPSROOT/vagrant
fi
fi
fi
###########################
# MAIN
###########################
[[ $TCSHRC_DEBUG ]] && echo "mklnDEBUG: starting main"
# make sure we have the dirs we need (useful for a brand-spanking-new homedir)
[[ -d ~/.ssh ]] || mkdir ~/.ssh
# ~/proj can be a bit trickier
if [[ $MACHINE_TYPE == "personal" || $MACHINE_TYPE == "work" ]]
then
proj_dir=$(storage_dir proj/common)
[[ -d $proj_dir ]] || die "make sure you mount or sync proj/ before running me"
make_link $proj_dir ~/common
fi
# do rc's first; they're moderately straightforward except for having to add
# . in front of the name ... these all go in ~
cd $mydir/rc
for file in *
do
make_link $mydir/rc/$file $HOME/.$file
done
# do localhost rc's, if any
localmach=$LOCALHOSTNAME
[[ $MACHINE_TYPE == "ec2"* ]] && localmach=vagrant-sandbox # not vagrant, but probably a sandbox
local_rcdir=$mydir/local/$localmach/rc
if [[ -d $local_rcdir ]]
then
cd $local_rcdir
for file in *
do
dest=$HOME/.$file
# don't allow local rc's to overwrite, even with confirmation
if [[ -e $dest && ! $local_rcdir/$file -ef $dest ]]
then
echo "WARNING! will not overwrite $dest with local link; skipping" >&2
else
make_link $local_rcdir/$file $dest
fi
done
fi
[[ $TCSHRC_DEBUG ]] && echo "mklnDEBUG: built simple rc's"
# do pidgin.layout, if any
p_layout=$mydir/local/$LOCALHOSTNAME/data/pidgin.layout
dest_dir=$HOME/local/data
if [[ -f $p_layout && ! -L $dest_dir ]]
then
dest=$dest_dir/pidgin.layout
make_link $p_layout $dest
fi
# .dzil dir will be built in three parts:
# # the directory itself will be made if it's not there
# (it can't be a symlink because it needs to contains files symlinked from
# two different places)
# # publicly available stuff from $mydir/dzil
# # the config.ini, which contains passwords and therefore isn't public-facing
# (that will be symlinked by the "sensitive" section, below)
if [[ $MACHINE_TYPE != "ec2" ]]
then
[[ -d ~/.dzil ]] || mkdir ~/.dzil
cd $mydir/dzil
for file in *
do
make_link $mydir/dzil/$file $HOME/.dzil/$file
done
fi
# .vctools dir is a bit like .dzil, only (mostly) simpler
# the only tricky bit is that the main vctools.conf file *might* have a
# host-specific override
if [[ $1 == refresh ]]
then
[[ -d ~/.vctools ]] || mkdir ~/.vctools
cd $mydir/vctools
local_vctools_conf=vctools.conf.${LOCALHOSTNAME%-i-*}
if [[ -r $local_vctools_conf ]]
then
make_link $mydir/vctools/$local_vctools_conf $HOME/.vctools/vctools.conf
elif [[ -r vctools.conf.$HOST ]]
then
make_link $mydir/vctools/vctools.conf.$HOST $HOME/.vctools/vctools.conf
else
make_copy vctools.conf $HOME/.vctools/vctools.conf
fi
for file in *
do
if [[ $file != vctools.conf* ]]
then
make_link $mydir/vctools/$file $HOME/.vctools/$file
fi
done
fi
# we have a few rc's in a separate place because they have passwords in them
if [[ $MACHINE_TYPE == "personal" || $MACHINE_TYPE == "work" ]]
then
alt_rcdir=~/docs/Dropbox/sensitive
if [[ -d $alt_rcdir ]]
then
cd $alt_rcdir
for file in *
do
if [[ -f $file ]] # skip directories
then
if [[ ${file/-/} != $file ]]
then
# there's a dash in it ... that means it goes underneath another dot-dir
lnfile=${file//-/\/}
else
lnfile=$file
fi
make_link $alt_rcdir/$file $HOME/.$lnfile
fi
done
fi
# not technically an rc, but is used for senstive API keys
make_link $alt_rcdir/ai $HOME/local/data/ai-keys
fi
# Claude Code configuration directories
if [[ $MACHINE_TYPE != "vagrant" ]]
then
claude_src=$mydir/conf/ai/claude
if [[ -d $claude_src ]]
then
[[ -d ~/.claude ]] || mkdir ~/.claude
cd $claude_src
for item in *
do
if [[ -d $item ]]
then
make_smart_dirlink $claude_src/$item ~/.claude/$item
elif [[ -f $item ]]
then
make_link $claude_src/$item ~/.claude/$item
fi
done
fi
fi
[[ $TCSHRC_DEBUG ]] && echo "mklnDEBUG: constructed special rc's"
# for bin, what we really want is for the whole directory to be symlinked
# this makes it easy to add new commands
# if there's already a directory there, though, we dare not just delete it
dir=~/bin
verify_dirlink $dir
make_link $mydir/bin $dir
# ditto for .cddb, only not as tragic if the dir already exists
# also not as tragic if we can't find it, since it isn't here in $mydir any more
if [[ $1 != refresh && $MACHINE_TYPE != "vagrant" && $MACHINE_TYPE != "ec2"* ]]
then
dir=~/.cddb
if [[ -d $dir ]]
then
verify_dirlink $dir
else
srcdir=$(find_dir /export/music/cddb $mydir/cddb)
if [[ -d $srcdir ]]
then
make_link $srcdir $dir
fi
fi
fi
# dirs to symlink in from external storage
if [[ $1 != refresh && $MACHINE_TYPE == "personal" || $MACHINE_TYPE == "work" ]]
then
dirs="rpg proj"
[[ $MACHINE_TYPE == "work" ]] && dirs="proj"
for dir in $dirs
do
src_dir=$(storage_dir $dir)
if [[ ! $src_dir ]]
then
die "can't find any external storage candidate for: $dir"
elif [[ -d $src_dir ]]
then
dest_dir=~/${src_dir##*/}
verify_dirlink $dest_dir
make_link $src_dir $dest_dir
fi
done
# this one gets renamed when linked
make_link $(storage_dir personal) ~/docs
# these only get done for work machines
if [[ $MACHINE_TYPE == "work" ]]
then
declare -A worklinks=( [work/ce]=~/work [work/timer]=~/timer [work/ce/vimS]=~/local/data/vimS )
for from in "${!worklinks[@]}"
do
src_dir=$(storage_dir $from)
if [[ ! $src_dir ]]
then
die "can't find any external storage candidate for: $dir"
elif [[ -d $src_dir ]]
then
dest_dir=${worklinks[$from]}
verify_dirlink $dest_dir
make_link $src_dir $dest_dir
fi
done
fi
fi
# dirs to symlink in from /export/proj as dot-dirs
if [[ $1 != refresh && $MACHINE_TYPE == "personal" && -d /export/proj ]]
then
for dir in cpan-testers
do
srcdir=/export/proj/$dir
destdir=~/.$dir
verify_dirlink $destdir
make_link $srcdir $destdir
done
fi
[[ $TCSHRC_DEBUG ]] && echo "mklnDEBUG: symlinked dirs"
# stuff to symlink in from /export/personal
if [[ $1 != refresh && $MACHINE_TYPE != "vagrant" && $MACHINE_TYPE != "ec2"* ]]
then
for dir in ~/vimS ~/.local/share/tomboy
do
verify_dirlink $dir
srcdir=$( storage_dir personal/$(basename $dir) )
make_link $srcdir $dir
done
fi
# Unison configuration files
# just symlink in what we've got
if [[ -d $mydir/unison && $MACHINE_TYPE == "personal" ]]
then
[[ -d ~/.unison ]] || mkdir ~/.unison
cd $mydir/unison
for file in *
do
make_link $mydir/unison/$file $HOME/.unison/$file
done
fi
# we're going to take this opportunity to build the index files that fortune needs, but there's
# always the possibility that we can't find strfile, so let's make a guess as to that too
strfile=$(which strfile 2>/dev/null)
if [[ -z $strfile ]]
then
if [[ -x /usr/sbin/strfile ]]
then
strfile=/usr/sbin/strfile
fi
fi
# if we couldn't find strfile at this point, there isn't much point in doing
# the fortune files, so we'll just skip it
if [[ -n $strfile ]]
then
# fortune files will occasionally sit in /usr/local/fortunes
# however, these days it's more likely in ~/local/fortunes instead
dir=$(find_dir ~/local/fortunes /usr/local/fortunes)
if [[ -d $dir ]]
then
cd $mydir/fortunes
for file in *
do
make_link $mydir/fortunes/$file $dir/$file
cd $dir
if [[ -L $file.dat ]]
then
/bin/rm -f $file.dat
fi
if [[ ! -e $file.dat || $file -nt $file.dat ]]
then
$strfile $file
fi
done
fi
fi
# now the special ones:
# 1: .screenrc.base
# if this file exists, don't mess with it
# if not, supply a useful default
if [[ ! -e ~/.screenrc.base ]]
then
cat >~/.screenrc.base <<END
bind ^_ source .screenrc.search
bind ^v source .screenrc.vctools
screen -t base
screen -t timer
stuff "timer\015"
screen -t man
stuff "man screen\015"
screen -t top top
screen -t root sudo su -
END
fi
# 2: .ssh/config
# the pieces of this file are in little chunks
# if the file is completely missing, start if off with the base config
# for each chunk, we need to know if that chunk is already in the config file
# if it is, do nothing
# if it isn't, add it
ssh_config=~/.ssh/config
cd $mydir
[[ -r $ssh_config ]] || cp ssh/config $ssh_config
for file in ssh/config.*
do
host=${file#ssh/config.}
if ! egrep -q "Host[ ]+$host" ~/.ssh/config 2>/dev/null
then
if [[ -n $(resolve_host $host) ]]
then
# if we can resolve the host already, don't use the HostName line
# this will help with hosts that can be either remote or on the local network
grep -v HostName $file >>$ssh_config
else
cat $file >>$ssh_config
fi
fi
done
# 3: .ssh/authorized_keys
# each public key needs to be put into authorized keys, but not if it's already there
cd $mydir
authfile=~/.ssh/authorized_keys
for file in ssh/*.pub
do
replace_in_file $authfile $file '{print $3}'
done
# 4: .ssh/known_hosts
# similar to authorized_keys, but for known_hosts
cd $mydir
knownfile=~/.ssh/known_hosts
for file in ssh/*.known
do
replace_in_file $knownfile $file '$1 != "#" {print $1}'
done
# 5: .ssh/
# may as well go ahead and fix the perms on this dir since little will
# actually work unless the perms are correct
chmod -R go-rwx ~/.ssh
##############################################
# Install crontab
# (but only on places where we have free rein)
##############################################
my_crondir=$mydir/conf/crontab
if [[ $MACHINE_TYPE == "personal" || $MACHINE_TYPE == "work" ]]
then
tmp_crontab=$(mktemp)
trap "/bin/rm -f $tmp_crontab" EXIT
cat $my_crondir/default.cron >$tmp_crontab
machine_cron=$my_crondir/$LOCALHOSTNAME.cron
if [[ -e $machine_cron ]]
then
cat $machine_cron >>$tmp_crontab
fi
if ! diff <(crontab -l) $tmp_crontab >/dev/null
then
echo "updating crontab" >&2
crontab $tmp_crontab
fi
elif [[ $MACHINE_TYPE == "ec2"* ]]
then
machine_cron=$my_crondir/${LOCALHOSTNAME%-i-*}.cron
if [[ -e $machine_cron ]]
then
if ! diff <(crontab -l) $machine_cron >/dev/null
then
echo "updating crontab" >&2
crontab $machine_cron
fi
fi
fi
###########################
# Subscripts
###########################