#!/bin/bash # git-check-all.sh # ---------------- # For all Git repositories in ~/workspace, print a summary of what is NOT pushed remotely # This script counts locally modified files, stashes and un-pushed commits # Script usage usage () { printf "Usage: %b%s%b [-h] [-v]\n" "${Color_BBlue}" "${0##*/}" "${Color_Reset}" printf "\t-h display this message\n" printf "\t-v display more logs\n" printf "\t-f fetch new refs (branches, tags, etc.) from remotes\n" exit 2 } # Parse command line arguments parse_arguments () { VERBOSE="false" FETCH="false" while getopts ':hvf' arg ; do case ${arg} in v) VERBOSE="true" ;; f) FETCH="true" ;; h) usage ;; \?) error "Unknown option -${OPTARG}" usage ;; :) error "Missing argument for option -${OPTARG}" usage ;; *) error "Option -${arg} not implemented" usage ;; esac done shift $((OPTIND - 1)) readonly VERBOSE FETCH } # Get the number of stash in the repo get_nb_stash () { printf "%d" "$(git stash list | wc --lines)" } # Get the number of dirty files in the repo get_nb_files () { printf "%d" "$(git status --porcelain | wc --lines)" } # Get the branch difference with the remote, use the branch specified in the 1st argument, or the current branch if not specified get_diff_branch () { # Get diff from a different branch if specified if [[ -n ${1:-""} ]] ; then if [[ ${1} == "$(get_git_branch)" ]] ; then return fi git checkout --quiet "${1}" fi local git_status_branch git_status_branch=$(git status --porcelain --branch | grep --extended-regexp "^##") local regex="^## .+ \[(.+)\]$" [[ ${git_status_branch} =~ ${regex} ]] printf "%s" "${BASH_REMATCH[1]:-""}" # Back to the original branch if [[ -n ${1:-""} ]] ; then git checkout --quiet - fi } # Print the summary of the repo, first argument is branch diff, second is nb of modified files and third the number of stash print_repo_summary () { local OLD_IFS=${IFS} IFS="|" local summary local idx=0 local log_color=${Color_ICyan} # Write repo name printf -v summary[$((idx++))] "For repo %b%s%b[%b%s%b]%b:" "${Color_BBlue}" "${PWD##*/}" "${Color_White}" "${Color_Cyan}" "$(get_git_branch)" "${Color_White}" "${log_color}" # Write branch diff if [[ -n ${1} ]] ; then printf -v summary[$((idx++))] "\t%bcommits%b diff with origin: %b%s%b" "${Color_IGreen}" "${log_color}" "${Color_IYellow}" "${1}" "${log_color}" fi # Write master branch diff if [[ -n ${2} ]] ; then printf -v summary[$((idx++))] "\t%bcommits%b[%bmaster%b] diff with origin: %b%s%b" "${Color_IGreen}" "${log_color}" "${Color_IRed}" "${log_color}" "${Color_IYellow}" "${2}" "${log_color}" fi # Write file diff if [[ ${3} != 0 ]] ; then printf -v summary[$((idx++))] "\tmodified %bfiles%b in workspace: %b%d%b" "${Color_IGreen}" "${log_color}" "${Color_IYellow}" "${3}" "${log_color}" fi # Write stash number if [[ ${4} != 0 ]] ; then printf -v summary[$((idx++))] "\tnumber of %bstash%b: %b%s%b" "${Color_IGreen}" "${log_color}" "${Color_IYellow}" "${4}" "${log_color}" fi # Print all lines of summary for line in ${summary[*]} ; do info "${line}" done IFS=${OLD_IFS} } # Print a full status for the current Git repository check_repo () { if ! is_git_repo >/dev/null 2>&1 ; then return 0 fi if [[ ${FETCH} == "true" ]] ; then git fetch --quiet 2>/dev/null if [[ ${?} != 0 ]] ; then error "Could not fetch refs from remote of repository ${PWD##*/}" return 1 fi fi fine "Processing repository ${PWD##*/}, on branch $(get_git_branch)" local nb_stash nb_file diff_branch diff_master_branch nb_stash=$(get_nb_stash) nb_file=$(get_nb_files) diff_branch=$(get_diff_branch) diff_master_branch=$(get_diff_branch "master") if [[ -z ${diff_branch} && -z ${diff_master_branch} && ${nb_file} == 0 && ${nb_stash} == 0 ]] ; then return 0 fi print_repo_summary "${diff_branch}" "${diff_master_branch}" "${nb_file}" "${nb_stash}" return 1 } # Script entry point main () { # shellcheck source=/home/alex/Documents/scripts/common.sh source common.sh parse_arguments "${@}" for dir in $(list_repo) ; do if ! cd "${dir}" ; then error "Could not go into '${dir}'" continue fi if ! check_repo ; then printf "\n" fi done return 0 } # Call main function main "${@}"