Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 132 lines (117 sloc) 3.71 KB
#!/bin/bash
set -e -f -u -o pipefail
dotfiles_sources() {
find "${HOME}/src" -maxdepth 1 -iname '*dotfiles*' -type d
}
cat_some_files() {
local dir="$1" pattern="$2"
find "${dir}" \
-name "${pattern}" \
-a \( -not -name '*-os-*' -o -name '*-os-'"$(uname -s)"'-*' \) \
-print0 \
| sort --zero-terminated \
| xargs -0 cat
}
cat_ssh_configs() {
cat_some_files "${HOME}"/.ssh 'config-??-*'
}
cat_ssh_known_hosts() {
cat_some_files "${HOME}"/.ssh 'known_hosts-??-*'
}
main() {
local IGNORE_FILENAME=".dotfiles.ignore"
readonly IGNORE_FILENAME
local flags=() return_early=0 opt
while getopts ":dfhrX" opt "$@"; do
case "${opt}" in
d)
flags+=("--dryrun")
return_early=1
;;
f)
flags+=("--force")
;;
h)
cat <<END_OF_HELP
Usage: $0 [-d] [-f] [-r] [-X]
Links files in ${HOME}/src/*dotfiles* to ${HOME}
Files and directories listed in ${HOME}/src/*dotfiles*/${IGNORE_FILENAME} will
be ignored. Note: ${IGNORE_FILENAME} lists are global, not scoped to the
directory containing them.
Options:
-f: force overwrite of files that differ.
-d: dry run, overrides -f.
-r: report unexpected files in destination.
-X: delete unexpected files in destination.
END_OF_HELP
exit 0
;;
r)
flags+=("--report_unexpected_files" "--ignore_unexpected_children")
return_early=1
;;
X)
flags+=("--delete_unexpected_files" "--ignore_unexpected_children")
;;
*)
echo "Unrecognised flag: ${OPTARG}" >&2
exit 1
esac
done
local SKIP_FLAGS=("--ignore_pattern=tags" "--ignore_pattern=*.pyc")
SKIP_FLAGS+=("--ignore_pattern=*.spl")
readonly SKIP_FLAGS
local SKIP_FILES=() SOURCE_DIRS=() dir
for dir in $(dotfiles_sources); do
SOURCE_DIRS+=("${dir}")
if [[ -f "${dir}/${IGNORE_FILENAME}" ]]; then
SKIP_FILES+=("--ignore_file=${dir}/${IGNORE_FILENAME}")
fi
done
readonly SKIP_FILES SOURCE_DIRS
linkdirs \
"${SKIP_FLAGS[@]:+${SKIP_FLAGS[@]}}" \
"${SKIP_FILES[@]:+${SKIP_FILES[@]}}" \
"${flags[@]:+${flags[@]}}" \
"${SOURCE_DIRS[@]}" \
"${HOME}"
if [[ "${return_early}" -eq 1 ]]; then
return
fi
# Lock down some sensitive directories.
chmod -R a=-rwx,u=rwX "${HOME}"/.ssh
local dir
for dir in "${HOME}" $(dotfiles_sources); do
if [[ -d "${dir}/.ssh" ]]; then
chmod 700 "${dir}/.ssh"
fi
done
# Assemble ssh config.
cat_ssh_configs > /dev/null
cat_ssh_configs > "${HOME}/.ssh/config"
# Assemble ssh known_hosts.
local tmp_known_hosts known_hosts="${HOME}/.ssh/known_hosts"
if [[ ! -e "${known_hosts}" ]]; then
touch "${known_hosts}"
chmod 600 "${known_hosts}"
fi
tmp_known_hosts="$(mktemp -t known_hosts.XXXXXXXXXX)"
# I want ${tmp_known_hosts} to be expanded now, because when we exit
# successfully it will be out of scope and cannot be expanded.
# shellcheck disable=SC2064
trap "rm -f \"${tmp_known_hosts}\"" EXIT
cat_ssh_known_hosts > "${tmp_known_hosts}"
# shellcheck disable=SC2094
# The disabled warning is about reading from and writing to the same file in a
# single command; in this case it's fine because sort needs to read the entire
# input before sorting, so there's no race condition.
sort "${known_hosts}" "${known_hosts}" "${tmp_known_hosts}" \
| uniq -u >> "${known_hosts}"
# Update vim stuff.
# Stop TmuxSetWindowName loading: it's not useful and it doesn't work properly
# when tmux is focused on a different pane. 'set t_u7=' stops '2R' appearing
# in my shell input stream with older versions of vim.
vim --cmd 'let g:loaded_TmuxSetWindowName=1' --cmd 'set t_u7=' \
-c 'call UpdateBundleHelptags() | call UpdateSpellFiles() | :quit'
}
main "$@"