diff options
author | Case Duckworth | 2021-09-05 12:06:19 -0500 |
---|---|---|
committer | Case Duckworth | 2021-09-05 12:07:10 -0500 |
commit | 01067990cce27b7af94506f583de025d28e31c1b (patch) | |
tree | 326acef39b1956003a2555ff405fe082098901a0 /bootstrap.sh | |
parent | Search multiple files for __git_ps1 function (diff) | |
download | etc-01067990cce27b7af94506f583de025d28e31c1b.tar.gz etc-01067990cce27b7af94506f583de025d28e31c1b.zip |
Change bootstrapping method
Now uses a script, ./bootstrap.sh, and a file, ./bootstrap.manifest.
Diffstat (limited to 'bootstrap.sh')
-rwxr-xr-x | bootstrap.sh | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..d37ef6a --- /dev/null +++ b/bootstrap.sh | |||
@@ -0,0 +1,195 @@ | |||
1 | #!/bin/sh | ||
2 | # Bootstrap file for XDG_CONFIG_HOME | ||
3 | # by Case Duckworth <acdw@acdw.net> | ||
4 | |||
5 | ### License: | ||
6 | |||
7 | # Everyone is permitted to do whatever with this software, without | ||
8 | # limitation. This software comes without any warranty whatsoever, | ||
9 | # but with two pieces of advice: | ||
10 | # - Don't hurt yourself. | ||
11 | # - Make good choices. | ||
12 | |||
13 | ### Commentary: | ||
14 | |||
15 | # For some time now, there has been a standard place to put configuration files | ||
16 | # for various programs: $XDG_CONFIG_HOME. Slowly but surely, programs have | ||
17 | # been adapting to that standard for their configuration files, but there have | ||
18 | # been some stubborn holdouts. Examples include shells such as sh, bash, and | ||
19 | # zsh. | ||
20 | |||
21 | # Luckily, the filesystem can help us. This script takes input from a file in | ||
22 | # its $PWD, bootstrap.manifest, and reads linking directions from tab-delimited | ||
23 | # lines in that file. Then, it creates links from within the cozy confines of | ||
24 | # $XDG_CONFIG_HOME to the wild west of ~, so that everyone is happy: you have | ||
25 | # your zen garden of configuration, and misbehaving programs have their bazaar. | ||
26 | |||
27 | ### Code: | ||
28 | |||
29 | ### Main entry point | ||
30 | |||
31 | main() { | ||
32 | ## Sanity checking | ||
33 | # Since bootstrap.sh does some naive path-mangling, let's show an error | ||
34 | # if it's not run correctly. Yes, there are other ways to run a | ||
35 | # script. But this script should ideally be run, like, one time. Also | ||
36 | # you can obviously comment this out or change it if you know what | ||
37 | # you're doing! | ||
38 | |||
39 | case "$0" in | ||
40 | ./*) ;; # this is the way bootstrap.sh /should/ be run. | ||
41 | *) | ||
42 | printf >&2 'Weird invocation! %s\n' "$*" | ||
43 | printf >&2 'Try: cd <bootstrap-dir>; ./bootstrap.sh\n' | ||
44 | exit 127 | ||
45 | ;; | ||
46 | esac | ||
47 | |||
48 | ## Variables | ||
49 | |||
50 | # option: -d/--dry-run | ||
51 | : "${BOOTSTRAP_ACTION:=link}" | ||
52 | # option: -v/--verbose | ||
53 | : "${BOOTSTRAP_DEBUG:=false}" | ||
54 | # option: -k/--keep-going | ||
55 | : "${BOOTSTRAP_QUIT_ON_ERROR:=true}" | ||
56 | # option: -m/--manifest FILE | ||
57 | : "${BOOTSTRAP_MANIFEST_FILE:=bootstrap.manifest}" | ||
58 | # option: -- (rest are passed to ln) | ||
59 | : "${BOOTSTRAP_LN_ARGS:=-s}" | ||
60 | |||
61 | ## Handle command-line flags | ||
62 | # Basically an easier way of setting the above variables. | ||
63 | while [ -n "$1" ]; do | ||
64 | case "$1" in | ||
65 | -h|--help) | ||
66 | cat >&2 <<END_HELP | ||
67 | Usage: ./bootstrap.sh [-d] [-v] [-k] [-m FILE] [-f] [-- LN_OPTS] | ||
68 | OPTIONS: | ||
69 | -d, --dry-run | ||
70 | Only print what would happen. | ||
71 | -v, --verbose | ||
72 | Be more verbose about things. | ||
73 | -k, --keep-going | ||
74 | Keep going after an error. | ||
75 | -f, --force | ||
76 | Force linking. Passes -f to ln. | ||
77 | -m FILE, --manifest FILE | ||
78 | Use FILE as manifest. | ||
79 | Default: bootstrap.manifest. | ||
80 | -- Signify end of options. The rest are passed to ln. | ||
81 | END_HELP | ||
82 | exit | ||
83 | ;; | ||
84 | -d|--dry-run) | ||
85 | BOOTSTRAP_ACTION=print | ||
86 | shift 1 | ||
87 | ;; | ||
88 | -v|--verbose) | ||
89 | BOOTSTRAP_DEBUG=true | ||
90 | shift 1 | ||
91 | ;; | ||
92 | -k|--keep-going) | ||
93 | BOOTSTRAP_QUIT_ON_ERROR=false | ||
94 | shift 1 | ||
95 | ;; | ||
96 | -m|--manifest) | ||
97 | case "$2" in | ||
98 | ''|-*) | ||
99 | printf >&2 "Bad argument: '$2'" | ||
100 | exit 129 | ||
101 | ;; | ||
102 | esac | ||
103 | BOOTSTRAP_MANIFEST_FILE="$2" | ||
104 | shift 2 | ||
105 | ;; | ||
106 | -f|--force) | ||
107 | BOOTSTRAP_LN_ARGS="$BOOTSTRAP_LN_ARGS -f" | ||
108 | shift 1 | ||
109 | ;; | ||
110 | --) | ||
111 | BOOTSTRAP_LN_ARGS="$@" | ||
112 | break | ||
113 | ;; | ||
114 | esac | ||
115 | done | ||
116 | |||
117 | ## Main loop | ||
118 | while IFS=' ' read -r source destination; do | ||
119 | # Ignore lines beginning with '#' | ||
120 | case "$source" in | ||
121 | '#'*) | ||
122 | if "$BOOTSTRAP_DEBUG"; then | ||
123 | printf >&2 'Skipping comment: %s %s\n' \ | ||
124 | "$source" "$destination" | ||
125 | fi | ||
126 | continue | ||
127 | ;; | ||
128 | esac | ||
129 | |||
130 | # Ignore empty lines, or lines with only SOURCE or DESTINATION | ||
131 | if [ -z "$source" ] || [ -z "$destination" ]; then | ||
132 | if "$BOOTSTRAP_DEBUG"; then | ||
133 | printf >&2 'Skipping line: %s\t%s\n' \ | ||
134 | "$source" "$destination" | ||
135 | fi | ||
136 | continue | ||
137 | fi | ||
138 | |||
139 | # Do the thing | ||
140 | if ! dispatch "$source" "$destination"; then | ||
141 | printf >&2 'ERROR: %s -> %s\n' \ | ||
142 | "$source" "$destination" | ||
143 | if "$BOOTSTRAP_QUIT_ON_ERROR"; then | ||
144 | exit "$dispatch_error" | ||
145 | fi | ||
146 | fi | ||
147 | done < "$BOOTSTRAP_MANIFEST_FILE" | ||
148 | } | ||
149 | |||
150 | |||
151 | ### Functions | ||
152 | |||
153 | dispatch() { # dispatch SOURCE DESTINATION | ||
154 | # Depending on environment variables, do the linking or displaying or | ||
155 | # whatever of a source and a destination. | ||
156 | |||
157 | ## Variables | ||
158 | |||
159 | src="$1" | ||
160 | dest="$2" | ||
161 | dispatch_error=0 # success | ||
162 | |||
163 | ## Sanitize pathnames | ||
164 | |||
165 | # If the SOURCE starts with ~, /, or $, keep it as-is; otherwise, | ||
166 | # prepend "$PWD/". | ||
167 | case "$src" in | ||
168 | '/'* | '~'* | '$'* ) ;; | ||
169 | *) src="$PWD/$src" ;; | ||
170 | esac | ||
171 | |||
172 | # Convert ~ to $HOME in SOURCE and DESTINATION, to get around shell | ||
173 | # quoting rules. | ||
174 | src="$(printf '%s\n' "$src" | sed "s#^~#$HOME#")" | ||
175 | dest="$(printf '%s\n' "$dest" | sed "s#^~#$HOME#")" | ||
176 | |||
177 | ## Do the thing | ||
178 | |||
179 | # /Always/ tell the user what we're doing. | ||
180 | printf >&2 "ln %s %s %s\n" "$BOOTSTRAP_LN_ARGS" "$src" "$dest" | ||
181 | |||
182 | case "$BOOTSTRAP_ACTION" in | ||
183 | link) # actually ... do the links | ||
184 | ln $BOOTSTRAP_LN_ARGS "$src" "$dest" || | ||
185 | dispatch_error="$?" | ||
186 | ;; | ||
187 | print) ;; # already printed. | ||
188 | esac | ||
189 | |||
190 | return "$dispatch_error" | ||
191 | } | ||
192 | |||
193 | ### Do the thing | ||
194 | |||
195 | main "$@" | ||