update_all_git_repo.sh
· 3.2 KiB · Bash
Raw
#!/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
| 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 | echo " --only=* Update only folders (comma-separated)" |
| 9 | exit 1 |
| 10 | } |
| 11 | |
| 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[@]}" |
| 36 | } |
| 37 | |
| 38 | # Map long options to short ones and rebuild argv |
| 39 | translated=() |
| 40 | 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 |
| 49 | done |
| 50 | set -- "${translated[@]}" |
| 51 | |
| 52 | IGNORE_FOLDERS="" |
| 53 | ONLY_FOLDERS="" |
| 54 | FLAG_SWITCH_TO_MAIN="" |
| 55 | |
| 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 |
| 65 | done |
| 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 | |
| 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 |
| 104 | fi |
| 105 | unset UNCOMMIT_CHANGES MASTER_BRANCH CURRENT_BRANCH |
| 106 | popd > /dev/null |
| 107 | done |