blob: 4ea560ef8b99ec94b3f7ff83021584430318d777 (
plain) (
tree)
|
|
#!/bin/sh
# _
# | |
# __ __, | |
# / \_/ | |/_)
# \__/ \_/|_/| \_/
#
# ~/.bin/oak
#
# manage multiple dotfiles repo in same work tree
#
# Example:
# dotfiles.d/
# |_ config
# |_ secret
#
# ~ rgoncalves.se
usage() {
cat <<- EOF
USAGE ${0} : git_dirname git_action [arguments...]
-b: enable bootstraping for absent repository
-d: oak directory to work on
works in batch mode if no directory is provided
-f: force all operations
use with caution
-m: commit message when using -s option
commits_msg_have_to_be_written_like_this
-r: git remote with full path to parent directory
-h: show usage of ${0}
EOF
}
log() {
echo "[OAK ] ${@}"
}
git_chroot() {
log ">> ${1}"
git --git-dir="${OAK_ROOT}/${1}" --work-tree="${HOME}" ${2}
}
git_bootstrap() {
# directory url remote
git_chroot "${1}" "clone --bare git@${2}/${1} ${OAK_ROOT}/${1}"
[ "${?}" -ne 0 ] && log "Failed to bootstrap ${1}" && exit 1
git_chroot "${1}" "checkout trunk" >/dev/null 2>&1
git_chroot "${1}" "branch --set-upstream-to trunk origin/trunk" >/dev/null 2>&1
git_chroot "${1}" "push -u origin trunk" >/dev/null 2>&1
}
git_sync() {
# actions
git_sane_all
pull_out=$(git_chroot "${1}" "pull")
if [ "${?}" -ne 0 ]; then
log "error while doing git pull"
exit 1
fi
echo "${pull_out}" 2>&1 | grep " ."
git_chroot "${1}" "add -u" >/dev/null
git_chroot "${1}" "commit -m ${OAK_MSG}"
git_chroot "${1}" "push --set-upstream origin trunk"
# cleanup
unset pull_out push_out
}
git_list() {
log "Available repositories : "
for dir in ${OAK_DIRS}; do
log " - ${dir}"
done
}
git_sane() {
if [ "${1}" = "${2}" ]; then
return 1
fi
git_chroot "${1}" "ls-files" > ~/.cache/oak_a
git_chroot "${2}" "ls-files" > ~/.cache/oak_b
out=$(grep -F -x -f ~/.cache/oak_a ~/.cache/oak_b)
if [ -n "${out}" ]; then
log "detected similar files for directories: ${repo_a}, ${repo_b}"
echo "${out}"
return 1
fi
return 0
}
git_sane_all() {
for repo_a in ${DOT_DIRS}; do
for repo_b in ${DOT_DIRS}; do
if [ "${repo_a}" = "${repo_b}" ]; then
continue
fi
git_sane "${DOT_ROOT}/${repo_a}" "${DOT_ROOT}/${repo_b}"
if [ "${?}" -ne 0 ]; then
log "aborting"
exit 1
fi
done
done
}
main() {
OAK_ROOT="${HOME}/.dotfiles.d"
OAK_DIRS=$(ls "${OAK_ROOT}")
OAK_DIR=""
OAK_REMOTE=""
OAK_CMD=""
OAK_MSG=""
# Retrieve oak params
while getopts "bd:hlm:r:s" arg; do
case "${arg}" in
b)
OAK_BOOTSTRAP=1
;;
d)
OAK_DIR="${OPTARG}"
;;
f)
OAK_FORCE=1
;;
h)
usage && exit 0
;;
m)
OAK_MSG="$(echo ${OPTARG} | tr -s '_' ' ')"
;;
l)
git_list
exit 0
;;
r)
OAK_REMOTE="${OPTARG}"
;;
s)
OAK_SYNC=1
;;
esac
done
[ -z "${OAK_MSG}" ] && OAK_MSG=$(date +%j_%H_%M_%S)
# Bootstrap non-present repositories
if [ -n "${OAK_DIR}" ] && [ ! -d "${OAK_ROOT}/${OAK_DIR}" ]; then
git_bootstrap "${OAK_DIR}" "${OAK_REMOTE}"
if [ "${?}" -ne 0 ]; then
log "Git repository does not exist. Error"
exit 1
fi
log "Successfully bootstraped git repository"
fi
# Retrieve oak command for git
shift $(expr "${OPTIND}" - 1)
for cmd in "${@}"; do
OAK_CMD="${OAK_CMD}${cmd} "
done
# Git synchronization in each repository
if [ -n "${OAK_SYNC}" ]; then
for dir in ${OAK_DIR:-$OAK_DIRS}; do
log "synchronize ${dir}"
git_sync "${dir}"
done
fi
# Raw command in each git repository
if [ -n "${OAK_CMD}" ]; then
for dir in ${OAK_DIR:-$OAK_DIRS}; do
git_chroot "${dir}" "${OAK_CMD}"
done
fi
}
main $@
|