Created
April 4, 2012 21:10
-
-
Save glesica/2305700 to your computer and use it in GitHub Desktop.
A script for linking dot files into a home directory.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# install.sh | |
# Author: George Lesica <[email protected]> | |
# Description: Deploy script for my dotfiles repo. | |
# License: Public Domain (where it exists), any OSI-approved | |
# license elsewhere. | |
# | |
# Configuration | |
# | |
repo="`pwd`" | |
src="${repo}/home" | |
manifest="${repo}/manifest" | |
target="$HOME" | |
# | |
# Defaults | |
# | |
do_backup=1 # Back up existing files. Default: true. | |
do_copy=0 # Copy instead of symlinking files. Default: false. | |
do_continue=0 # Continue on error instead of exit | |
do_help=0 # Display the help message. Default: false. | |
do_silent=0 # Suppress all output to stdout. Default: false. | |
do_test=0 # Testing mode, don't make changes. Default: false. | |
do_verbose=0 # Produce extra output. Default: false. | |
do_yes=0 # Assume "yes" to all queries. Default: false. | |
# | |
# Constants | |
# | |
PROGNAME=$(basename $0) | |
# | |
# Helper Functions | |
# | |
# Error printer | |
function error_echo() { | |
echo "${PROGNAME}: ${1:-"Unknown error"}" 1>&2 | |
} | |
# Error output function | |
function error_exit() { | |
error_echo "$1" | |
exit 1 | |
} | |
# Conditional echo that checks $do_verbose. | |
function verbose_echo() { | |
if (( $do_verbose )); then | |
echo $1 | |
fi | |
} | |
# Conditional echo that checks $do_silent. | |
function silent_echo() { | |
if (( ! $do_silent )); then | |
echo $1 | |
fi | |
} | |
# Back up an existing dot file. | |
# Return codes: | |
# 0 - successfully backed up file/dir | |
# 1 - received a blank argument | |
# 2 - move command failed | |
function backup() { | |
# Exit on blank argument. | |
if [ -z "$1" ]; then | |
error_echo "Empty backup target given" | |
return 1 | |
fi | |
# Announce | |
verbose_echo "Backing up ${target}/.${1}" | |
# Return successfully if file/dir does not exist. | |
if [ ! -e "${target}/.${1}" ]; then | |
silent_echo "File ${target}/.${1} does not exist, no backup created" | |
return 0 | |
fi | |
# Safely rename the file as a backup. | |
local i=0 | |
while [ -e "${target}/.${1}.backup${i}" ]; do | |
i=$[$i+1] | |
done | |
# Move the file to its backup location. | |
silent_echo "File ${target}/.${1} exists. Backing up as ${target}/.${1}.backup${i}" | |
if (( ! $do_test )); then | |
mv "${target}/.${1}" "${target}/.${1}.backup${i}" | |
if [ "$?" -ne 0 ]; then | |
return 2 | |
fi | |
else | |
silent_echo "Test mode, no action taken" | |
fi | |
return 0 | |
} | |
# Link or copy a file or directory into the target location. | |
# Return codes: | |
# 0 - successfully handled file/dir | |
# 1 - received a blank argument | |
# 2 - source file does not exist | |
# 3 - backup failed | |
# 4 - copy or link command failed | |
function install() { | |
# Exit on a blank argument. | |
if [ -z "$1" ]; then | |
error_echo "Empty install target given" | |
return 1 | |
fi | |
# Announce ourselves. | |
verbose_echo "Installing ${1}" | |
# Check if file exists in source. | |
if [ ! -e "${src}/${1}" ]; then | |
error_echo "File ${src}/${1} does not exist" | |
return 2 | |
fi | |
# Determine whether we should handle the file/dir. | |
local proceed="Yes" | |
if (( ! $do_silent )) && (( ! $do_yes )); then | |
echo "Install file ${1}?" | |
select proceed in "Yes" "No"; do | |
break; | |
done | |
fi | |
# Return successfully if we were instructed to skip the file/dir. | |
if [ "$proceed" != "Yes" ]; then | |
verbose_echo "Skipping ${1} per user request" | |
return 0 | |
fi | |
# Back up the existing version of the file/dir. | |
if (( $do_backup )); then | |
backup "$1" | |
if [ "$?" -ne 0 ]; then | |
error_echo "Backup of ${1} failed" | |
return 3 | |
fi | |
fi | |
# Copy or symlink the file/dir into the target. | |
if (( $do_copy )); then | |
silent_echo "Copying file ${src}/${1} to ${target}/.${1}" | |
if (( ! $do_test )); then | |
cp -R "${src}/${1}" "${target}/.${1}"; | |
if [ "$?" -ne 0 ]; then | |
error_echo "Copying ${1} failed" | |
return 4 | |
fi | |
else | |
silent_echo "Test mode, no action taken" | |
fi | |
else | |
silent_echo "Symlinking file ${src}/${1} to ${target}/.${1}" | |
if (( ! $do_test )); then | |
ln -sf "${src}/${1}" "${target}/.${1}"; | |
if [ "$?" -ne 0 ]; then | |
error_echo "Symlinking ${1} failed" | |
return 4 | |
fi | |
else | |
silent_echo "Test mode, no action taken" | |
fi | |
fi | |
return 0 | |
} | |
# Install a list of files. | |
function install_all() { | |
# Make sure the manifest file exists. | |
if [ ! -f ${manifest} ]; then | |
error_exit "Invalid source location. No manifest found" | |
fi | |
# Install each item in the manifest. | |
for f in `cat ${manifest}`; do | |
install "${f}" | |
if [ "$?" -ne 0 ]; then | |
local msg="Error processing ${f}" | |
if (( ! $do_continue )); then | |
error_exit "$msg" | |
else | |
error_echo "$msg" | |
fi | |
fi | |
done | |
return 0 | |
} | |
# Print help information. | |
function help() { | |
echo "Usage: ${PROGNAME} -[bchstvy] [-m <manifest>] [-r <src>] [-d <destination>]" | |
echo "A script to install dot files into /home (or elsewhere) from a common location based on a manifest file." | |
echo " -b : Skip creating backups of existing files" | |
echo " -c : Copy instead of symlinking new files" | |
echo " -e : Continue processing manifest even if errors occur" | |
echo " -h : Display this help message and exit" | |
echo " -s : Suppress all non-error output" | |
echo " -t : Test run, do not modify files or directories" | |
echo " -v : Be extra verbose, lots of output" | |
echo " -y : Automatically answer 'yes' to all queries" | |
echo " -m <manifest> : Read list of dot files from <manifest>" | |
echo " -r <src> : Directory to fetch dot files from" | |
echo " -d <destination> : Target directory for dot files" | |
} | |
# | |
# Get to it! | |
# | |
# Gather arguments and such together. | |
while getopts "bcd:ehm:r:stvy" opt; do | |
case $opt in | |
b ) do_backup=0;; | |
c ) do_copy=1;; | |
e ) do_continue=1;; | |
h ) do_help=1;; | |
s ) do_silent=1;; | |
t ) do_test=1;; | |
v ) do_verbose=1;; | |
y ) do_yes=1;; | |
# Arguments | |
d ) destination="${OPTARG}";; | |
m ) manifest="${OPTARG}";; | |
r ) src="${OPTARG}";; | |
# If we got an invalid argument, show help text. | |
* ) do_help=1;; | |
esac | |
done | |
# Print help if requested, then exit. | |
if (( $do_help )); then | |
help | |
exit 0 | |
fi | |
# Run the installation, then exit. | |
install_all | |
exit $? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment