#!/bin/bash usage() { echo "Usage ${0} [[--ignore|-i] dir_name] [--main]" echo " --help Show this help" echo " --main Checkout to main branch" echo " --ignore=* Ignore folders" echo " --only=* Update only folders (comma-separated)" exit 1 } find_folders() { local FIND_ARGS=(.) FIND_ARGS+=("-name" ".git") FIND_ARGS+=("-type" "d") # If only specific folders are requested local ONLY_PATHS=() for ONLY_FOLDER in ${ONLY_FOLDERS} do ONLY_PATHS+=("-o" "-path" "*/${ONLY_FOLDER}/*") # Remove first -o and add parentheses done if [[ ${#ONLY_PATHS[@]} -gt 1 ]] then unset 'ONLY_PATHS[0]' FIND_ARGS+=("(" "${ONLY_PATHS[@]}" ")") fi # Exclude ignored folders for IGNORE_FOLDER in ${IGNORE_FOLDERS} do FIND_ARGS+=("-not" "-path" "*/${IGNORE_FOLDER}/*") done find "${FIND_ARGS[@]}" } # Map long options to short ones and rebuild argv translated=() while (( $# )); do case "$1" in --help) translated+=("-h"); shift ;; --main) translated+=("-m"); shift ;; --ignore=*) translated+=("-i" "${1#*=}"); shift ;; --only=*) translated+=("-o" "${1#*=}"); shift ;; --) translated+=("--"); shift; translated+=("$@"); set -- ;; *) translated+=("$1"); shift ;; esac done set -- "${translated[@]}" IGNORE_FOLDERS="" ONLY_FOLDERS="" FLAG_SWITCH_TO_MAIN="" while getopts ":hmi:o:" opt; do case "$opt" in h) usage;; m) FLAG_SWITCH_TO_MAIN=1;; i) IGNORE_FOLDERS="${IGNORE_FOLDERS} ${OPTARG}";; o) ONLY_FOLDERS="${ONLY_FOLDERS} ${OPTARG}";; :) echo "Missing arg for -$OPTARG"; usage;; \?) echo "Invalid option: -$OPTARG"; usage;; esac done if [ ${#IGNORE_FOLDERS[@]} -gt 0 ]; then echo "[DEBUG] Ignoring folders to update: ${IGNORE_FOLDERS[*]}" fi if [ ${#ONLY_FOLDERS[@]} -gt 0 ]; then echo "[DEBUG] Only folders to update: ${ONLY_FOLDERS[*]}" fi for DIR in $(find_folders) do pushd ${PWD} > /dev/null echo "[DEBUG] Work with $(dirname ${DIR})" cd $(dirname ${DIR}) if [[ -n $(git status --porcelain) ]] then echo "[WARN] There are uncommitted changes." declare UNCOMMIT_CHANGES=1 git stash fi declare MASTER_BRANCH="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')" declare CURRENT_BRANCH="$(git branch --show-current)" if [[ "$MASTER_BRANCH" == "$CURRENT_BRANCH" ]] then git pull --all git remote prune origin else git checkout ${MASTER_BRANCH} git pull --all git remote prune origin if [[ -z "${FLAG_SWITCH_TO_MAIN}" ]] then git checkout ${CURRENT_BRANCH} || echo "[WARN] current brach has been deleted" fi fi git branch --merged | grep -v "^*\|${MASTER_BRANCH}" | xargs -r git branch -D if [ ! -z "$UNCOMMIT_CHANGES" ] then git stash pop fi unset UNCOMMIT_CHANGES MASTER_BRANCH CURRENT_BRANCH popd > /dev/null done