-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgit-status-all.sh
163 lines (137 loc) · 4.29 KB
/
git-status-all.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/bin/sh
NEW_LINE=${NEW_LINE:-"
"}
IFS=$NEW_LINE
logLvl1=''
unset logLvl2 logLvl3
#unset logLvl5
#logLvl5=''
case $1 in
--help)
printf %s\\n "Usage: ${0##*/} [--log-level=0..3 (default is 1)] [PATH]"
;;
--log-level=*)
logLvl=${1#*=}
case $logLvl in
0) unset logLvl1 logLvl2 logLvl3;;
1) logLvl1=''; unset logLvl2 logLvl3;;
2) logLvl1=''; logLvl2=''; unset logLvl3;;
3) logLvl1=''; logLvl2=''; logLvl3='';;
*) printf %s\\n "invalid log leve argument"; exit 2;;
esac
shift
esac
git_getCurrentBranch() { git rev-parse --verify --abbrev-ref HEAD; }
git_isMerging() { git rev-parse --verify -q MERGE_HEAD; } # todo use this fn
git_isCherriPicking() { git rev-parse --verify -q CHERRY_PICK_HEAD; } # todo use this fn
git_getLatestCommitHash() { git log -n 1 --pretty=format:"%H" "$@"; }
git_getAllRemoteBranchWithHash() { git branch --format='%(objectname) %(refname)' -r; }
git_getAllBranchWithHash() { git branch --format='%(objectname) %(refname)' -a; }
die() {
printf %s\\n "${0##*/}: $1" >&2
exit ${2-2}
}
case $# in
0)
;;
1)
cd "$1" || exit
;;
*)
die "too many arguments, see --help"
esac
set -f
set -eu
errs=0
uncommited=''
reposDiffersFromRemote_str=''
set +f;for repoDir in ./[a-zA-Z_]*/raw/*; do # note use PWD as root path to enshure no lose relative paths in `loop { cd ./foo; }` (test if neeeded?)
set -f
${logLvl3+echo} ${logLvl3+": begin loop for '$repoDir' :"} >&2
${logLvl3+pwd} >&2
cd -- "$repoDir" || {
continue
errs=$(( errs + 1 ))
}
if ! [ -e .git ]; then # note: *.git* might not be a dir, for example when using `git worktree`
case ${logLvl1+x} in x)
printf %s\\n >&2 "NOTE: not a git repo: $repoDir" ""
esac
cd "$OLDPWD" || exit; continue
fi
case ${logLvl1+x} in x)
echo >&2 -- "$repoDir" --
esac
run_git_status=1
_uncommited=$(git status -s)
case $_uncommited in ?*)
uncommited=${uncommited}${uncommited:+$NEW_LINE}"${repoDir}:${NEW_LINE}$(echo "${_uncommited}" | sed 's/^/ /' )${NEW_LINE}"
run_git_status=0
esac
branch=$(git_getCurrentBranch)
localHash=$(git_getLatestCommitHash) # same as: git_getLatestCommitHash "$_branch"
localFiles_noChange=0
localFiles_differ=0
localFiles_differ_str=''
#for _remoteBranch in $( git branch -r | sed 's/^ *//; s/ *$//' | grep -v '/HEAD$' ); do
for remote_hb in $( git_getAllRemoteBranchWithHash | grep -v '/HEAD$' ); do
remoteBranch=${remote_hb#*" "}
remoteHash=${remote_hb%"$remoteBranch"}
case ${logLvl3+x} in x)
printf %s\\ >&2 \
"remoteBranch=$remoteBranch" \
"remoteHash=$remoteHash" \
;
esac
case $remoteBranch in */"$branch") ;; *)
case ${logLvl2+x} in x)
printf %s\\n >&2 "note: not remoteBranch='$remoteBranch' is for this local branch localFiles_branch='$branch' --> '$remoteBranch' is not in */'$branch'"
esac
####case ${logLvl5+x} in x)
#### printf %s\\n >&2 " @1@ PWD='$PWD' OLDPWD='$OLDPWD'"
####esac
####cd "$OLDPWD" || exit; pwd;
continue
esac
case $remoteHash in
'') printf %s\\n >&2 "warning: can not git_getLatestCommitHash for branch '$remoteBranch' for: '$repoDir'";; # warning is not a log, do not add `${logLvl?:+`
"$localHash") localFiles_noChange=$(( localFiles_noChange + 1 ));;
*) localFiles_differ=$(( localFiles_differ + 1 )); run_git_status=0; localFiles_differ_str="'$localFiles_differ_str' '$remoteBranch'";;
esac
done
case ${localFiles_differ}:${localFiles_noChange} in
0:0)
printf %s\\n >&2 "warning: can not detect any remote branches for: '$repoDir'" "" # warning is not a log, do not add `${logLvl?:+`
;;
0:*)
# all ok
;;
*)
reposDiffersFromRemote_str=${reposDiffersFromRemote_str}${reposDiffersFromRemote_str:+$NEW_LINE}"'${repoDir}': ${localFiles_differ_str} repos differ:${NEW_LINE}$(git_getAllBranchWithHash)${NEW_LINE}"
run_git_status=0
esac
#
case $run_git_status in 1)
git status
echo
echo
esac
cd "$OLDPWD" || exit
done >&2
printf %s\\n "" --------
case ${uncommited:+x}:${reposDiffersFromRemote_str:+x} in
x:x)
printf %s\\n "" "$uncommited" "" "$reposDiffersFromRemote_str"
;;
*x*)
printf %s\\n "" "${uncommited}${reposDiffersFromRemote_str}"
;;
esac
case $errs in 0) ;; *)
case "${uncommited:+$NEW_LINE}${reposDiffersFromRemote_str:+x}" in
:x) printf \\n;;
x:|x:x) printf \\n\\n;;
esac
printf %s\\n >&2 "errors count: ${errs}"
exit 1
esac