about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xbootstrap.sh310
1 files changed, 159 insertions, 151 deletions
diff --git a/bootstrap.sh b/bootstrap.sh index d37ef6a..09b8cd6 100755 --- a/bootstrap.sh +++ b/bootstrap.sh
@@ -29,165 +29,173 @@
29### Main entry point 29### Main entry point
30 30
31main() { 31main() {
32 ## Sanity checking 32 ## Sanity checking
33 # Since bootstrap.sh does some naive path-mangling, let's show an error 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 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 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 36 # you can obviously comment this out or change it if you know what
37 # you're doing! 37 # you're doing!
38 38
39 case "$0" in 39 case "$0" in
40 ./*) ;; # this is the way bootstrap.sh /should/ be run. 40 ./*) ;; # this is the way bootstrap.sh /should/ be run.
41 *) 41 *)
42 printf >&2 'Weird invocation! %s\n' "$*" 42 printf >&2 'Weird invocation! %s\n' "$*"
43 printf >&2 'Try: cd <bootstrap-dir>; ./bootstrap.sh\n' 43 printf >&2 'Try: cd <bootstrap-dir>; ./bootstrap.sh\n'
44 exit 127 44 exit 127
45 ;; 45 ;;
46 esac 46 esac
47 47
48 ## Variables 48 ## Variables
49 49
50 # option: -d/--dry-run 50 # option: -d/--dry-run
51 : "${BOOTSTRAP_ACTION:=link}" 51 : "${BOOTSTRAP_ACTION:=link}"
52 # option: -v/--verbose 52 # option: -v/--verbose
53 : "${BOOTSTRAP_DEBUG:=false}" 53 : "${BOOTSTRAP_DEBUG:=false}"
54 # option: -k/--keep-going 54 # option: -k/--keep-going
55 : "${BOOTSTRAP_QUIT_ON_ERROR:=true}" 55 : "${BOOTSTRAP_QUIT_ON_ERROR:=true}"
56 # option: -m/--manifest FILE 56 # option: -m/--manifest FILE
57 : "${BOOTSTRAP_MANIFEST_FILE:=bootstrap.manifest}" 57 : "${BOOTSTRAP_MANIFEST_FILE:=bootstrap.manifest}"
58 # option: -- (rest are passed to ln) 58 # option: -- (rest are passed to ln)
59 : "${BOOTSTRAP_LN_ARGS:=-s}" 59 : "${BOOTSTRAP_LN_ARGS:=-s}"
60 60
61 ## Handle command-line flags 61 ## Handle command-line flags
62 # Basically an easier way of setting the above variables. 62 # Basically an easier way of setting the above variables.
63 while [ -n "$1" ]; do 63 while [ -n "$1" ]; do
64 case "$1" in 64 case "$1" in
65 -h|--help) 65 -h|--help)
66 cat >&2 <<END_HELP 66 cat >&2 <<END_HELP
67Usage: ./bootstrap.sh [-d] [-v] [-k] [-m FILE] [-f] [-- LN_OPTS] 67Usage: ./bootstrap.sh [-d] [-v] [-k] [-m FILE] [-f] [-- LN_OPTS]
68OPTIONS: 68OPTIONS:
69 -d, --dry-run 69 -d, --dry-run
70 Only print what would happen. 70 Only print what would happen.
71 -v, --verbose 71 -v, --verbose
72 Be more verbose about things. 72 Be more verbose about things.
73 -k, --keep-going 73 -k, --keep-going
74 Keep going after an error. 74 Keep going after an error.
75 -f, --force 75 -f, --force
76 Force linking. Passes -f to ln. 76 Force linking. Passes -f to ln.
77 -m FILE, --manifest FILE 77 -m FILE, --manifest FILE
78 Use FILE as manifest. 78 Use FILE as manifest.
79 Default: bootstrap.manifest. 79 Default: bootstrap.manifest.
80 -- Signify end of options. The rest are passed to ln. 80 -- Signify end of options. The rest are passed to ln.
81END_HELP 81END_HELP
82 exit 82 exit
83 ;; 83 ;;
84 -d|--dry-run) 84 -d|--dry-run)
85 BOOTSTRAP_ACTION=print 85 BOOTSTRAP_ACTION=print
86 shift 1 86 shift 1
87 ;; 87 ;;
88 -v|--verbose) 88 -v|--verbose)
89 BOOTSTRAP_DEBUG=true 89 BOOTSTRAP_DEBUG=true
90 shift 1 90 shift 1
91 ;; 91 ;;
92 -k|--keep-going) 92 -k|--keep-going)
93 BOOTSTRAP_QUIT_ON_ERROR=false 93 BOOTSTRAP_QUIT_ON_ERROR=false
94 shift 1 94 shift 1
95 ;; 95 ;;
96 -m|--manifest) 96 -m|--manifest)
97 case "$2" in 97 case "$2" in
98 ''|-*) 98 ''|-*)
99 printf >&2 "Bad argument: '$2'" 99 printf >&2 "Bad argument: '$2'"
100 exit 129 100 exit 129
101 ;; 101 ;;
102 esac 102 esac
103 BOOTSTRAP_MANIFEST_FILE="$2" 103 BOOTSTRAP_MANIFEST_FILE="$2"
104 shift 2 104 shift 2
105 ;; 105 ;;
106 -f|--force) 106 -f|--force)
107 BOOTSTRAP_LN_ARGS="$BOOTSTRAP_LN_ARGS -f" 107 BOOTSTRAP_LN_ARGS="$BOOTSTRAP_LN_ARGS -f"
108 shift 1 108 shift 1
109 ;; 109 ;;
110 --) 110 --)
111 BOOTSTRAP_LN_ARGS="$@" 111 shift 1
112 break 112 BOOTSTRAP_LN_ARGS="$@"
113 ;; 113 break
114 esac 114 ;;
115 done 115 esac
116 116 done
117 ## Main loop 117
118 while IFS=' ' read -r source destination; do 118 ## Main loop
119 # Ignore lines beginning with '#' 119 while IFS=' ' read -r source destination; do
120 case "$source" in 120 # Ignore lines beginning with '#'
121 '#'*) 121 case "$source" in
122 if "$BOOTSTRAP_DEBUG"; then 122 '#'*)
123 printf >&2 'Skipping comment: %s %s\n' \ 123 if "$BOOTSTRAP_DEBUG"; then
124 "$source" "$destination" 124 printf >&2 'Skipping comment: %s %s\n' \
125 fi 125 "$source" "$destination"
126 continue 126 fi
127 ;; 127 continue
128 esac 128 ;;
129 129 esac
130 # Ignore empty lines, or lines with only SOURCE or DESTINATION 130
131 if [ -z "$source" ] || [ -z "$destination" ]; then 131 # Ignore empty lines, or lines with only SOURCE or DESTINATION
132 if "$BOOTSTRAP_DEBUG"; then 132 if [ -z "$source" ] || [ -z "$destination" ]; then
133 printf >&2 'Skipping line: %s\t%s\n' \ 133 if "$BOOTSTRAP_DEBUG"; then
134 "$source" "$destination" 134 printf >&2 'Skipping line: %s\t%s\n' \
135 fi 135 "$source" "$destination"
136 continue 136 fi
137 fi 137 continue
138 138 fi
139 # Do the thing 139
140 if ! dispatch "$source" "$destination"; then 140 # Do the thing
141 printf >&2 'ERROR: %s -> %s\n' \ 141 if ! dispatch "$source" "$destination"; then
142 "$source" "$destination" 142 printf >&2 'ERROR: %s -> %s\n' \
143 if "$BOOTSTRAP_QUIT_ON_ERROR"; then 143 "$source" "$destination"
144 exit "$dispatch_error" 144 if "$BOOTSTRAP_QUIT_ON_ERROR"; then
145 fi 145 exit "$dispatch_error"
146 fi 146 fi
147 done < "$BOOTSTRAP_MANIFEST_FILE" 147 fi
148 done < "$BOOTSTRAP_MANIFEST_FILE"
148} 149}
149 150
150
151### Functions 151### Functions
152 152
153dispatch() { # dispatch SOURCE DESTINATION 153dispatch() { # dispatch SOURCE DESTINATION
154 # Depending on environment variables, do the linking or displaying or 154 # Depending on environment variables, do the linking or displaying or
155 # whatever of a source and a destination. 155 # whatever of a source and a destination.
156 156
157 ## Variables 157 ## Variables
158 158
159 src="$1" 159 src="$1"
160 dest="$2" 160 dest="$2"
161 dispatch_error=0 # success 161 dispatch_error=0 # success
162 162
163 ## Sanitize pathnames 163 ## Sanitize pathnames
164 164
165 # If the SOURCE starts with ~, /, or $, keep it as-is; otherwise, 165 # If the SOURCE starts with ~, /, or $, keep it as-is; otherwise,
166 # prepend "$PWD/". 166 # prepend "$PWD/".
167 case "$src" in 167 case "$src" in
168 '/'* | '~'* | '$'* ) ;; 168 '/'* | '~'* | '$'* ) ;;
169 *) src="$PWD/$src" ;; 169 *) src="$PWD/$src" ;;
170 esac 170 esac
171 171
172 # Convert ~ to $HOME in SOURCE and DESTINATION, to get around shell 172 # Convert ~ to $HOME in SOURCE and DESTINATION, to get around shell
173 # quoting rules. 173 # quoting rules.
174 src="$(printf '%s\n' "$src" | sed "s#^~#$HOME#")" 174 src="$(printf '%s\n' "$src" | sed "s#^~#$HOME#")"
175 dest="$(printf '%s\n' "$dest" | sed "s#^~#$HOME#")" 175 dest="$(printf '%s\n' "$dest" | sed "s#^~#$HOME#")"
176 176
177 ## Do the thing 177 ## Do the thing
178 178
179 # /Always/ tell the user what we're doing. 179 # /Always/ tell the user what we're doing.
180 printf >&2 "ln %s %s %s\n" "$BOOTSTRAP_LN_ARGS" "$src" "$dest" 180 if [ -f "$dest" ]; then
181 181 printf >&2 'mv %s %s.old\n' "$dest" "$dest"
182 case "$BOOTSTRAP_ACTION" in 182 fi
183 link) # actually ... do the links 183 printf >&2 "ln %s %s %s\n" "$BOOTSTRAP_LN_ARGS" "$src" "$dest"
184 ln $BOOTSTRAP_LN_ARGS "$src" "$dest" || 184
185 dispatch_error="$?" 185 case "$BOOTSTRAP_ACTION" in
186 ;; 186 link) # actually ... do the links
187 print) ;; # already printed. 187 # if DESTINATION exists, move it to DESTINATION.old
188 esac 188 if [ -f "$dest" ]; then
189 189 mv "$dest" "$dest.old"
190 return "$dispatch_error" 190 fi
191
192 ln $BOOTSTRAP_LN_ARGS "$src" "$dest" ||
193 dispatch_error="$?"
194 ;;
195 print) ;; # already printed.
196 esac
197
198 return "$dispatch_error"
191} 199}
192 200
193### Do the thing 201### Do the thing