botanikanet revised this gist 1 month ago. Go to revision
1 file changed, 160 insertions, 89 deletions
update_all_git_repo.sh
| @@ -1,107 +1,178 @@ | |||
| 1 | 1 | #!/bin/bash | |
| 2 | + | set -euo pipefail | |
| 2 | 3 | ||
| 4 | + | # ── Colors ─────────────────────────────────────────────────────────── | |
| 5 | + | RED='\033[0;31m' | |
| 6 | + | GREEN='\033[0;32m' | |
| 7 | + | YELLOW='\033[1;33m' | |
| 8 | + | CYAN='\033[0;36m' | |
| 9 | + | NC='\033[0m' # No Color | |
| 10 | + | ||
| 11 | + | # ── Logging helpers ────────────────────────────────────────────────── | |
| 12 | + | log_info() { printf "${CYAN}[INFO]${NC} %s\n" "$*"; } | |
| 13 | + | log_warn() { printf "${YELLOW}[WARN]${NC} %s\n" "$*"; } | |
| 14 | + | log_ok() { printf "${GREEN}[ OK ]${NC} %s\n" "$*"; } | |
| 15 | + | log_error() { printf "${RED}[ERR]${NC} %s\n" "$*" >&2; } | |
| 16 | + | ||
| 17 | + | # ── Usage ──────────────────────────────────────────────────────────── | |
| 3 | 18 | usage() { | |
| 4 | - | echo "Usage ${0} [[--ignore|-i] dir_name] [--main]" | |
| 5 | - | echo " --help Show this help" | |
| 6 | - | echo " --main Checkout to main branch" | |
| 7 | - | echo " --ignore=* Ignore folders" | |
| 8 | - | echo " --only=* Update only folders (comma-separated)" | |
| 9 | - | exit 1 | |
| 10 | - | } | |
| 19 | + | cat <<EOF | |
| 20 | + | Usage: ${0##*/} [OPTIONS] | |
| 11 | 21 | ||
| 12 | - | find_folders() { | |
| 13 | - | local FIND_ARGS=(.) | |
| 14 | - | FIND_ARGS+=("-name" ".git") | |
| 15 | - | FIND_ARGS+=("-type" "d") | |
| 16 | - | ||
| 17 | - | # If only specific folders are requested | |
| 18 | - | local ONLY_PATHS=() | |
| 19 | - | for ONLY_FOLDER in ${ONLY_FOLDERS} | |
| 20 | - | do | |
| 21 | - | ONLY_PATHS+=("-o" "-path" "*/${ONLY_FOLDER}/*") | |
| 22 | - | # Remove first -o and add parentheses | |
| 23 | - | done | |
| 24 | - | if [[ ${#ONLY_PATHS[@]} -gt 1 ]] | |
| 25 | - | then | |
| 26 | - | unset 'ONLY_PATHS[0]' | |
| 27 | - | FIND_ARGS+=("(" "${ONLY_PATHS[@]}" ")") | |
| 28 | - | fi | |
| 29 | - | ||
| 30 | - | # Exclude ignored folders | |
| 31 | - | for IGNORE_FOLDER in ${IGNORE_FOLDERS} | |
| 32 | - | do | |
| 33 | - | FIND_ARGS+=("-not" "-path" "*/${IGNORE_FOLDER}/*") | |
| 34 | - | done | |
| 35 | - | find "${FIND_ARGS[@]}" | |
| 22 | + | Update all git repositories found under the current directory. | |
| 23 | + | ||
| 24 | + | Options: | |
| 25 | + | -h, --help Show this help | |
| 26 | + | -m, --main Checkout to main/master branch after update | |
| 27 | + | -i, --ignore=DIR Ignore folder(s) (repeatable, comma-separated) | |
| 28 | + | -o, --only=DIR Update only these folder(s) (repeatable, comma-separated) | |
| 29 | + | ||
| 30 | + | Examples: | |
| 31 | + | ${0##*/} --ignore=vendor,node_modules | |
| 32 | + | ${0##*/} --only=project-a,project-b --main | |
| 33 | + | EOF | |
| 34 | + | exit 1 | |
| 36 | 35 | } | |
| 37 | 36 | ||
| 38 | - | # Map long options to short ones and rebuild argv | |
| 37 | + | # ── Parse arguments ────────────────────────────────────────────────── | |
| 38 | + | IGNORE_FOLDERS=() | |
| 39 | + | ONLY_FOLDERS=() | |
| 40 | + | FLAG_SWITCH_TO_MAIN="" | |
| 41 | + | ||
| 42 | + | # Map long options to short ones | |
| 39 | 43 | translated=() | |
| 40 | 44 | while (( $# )); do | |
| 41 | - | case "$1" in | |
| 42 | - | --help) translated+=("-h"); shift ;; | |
| 43 | - | --main) translated+=("-m"); shift ;; | |
| 44 | - | --ignore=*) translated+=("-i" "${1#*=}"); shift ;; | |
| 45 | - | --only=*) translated+=("-o" "${1#*=}"); shift ;; | |
| 46 | - | --) translated+=("--"); shift; translated+=("$@"); set -- ;; | |
| 47 | - | *) translated+=("$1"); shift ;; | |
| 48 | - | esac | |
| 45 | + | case "$1" in | |
| 46 | + | --help) translated+=("-h"); shift ;; | |
| 47 | + | --main) translated+=("-m"); shift ;; | |
| 48 | + | --ignore=*) translated+=("-i" "${1#*=}"); shift ;; | |
| 49 | + | --only=*) translated+=("-o" "${1#*=}"); shift ;; | |
| 50 | + | --) translated+=("--"); shift; translated+=("$@"); break ;; | |
| 51 | + | *) translated+=("$1"); shift ;; | |
| 52 | + | esac | |
| 49 | 53 | done | |
| 50 | 54 | set -- "${translated[@]}" | |
| 51 | 55 | ||
| 52 | - | IGNORE_FOLDERS="" | |
| 53 | - | ONLY_FOLDERS="" | |
| 54 | - | FLAG_SWITCH_TO_MAIN="" | |
| 55 | - | ||
| 56 | 56 | while getopts ":hmi:o:" opt; do | |
| 57 | - | case "$opt" in | |
| 58 | - | h) usage;; | |
| 59 | - | m) FLAG_SWITCH_TO_MAIN=1;; | |
| 60 | - | i) IGNORE_FOLDERS="${IGNORE_FOLDERS} ${OPTARG}";; | |
| 61 | - | o) ONLY_FOLDERS="${ONLY_FOLDERS} ${OPTARG}";; | |
| 62 | - | :) echo "Missing arg for -$OPTARG"; usage;; | |
| 63 | - | \?) echo "Invalid option: -$OPTARG"; usage;; | |
| 64 | - | esac | |
| 57 | + | case "$opt" in | |
| 58 | + | h) usage ;; | |
| 59 | + | m) FLAG_SWITCH_TO_MAIN=1 ;; | |
| 60 | + | i) | |
| 61 | + | # Support comma-separated values | |
| 62 | + | IFS=',' read -ra parts <<< "$OPTARG" | |
| 63 | + | IGNORE_FOLDERS+=("${parts[@]}") | |
| 64 | + | ;; | |
| 65 | + | o) | |
| 66 | + | IFS=',' read -ra parts <<< "$OPTARG" | |
| 67 | + | ONLY_FOLDERS+=("${parts[@]}") | |
| 68 | + | ;; | |
| 69 | + | :) log_error "Missing argument for -${OPTARG}"; usage ;; | |
| 70 | + | \?) log_error "Invalid option: -${OPTARG}"; usage ;; | |
| 71 | + | esac | |
| 65 | 72 | done | |
| 73 | + | shift $((OPTIND - 1)) | |
| 66 | 74 | ||
| 67 | - | if [ ${#IGNORE_FOLDERS[@]} -gt 0 ]; then | |
| 68 | - | echo "[DEBUG] Ignoring folders to update: ${IGNORE_FOLDERS[*]}" | |
| 75 | + | # ── Debug: show filters ───────────────────────────────────────────── | |
| 76 | + | if (( ${#IGNORE_FOLDERS[@]} > 0 )); then | |
| 77 | + | log_info "Ignoring folders: ${IGNORE_FOLDERS[*]}" | |
| 69 | 78 | fi | |
| 70 | - | if [ ${#ONLY_FOLDERS[@]} -gt 0 ]; then | |
| 71 | - | echo "[DEBUG] Only folders to update: ${ONLY_FOLDERS[*]}" | |
| 79 | + | if (( ${#ONLY_FOLDERS[@]} > 0 )); then | |
| 80 | + | log_info "Only updating folders: ${ONLY_FOLDERS[*]}" | |
| 72 | 81 | fi | |
| 73 | 82 | ||
| 74 | - | for DIR in $(find_folders) | |
| 75 | - | do | |
| 76 | - | pushd ${PWD} > /dev/null | |
| 77 | - | echo "[DEBUG] Work with $(dirname ${DIR})" | |
| 78 | - | cd $(dirname ${DIR}) | |
| 79 | - | if [[ -n $(git status --porcelain) ]] | |
| 80 | - | then | |
| 81 | - | echo "[WARN] There are uncommitted changes." | |
| 82 | - | declare UNCOMMIT_CHANGES=1 | |
| 83 | - | git stash | |
| 84 | - | fi | |
| 85 | - | declare MASTER_BRANCH="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')" | |
| 86 | - | declare CURRENT_BRANCH="$(git branch --show-current)" | |
| 87 | - | if [[ "$MASTER_BRANCH" == "$CURRENT_BRANCH" ]] | |
| 88 | - | then | |
| 89 | - | git pull --all | |
| 90 | - | git remote prune origin | |
| 91 | - | else | |
| 92 | - | git checkout ${MASTER_BRANCH} | |
| 93 | - | git pull --all | |
| 94 | - | git remote prune origin | |
| 95 | - | if [[ -z "${FLAG_SWITCH_TO_MAIN}" ]] | |
| 96 | - | then | |
| 97 | - | git checkout ${CURRENT_BRANCH} || echo "[WARN] current brach has been deleted" | |
| 98 | - | fi | |
| 99 | - | fi | |
| 100 | - | git branch --merged | grep -v "^*\|${MASTER_BRANCH}" | xargs -r git branch -D | |
| 101 | - | if [ ! -z "$UNCOMMIT_CHANGES" ] | |
| 102 | - | then | |
| 103 | - | git stash pop | |
| 83 | + | # ── Find git repositories ─────────────────────────────────────────── | |
| 84 | + | find_repos() { | |
| 85 | + | local find_args=(. -name ".git" -type d) | |
| 86 | + | ||
| 87 | + | # Whitelist: only matching paths | |
| 88 | + | if (( ${#ONLY_FOLDERS[@]} > 0 )); then | |
| 89 | + | local only_paths=() | |
| 90 | + | for folder in "${ONLY_FOLDERS[@]}"; do | |
| 91 | + | only_paths+=("-o" "-path" "*/${folder}/*") | |
| 92 | + | done | |
| 93 | + | # Remove the leading -o and wrap in parentheses | |
| 94 | + | unset 'only_paths[0]' | |
| 95 | + | find_args+=("(" "${only_paths[@]}" ")") | |
| 96 | + | fi | |
| 97 | + | ||
| 98 | + | # Blacklist: excluded paths | |
| 99 | + | for folder in "${IGNORE_FOLDERS[@]}"; do | |
| 100 | + | find_args+=("-not" "-path" "*/${folder}/*") | |
| 101 | + | done | |
| 102 | + | ||
| 103 | + | find "${find_args[@]}" | |
| 104 | + | } | |
| 105 | + | ||
| 106 | + | # ── Update a single repository ─────────────────────────────────────── | |
| 107 | + | update_repo() { | |
| 108 | + | local repo_dir="$1" | |
| 109 | + | local had_stash=0 | |
| 110 | + | ||
| 111 | + | # Stash uncommitted changes if any | |
| 112 | + | if [[ -n "$(git -C "$repo_dir" status --porcelain)" ]]; then | |
| 113 | + | log_warn "Uncommitted changes in ${repo_dir} — stashing" | |
| 114 | + | git -C "$repo_dir" stash --quiet | |
| 115 | + | had_stash=1 | |
| 116 | + | fi | |
| 117 | + | ||
| 118 | + | # Determine main and current branches | |
| 119 | + | local master_branch current_branch | |
| 120 | + | master_branch="$(git -C "$repo_dir" symbolic-ref refs/remotes/origin/HEAD 2>/dev/null \ | |
| 121 | + | | sed 's@^refs/remotes/origin/@@')" || true | |
| 122 | + | current_branch="$(git -C "$repo_dir" branch --show-current)" | |
| 123 | + | ||
| 124 | + | if [[ -z "$master_branch" ]]; then | |
| 125 | + | log_warn "Cannot determine default branch for ${repo_dir} — skipping" | |
| 126 | + | return | |
| 127 | + | fi | |
| 128 | + | ||
| 129 | + | if [[ "$master_branch" == "$current_branch" ]]; then | |
| 130 | + | git -C "$repo_dir" pull --all --quiet | |
| 131 | + | else | |
| 132 | + | git -C "$repo_dir" checkout "$master_branch" --quiet | |
| 133 | + | git -C "$repo_dir" pull --all --quiet | |
| 134 | + | if [[ -z "$FLAG_SWITCH_TO_MAIN" ]]; then | |
| 135 | + | git -C "$repo_dir" checkout "$current_branch" --quiet 2>/dev/null \ | |
| 136 | + | || log_warn "Branch '${current_branch}' was deleted on remote" | |
| 104 | 137 | fi | |
| 105 | - | unset UNCOMMIT_CHANGES MASTER_BRANCH CURRENT_BRANCH | |
| 106 | - | popd > /dev/null | |
| 107 | - | done | |
| 138 | + | fi | |
| 139 | + | ||
| 140 | + | # Prune stale remote-tracking branches | |
| 141 | + | git -C "$repo_dir" remote prune origin --quiet 2>/dev/null || true | |
| 142 | + | ||
| 143 | + | # Delete local branches that have been merged into the default branch | |
| 144 | + | local merged | |
| 145 | + | merged="$(git -C "$repo_dir" branch --merged \ | |
| 146 | + | | grep -v -E "^\*|${master_branch}" || true)" | |
| 147 | + | if [[ -n "$merged" ]]; then | |
| 148 | + | echo "$merged" | xargs git -C "$repo_dir" branch -D --quiet 2>/dev/null || true | |
| 149 | + | fi | |
| 150 | + | ||
| 151 | + | # Restore stashed changes | |
| 152 | + | if (( had_stash )); then | |
| 153 | + | git -C "$repo_dir" stash pop --quiet || log_warn "Stash pop failed in ${repo_dir}" | |
| 154 | + | fi | |
| 155 | + | ||
| 156 | + | log_ok "$repo_dir" | |
| 157 | + | } | |
| 158 | + | ||
| 159 | + | # ── Main ───────────────────────────────────────────────────────────── | |
| 160 | + | main() { | |
| 161 | + | local count=0 | |
| 162 | + | ||
| 163 | + | while IFS= read -r git_dir; do | |
| 164 | + | local repo_dir | |
| 165 | + | repo_dir="$(dirname "$git_dir")" | |
| 166 | + | log_info "Updating ${repo_dir} …" | |
| 167 | + | update_repo "$repo_dir" | |
| 168 | + | (( count++ )) || true | |
| 169 | + | done < <(find_repos) | |
| 170 | + | ||
| 171 | + | if (( count == 0 )); then | |
| 172 | + | log_warn "No git repositories found" | |
| 173 | + | else | |
| 174 | + | log_ok "Done — updated ${count} repo(s)" | |
| 175 | + | fi | |
| 176 | + | } | |
| 177 | + | ||
| 178 | + | main | |
botanikanet revised this gist 2 months ago. Go to revision
1 file changed, 28 insertions, 2 deletions
update_all_git_repo.sh
| @@ -5,13 +5,29 @@ usage() { | |||
| 5 | 5 | echo " --help Show this help" | |
| 6 | 6 | echo " --main Checkout to main branch" | |
| 7 | 7 | echo " --ignore=* Ignore folders" | |
| 8 | + | echo " --only=* Update only folders (comma-separated)" | |
| 8 | 9 | exit 1 | |
| 9 | 10 | } | |
| 10 | 11 | ||
| 11 | 12 | find_folders() { | |
| 12 | - | FIND_ARGS=(.) | |
| 13 | + | local FIND_ARGS=(.) | |
| 13 | 14 | FIND_ARGS+=("-name" ".git") | |
| 14 | 15 | FIND_ARGS+=("-type" "d") | |
| 16 | + | ||
| 17 | + | # If only specific folders are requested | |
| 18 | + | local ONLY_PATHS=() | |
| 19 | + | for ONLY_FOLDER in ${ONLY_FOLDERS} | |
| 20 | + | do | |
| 21 | + | ONLY_PATHS+=("-o" "-path" "*/${ONLY_FOLDER}/*") | |
| 22 | + | # Remove first -o and add parentheses | |
| 23 | + | done | |
| 24 | + | if [[ ${#ONLY_PATHS[@]} -gt 1 ]] | |
| 25 | + | then | |
| 26 | + | unset 'ONLY_PATHS[0]' | |
| 27 | + | FIND_ARGS+=("(" "${ONLY_PATHS[@]}" ")") | |
| 28 | + | fi | |
| 29 | + | ||
| 30 | + | # Exclude ignored folders | |
| 15 | 31 | for IGNORE_FOLDER in ${IGNORE_FOLDERS} | |
| 16 | 32 | do | |
| 17 | 33 | FIND_ARGS+=("-not" "-path" "*/${IGNORE_FOLDER}/*") | |
| @@ -26,6 +42,7 @@ while (( $# )); do | |||
| 26 | 42 | --help) translated+=("-h"); shift ;; | |
| 27 | 43 | --main) translated+=("-m"); shift ;; | |
| 28 | 44 | --ignore=*) translated+=("-i" "${1#*=}"); shift ;; | |
| 45 | + | --only=*) translated+=("-o" "${1#*=}"); shift ;; | |
| 29 | 46 | --) translated+=("--"); shift; translated+=("$@"); set -- ;; | |
| 30 | 47 | *) translated+=("$1"); shift ;; | |
| 31 | 48 | esac | |
| @@ -33,18 +50,27 @@ done | |||
| 33 | 50 | set -- "${translated[@]}" | |
| 34 | 51 | ||
| 35 | 52 | IGNORE_FOLDERS="" | |
| 53 | + | ONLY_FOLDERS="" | |
| 36 | 54 | FLAG_SWITCH_TO_MAIN="" | |
| 37 | 55 | ||
| 38 | - | while getopts ":hmi:" opt; do | |
| 56 | + | while getopts ":hmi:o:" opt; do | |
| 39 | 57 | case "$opt" in | |
| 40 | 58 | h) usage;; | |
| 41 | 59 | m) FLAG_SWITCH_TO_MAIN=1;; | |
| 42 | 60 | i) IGNORE_FOLDERS="${IGNORE_FOLDERS} ${OPTARG}";; | |
| 61 | + | o) ONLY_FOLDERS="${ONLY_FOLDERS} ${OPTARG}";; | |
| 43 | 62 | :) echo "Missing arg for -$OPTARG"; usage;; | |
| 44 | 63 | \?) echo "Invalid option: -$OPTARG"; usage;; | |
| 45 | 64 | esac | |
| 46 | 65 | done | |
| 47 | 66 | ||
| 67 | + | if [ ${#IGNORE_FOLDERS[@]} -gt 0 ]; then | |
| 68 | + | echo "[DEBUG] Ignoring folders to update: ${IGNORE_FOLDERS[*]}" | |
| 69 | + | fi | |
| 70 | + | if [ ${#ONLY_FOLDERS[@]} -gt 0 ]; then | |
| 71 | + | echo "[DEBUG] Only folders to update: ${ONLY_FOLDERS[*]}" | |
| 72 | + | fi | |
| 73 | + | ||
| 48 | 74 | for DIR in $(find_folders) | |
| 49 | 75 | do | |
| 50 | 76 | pushd ${PWD} > /dev/null | |
botanikanet revised this gist 6 months ago. Go to revision
1 file changed, 18 insertions, 16 deletions
update_all_git_repo.sh
| @@ -1,20 +1,22 @@ | |||
| 1 | 1 | #!/bin/bash | |
| 2 | 2 | ||
| 3 | 3 | usage() { | |
| 4 | - | echo "Usage ${0} [[--ignore|-i] dir_name] [--main]" | |
| 4 | + | echo "Usage ${0} [[--ignore|-i] dir_name] [--main]" | |
| 5 | 5 | echo " --help Show this help" | |
| 6 | 6 | echo " --main Checkout to main branch" | |
| 7 | 7 | echo " --ignore=* Ignore folders" | |
| 8 | - | exit 1 | |
| 8 | + | exit 1 | |
| 9 | 9 | } | |
| 10 | 10 | ||
| 11 | 11 | find_folders() { | |
| 12 | - | set -- ./ -name ".git" -type d | |
| 13 | - | for IGNORE_FOLDER in ${IGNORE_FOLDERS} | |
| 14 | - | do | |
| 15 | - | set -- "$@" -not -path '"*/'${IGNORE_FOLDER}'/*"' | |
| 16 | - | done | |
| 17 | - | find $@ | |
| 12 | + | FIND_ARGS=(.) | |
| 13 | + | FIND_ARGS+=("-name" ".git") | |
| 14 | + | FIND_ARGS+=("-type" "d") | |
| 15 | + | for IGNORE_FOLDER in ${IGNORE_FOLDERS} | |
| 16 | + | do | |
| 17 | + | FIND_ARGS+=("-not" "-path" "*/${IGNORE_FOLDER}/*") | |
| 18 | + | done | |
| 19 | + | find "${FIND_ARGS[@]}" | |
| 18 | 20 | } | |
| 19 | 21 | ||
| 20 | 22 | # Map long options to short ones and rebuild argv | |
| @@ -59,21 +61,21 @@ do | |||
| 59 | 61 | if [[ "$MASTER_BRANCH" == "$CURRENT_BRANCH" ]] | |
| 60 | 62 | then | |
| 61 | 63 | git pull --all | |
| 62 | - | git remote prune origin | |
| 64 | + | git remote prune origin | |
| 63 | 65 | else | |
| 64 | 66 | git checkout ${MASTER_BRANCH} | |
| 65 | 67 | git pull --all | |
| 66 | - | git remote prune origin | |
| 67 | - | if [[ -z "${FLAG_SWITCH_TO_MAIN}" ]] | |
| 68 | - | then | |
| 69 | - | git checkout ${CURRENT_BRANCH} || echo "[WARN] current brach has been deleted" | |
| 70 | - | fi | |
| 68 | + | git remote prune origin | |
| 69 | + | if [[ -z "${FLAG_SWITCH_TO_MAIN}" ]] | |
| 70 | + | then | |
| 71 | + | git checkout ${CURRENT_BRANCH} || echo "[WARN] current brach has been deleted" | |
| 72 | + | fi | |
| 71 | 73 | fi | |
| 72 | - | git branch --merged | grep -v "^*\|${MASTER_BRANCH}" | xargs -r git branch -D | |
| 74 | + | git branch --merged | grep -v "^*\|${MASTER_BRANCH}" | xargs -r git branch -D | |
| 73 | 75 | if [ ! -z "$UNCOMMIT_CHANGES" ] | |
| 74 | 76 | then | |
| 75 | 77 | git stash pop | |
| 76 | 78 | fi | |
| 77 | 79 | unset UNCOMMIT_CHANGES MASTER_BRANCH CURRENT_BRANCH | |
| 78 | 80 | popd > /dev/null | |
| 79 | - | done | |
| 81 | + | done | |
botanikanet revised this gist 8 months ago. Go to revision
1 file changed, 79 insertions
update_all_git_repo.sh(file created)
| @@ -0,0 +1,79 @@ | |||
| 1 | + | #!/bin/bash | |
| 2 | + | ||
| 3 | + | usage() { | |
| 4 | + | echo "Usage ${0} [[--ignore|-i] dir_name] [--main]" | |
| 5 | + | echo " --help Show this help" | |
| 6 | + | echo " --main Checkout to main branch" | |
| 7 | + | echo " --ignore=* Ignore folders" | |
| 8 | + | exit 1 | |
| 9 | + | } | |
| 10 | + | ||
| 11 | + | find_folders() { | |
| 12 | + | set -- ./ -name ".git" -type d | |
| 13 | + | for IGNORE_FOLDER in ${IGNORE_FOLDERS} | |
| 14 | + | do | |
| 15 | + | set -- "$@" -not -path '"*/'${IGNORE_FOLDER}'/*"' | |
| 16 | + | done | |
| 17 | + | find $@ | |
| 18 | + | } | |
| 19 | + | ||
| 20 | + | # Map long options to short ones and rebuild argv | |
| 21 | + | translated=() | |
| 22 | + | while (( $# )); do | |
| 23 | + | case "$1" in | |
| 24 | + | --help) translated+=("-h"); shift ;; | |
| 25 | + | --main) translated+=("-m"); shift ;; | |
| 26 | + | --ignore=*) translated+=("-i" "${1#*=}"); shift ;; | |
| 27 | + | --) translated+=("--"); shift; translated+=("$@"); set -- ;; | |
| 28 | + | *) translated+=("$1"); shift ;; | |
| 29 | + | esac | |
| 30 | + | done | |
| 31 | + | set -- "${translated[@]}" | |
| 32 | + | ||
| 33 | + | IGNORE_FOLDERS="" | |
| 34 | + | FLAG_SWITCH_TO_MAIN="" | |
| 35 | + | ||
| 36 | + | while getopts ":hmi:" opt; do | |
| 37 | + | case "$opt" in | |
| 38 | + | h) usage;; | |
| 39 | + | m) FLAG_SWITCH_TO_MAIN=1;; | |
| 40 | + | i) IGNORE_FOLDERS="${IGNORE_FOLDERS} ${OPTARG}";; | |
| 41 | + | :) echo "Missing arg for -$OPTARG"; usage;; | |
| 42 | + | \?) echo "Invalid option: -$OPTARG"; usage;; | |
| 43 | + | esac | |
| 44 | + | done | |
| 45 | + | ||
| 46 | + | for DIR in $(find_folders) | |
| 47 | + | do | |
| 48 | + | pushd ${PWD} > /dev/null | |
| 49 | + | echo "[DEBUG] Work with $(dirname ${DIR})" | |
| 50 | + | cd $(dirname ${DIR}) | |
| 51 | + | if [[ -n $(git status --porcelain) ]] | |
| 52 | + | then | |
| 53 | + | echo "[WARN] There are uncommitted changes." | |
| 54 | + | declare UNCOMMIT_CHANGES=1 | |
| 55 | + | git stash | |
| 56 | + | fi | |
| 57 | + | declare MASTER_BRANCH="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')" | |
| 58 | + | declare CURRENT_BRANCH="$(git branch --show-current)" | |
| 59 | + | if [[ "$MASTER_BRANCH" == "$CURRENT_BRANCH" ]] | |
| 60 | + | then | |
| 61 | + | git pull --all | |
| 62 | + | git remote prune origin | |
| 63 | + | else | |
| 64 | + | git checkout ${MASTER_BRANCH} | |
| 65 | + | git pull --all | |
| 66 | + | git remote prune origin | |
| 67 | + | if [[ -z "${FLAG_SWITCH_TO_MAIN}" ]] | |
| 68 | + | then | |
| 69 | + | git checkout ${CURRENT_BRANCH} || echo "[WARN] current brach has been deleted" | |
| 70 | + | fi | |
| 71 | + | fi | |
| 72 | + | git branch --merged | grep -v "^*\|${MASTER_BRANCH}" | xargs -r git branch -D | |
| 73 | + | if [ ! -z "$UNCOMMIT_CHANGES" ] | |
| 74 | + | then | |
| 75 | + | git stash pop | |
| 76 | + | fi | |
| 77 | + | unset UNCOMMIT_CHANGES MASTER_BRANCH CURRENT_BRANCH | |
| 78 | + | popd > /dev/null | |
| 79 | + | done | |