From 01067990cce27b7af94506f583de025d28e31c1b Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Sun, 5 Sep 2021 12:06:19 -0500 Subject: Change bootstrapping method Now uses a script, ./bootstrap.sh, and a file, ./bootstrap.manifest. --- bootstrap.sh | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100755 bootstrap.sh (limited to 'bootstrap.sh') diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..d37ef6a --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,195 @@ +#!/bin/sh +# Bootstrap file for XDG_CONFIG_HOME +# by Case Duckworth + +### License: + +# Everyone is permitted to do whatever with this software, without +# limitation. This software comes without any warranty whatsoever, +# but with two pieces of advice: +# - Don't hurt yourself. +# - Make good choices. + +### Commentary: + +# For some time now, there has been a standard place to put configuration files +# for various programs: $XDG_CONFIG_HOME. Slowly but surely, programs have +# been adapting to that standard for their configuration files, but there have +# been some stubborn holdouts. Examples include shells such as sh, bash, and +# zsh. + +# Luckily, the filesystem can help us. This script takes input from a file in +# its $PWD, bootstrap.manifest, and reads linking directions from tab-delimited +# lines in that file. Then, it creates links from within the cozy confines of +# $XDG_CONFIG_HOME to the wild west of ~, so that everyone is happy: you have +# your zen garden of configuration, and misbehaving programs have their bazaar. + +### Code: + +### Main entry point + +main() { + ## Sanity checking + # Since bootstrap.sh does some naive path-mangling, let's show an error + # if it's not run correctly. Yes, there are other ways to run a + # script. But this script should ideally be run, like, one time. Also + # you can obviously comment this out or change it if you know what + # you're doing! + + case "$0" in + ./*) ;; # this is the way bootstrap.sh /should/ be run. + *) + printf >&2 'Weird invocation! %s\n' "$*" + printf >&2 'Try: cd ; ./bootstrap.sh\n' + exit 127 + ;; + esac + + ## Variables + + # option: -d/--dry-run + : "${BOOTSTRAP_ACTION:=link}" + # option: -v/--verbose + : "${BOOTSTRAP_DEBUG:=false}" + # option: -k/--keep-going + : "${BOOTSTRAP_QUIT_ON_ERROR:=true}" + # option: -m/--manifest FILE + : "${BOOTSTRAP_MANIFEST_FILE:=bootstrap.manifest}" + # option: -- (rest are passed to ln) + : "${BOOTSTRAP_LN_ARGS:=-s}" + + ## Handle command-line flags + # Basically an easier way of setting the above variables. + while [ -n "$1" ]; do + case "$1" in + -h|--help) + cat >&2 <&2 "Bad argument: '$2'" + exit 129 + ;; + esac + BOOTSTRAP_MANIFEST_FILE="$2" + shift 2 + ;; + -f|--force) + BOOTSTRAP_LN_ARGS="$BOOTSTRAP_LN_ARGS -f" + shift 1 + ;; + --) + BOOTSTRAP_LN_ARGS="$@" + break + ;; + esac + done + + ## Main loop + while IFS=' ' read -r source destination; do + # Ignore lines beginning with '#' + case "$source" in + '#'*) + if "$BOOTSTRAP_DEBUG"; then + printf >&2 'Skipping comment: %s %s\n' \ + "$source" "$destination" + fi + continue + ;; + esac + + # Ignore empty lines, or lines with only SOURCE or DESTINATION + if [ -z "$source" ] || [ -z "$destination" ]; then + if "$BOOTSTRAP_DEBUG"; then + printf >&2 'Skipping line: %s\t%s\n' \ + "$source" "$destination" + fi + continue + fi + + # Do the thing + if ! dispatch "$source" "$destination"; then + printf >&2 'ERROR: %s -> %s\n' \ + "$source" "$destination" + if "$BOOTSTRAP_QUIT_ON_ERROR"; then + exit "$dispatch_error" + fi + fi + done < "$BOOTSTRAP_MANIFEST_FILE" +} + + +### Functions + +dispatch() { # dispatch SOURCE DESTINATION + # Depending on environment variables, do the linking or displaying or + # whatever of a source and a destination. + + ## Variables + + src="$1" + dest="$2" + dispatch_error=0 # success + + ## Sanitize pathnames + + # If the SOURCE starts with ~, /, or $, keep it as-is; otherwise, + # prepend "$PWD/". + case "$src" in + '/'* | '~'* | '$'* ) ;; + *) src="$PWD/$src" ;; + esac + + # Convert ~ to $HOME in SOURCE and DESTINATION, to get around shell + # quoting rules. + src="$(printf '%s\n' "$src" | sed "s#^~#$HOME#")" + dest="$(printf '%s\n' "$dest" | sed "s#^~#$HOME#")" + + ## Do the thing + + # /Always/ tell the user what we're doing. + printf >&2 "ln %s %s %s\n" "$BOOTSTRAP_LN_ARGS" "$src" "$dest" + + case "$BOOTSTRAP_ACTION" in + link) # actually ... do the links + ln $BOOTSTRAP_LN_ARGS "$src" "$dest" || + dispatch_error="$?" + ;; + print) ;; # already printed. + esac + + return "$dispatch_error" +} + +### Do the thing + +main "$@" -- cgit 1.4.1-21-gabe81