diff options
Diffstat (limited to '.bin/oak')
-rwxr-xr-x | .bin/oak | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/.bin/oak b/.bin/oak new file mode 100755 index 0000000..4ea560e --- /dev/null +++ b/.bin/oak @@ -0,0 +1,180 @@ +#!/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 $@ |