summaryrefslogtreecommitdiffstats
path: root/.bin/oak
diff options
context:
space:
mode:
Diffstat (limited to '.bin/oak')
-rwxr-xr-x.bin/oak180
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 $@
remember that computers suck.