forked from kamranahmedse/git-standup
-
Notifications
You must be signed in to change notification settings - Fork 0
/
git-standup
executable file
·316 lines (268 loc) · 8.01 KB
/
git-standup
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
#!/usr/bin/env bash
# shellcheck disable=SC2128
# Shows the usage
function usage() {
cat << EOS
Usage:
git standup [-a <author name>] [-w <weekstart-weekend>] [-d <since-days-ago>] [-u <until-days-ago>] [-m <max-dir-depth>] [-g] [-h] [-f] [-c]
-a - Specify author to restrict search to or use "all" to see all authors
-b - Specify branch to restrict search to (unset: all branches, "\$remote/\$branch" to include fetches)
-w - Specify weekday range to limit search to
-m - Specify the depth of recursive directory search
-F - Force recursion up to speficied depth
-L - Toggle inclusion of symbolic links in recursive directory search
-d - Specify the number of days back to include
-u - Specify the number of days back until this day
-D - Specify the date format for "git log" (default: relative, other: local|default|iso|rfc|short|raw)
-h - Display this help screen
-g - Show if commit is GPG signed (G) or not (N)
-f - Fetch the latest commits beforehand
-s - Silences the no activity message (useful when running in a directory having many repositories)
-r - Generate a file with the report
-c - Show diffstat for every matched commit
-A - List commits after this date
-B - List commits before this date
-R - Display the author date instead of the committer date
Examples:
git standup -a "John Doe" -w "MON-FRI" -m 3
EOS
}
# Sets up the colored output
function colored() {
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
BOLD=$(tput bold)
UNDERLINE=$(tput smul)
NORMAL=$(tput sgr0)
GIT_PRETTY_DATE="%cd"
if [[ ${option_R:=} ]]; then
GIT_PRETTY_DATE="%ad"
fi
if [[ $GIT_LOG = "shortlog" ]]; then
GIT_PRETTY_FORMAT="%Cred%h%Creset - %s %Cgreen($GIT_PRETTY_DATE) %Creset"
else
GIT_PRETTY_FORMAT="%Cred%h%Creset - %s %Cgreen($GIT_PRETTY_DATE) %C(bold blue)<%an>%Creset"
fi
COLOR=always
if [[ ${option_g:=} ]]; then
GIT_PRETTY_FORMAT="$GIT_PRETTY_FORMAT %C(yellow)gpg: %G?%Creset"
fi
}
# Sets up the uncolored output
function uncolored() {
# shellcheck disable=SC2034
RED=""
GREEN=""
YELLOW=""
# shellcheck disable=SC2034
BLUE=""
BOLD=""
UNDERLINE=""
NORMAL=""
GIT_PRETTY_DATE="%cd"
if [[ $option_R ]]; then
GIT_PRETTY_DATE="%ad"
fi
if [[ $GIT_LOG = "shortlog" ]]; then
GIT_PRETTY_FORMAT="%h - %s ($GIT_PRETTY_DATE)"
else
GIT_PRETTY_FORMAT="%h - %s ($GIT_PRETTY_DATE) <%an>"
fi
COLOR=never
if [[ $option_g ]]; then
GIT_PRETTY_FORMAT="$GIT_PRETTY_FORMAT gpg: %G?\n"
else
GIT_PRETTY_FORMAT="$GIT_PRETTY_FORMAT \n"
fi
}
function writeFile() {
echo -e "$1" >> "${REPORT_FILE_PATH}"
}
function runStandup() {
# Fetch the latest commits, if required
if [[ ${option_f:=} ]]; then
echo "${BOLD}${GREEN}Fetching commits in ${YELLOW}${UNDERLINE}${BOLD}${BASENAME}${NORMAL}"
git fetch --all > /dev/null 2>&1
fi
{
# shellcheck disable=SC2086
GITOUT=$(eval ${GIT_LOG_COMMAND} 2> /dev/null)
} || {
GITOUT=""
}
# If `r` option was given then no output, just write the report
if [[ -n ${option_r:=} ]]; then
echo "Generating report for: ${CUR_DIR}"
if [[ -n "$GITOUT" ]]; then
writeFile "${CUR_DIR}\n $GITOUT"
elif [[ -z ${option_s:=} ]]; then
writeFile "${CUR_DIR}\n No activity found!\n"
fi
else
## Only output if there is some activity
if [[ -n "$GITOUT" ]]; then
echo "${BOLD}${UNDERLINE}${YELLOW}$CUR_DIR${NORMAL}"
echo "$GITOUT"
elif [[ -z $option_s ]]; then ## Show the no activity message only if the `s` flag is not there
echo "${BOLD}${UNDERLINE}${YELLOW}$CUR_DIR${NORMAL}"
if [[ ${AUTHOR} = '.*' ]]; then
echo "${YELLOW}No commits found during this period.${NORMAL}"
else
echo "${YELLOW}No commits from $AUTHOR during this period.${NORMAL}"
fi
fi
fi
}
while getopts "hgfsd:u:a:w:m:D:A:B:LrcRFGb:" opt; do
case $opt in
h | d | u | a | w | m | g | D | f | s | L | r | A | B | c | R | F | G | b)
declare "option_$opt=${OPTARG:-0}"
;;
\?)
echo >&2 "Use 'git standup -h' to see usage info"
exit 1
;;
esac
done
shift $((OPTIND - 1))
if [[ $# -gt 0 ]]; then
echo >&2 "Invalid arguments: $*"
echo >&2 "Use 'git standup -h' to see usage info"
exit 1
fi
# Main script
if [[ ${option_h:=} ]]; then
usage
exit 0
fi
AUTHOR=$(git config user.name)
GIT_LOG="log"
if [[ ${option_a:=} ]]; then
# In case the parameter
if [[ $option_a = 'all' ]]; then
AUTHOR=".*"
if [[ ${option_G:=} ]]; then
GIT_LOG="shortlog"
fi
else
AUTHOR="$option_a"
fi
fi
# Use colors, but only if connected to a terminal, and that terminal supports them.
if [[ -t 1 ]] && [[ -n "$TERM" ]] && command -v tput &> /dev/null && tput colors &> /dev/null; then
ncolors=$(tput colors)
if [[ -n "$ncolors" ]] && [[ "$ncolors" -ge 8 ]] && [[ -z "$option_r" ]]; then
colored
else
uncolored
fi
else
uncolored
fi
## Set the necessary variables for standup
SINCE="yesterday"
MAXDEPTH=2
INCLUDE_LINKS=
RAN_FROM_DIR=$(pwd)
REPORT_FILE_PATH="${RAN_FROM_DIR}/git-standup-report.txt"
STAT=
# If report is to be generated, remove the existing report file if any
if [[ -n $option_r ]]; then
rm -rf "${REPORT_FILE_PATH}"
fi
if [[ ${option_m:=} ]]; then
MAXDEPTH="$((${option_m:=} + 1))"
fi
if [[ ${option_L:=} ]]; then
INCLUDE_LINKS="-L"
fi
if [[ ${option_c:=} ]]; then
STAT="--stat"
fi
## If -d flag is there, use its value for the since
if [[ ${option_d:=} ]] && [[ $option_d -ne 0 ]]; then
SINCE="$option_d days ago"
else
## -d flag is not there, go on with the normal processing
WEEKSTART="$(cut -d '-' -f 1 <<< "${option_:=w}")"
WEEKSTART=${WEEKSTART:="Mon"}
WEEKEND="$(cut -d '-' -f 2 <<< "${option_w:=}")"
WEEKEND=${WEEKEND:="Fri"}
## In case it is the start of week, we need to
## show the commits since the last weekend
shopt -s nocasematch
if [[ ${WEEKSTART} == "$(date +%a)" ]]; then
SINCE="last $WEEKEND"
fi
fi
## If -u flag is there, use its value for the until
if [[ ${option_u:=} ]] && [[ $option_u -ne 0 ]]; then
UNTIL_OPT="--until=\"$option_u days ago\""
elif [[ ${option_B:=} ]]; then
UNTIL_OPT="--until=\"$option_B\""
fi
if [[ ${option_A:=} ]]; then
AFTER_OPT="--after=\"$option_A\""
fi
GIT_DATE_FORMAT=${option_D:-relative}
# For when the command has been run in a non-repo directory
if [[ ${option_F:=} || ! -d ".git" || -f ".git" ]]; then
BASE_DIR=$(pwd)
# Set delimiter to newline for the loop
IFS=$'\n'
if [[ -f ".git-standup-whitelist" ]]; then
SEARCH_PATH=$(cat .git-standup-whitelist)
else
SEARCH_PATH=.
fi
# Recursively search for git repositories
PROJECT_DIRS=$(find ${INCLUDE_LINKS} ${SEARCH_PATH} -maxdepth ${MAXDEPTH} -mindepth 0 -name .git)
elif [[ -f ".git" || -d ".git" ]]; then
PROJECT_DIRS=("$(pwd)/.git")
fi
# if project directories is still empty
# we might be sitting inside a git repo
if [[ -z ${PROJECT_DIRS} ]]; then
ROOT_DIR_COMMAND="git rev-parse --show-toplevel"
PROJECT_ROOT=$(eval "${ROOT_DIR_COMMAND}" 2> /dev/null)
if [[ -z ${PROJECT_ROOT} ]]; then
echo "${YELLOW}You must be inside a git repository!${NORMAL}"
exit 0
fi
PROJECT_DIRS=("${PROJECT_ROOT}/.git")
fi
# Foreach of the project directories, run the standup
IFS=$'\n'
for DIR in ${PROJECT_DIRS}; do
PROJECT_DIR=$(dirname "$DIR")
cd "$PROJECT_DIR" || exit
CUR_DIR=$(pwd)
BASENAME=$(basename "$CUR_DIR")
# continue if not a git directory
if [[ ! -d ".git" || -f ".git" ]]; then
cd "${BASE_DIR}" || exit
continue
fi
GIT_BRANCH_FILTER="--all"
if [[ ${option_b:=} ]]; then
GIT_BRANCH_FILTER="--first-parent $option_b"
fi
GIT_LOG_COMMAND="git --no-pager ${GIT_LOG} \
${GIT_BRANCH_FILTER}
--no-merges
--since=\"$SINCE\"
${UNTIL_OPT}
${AFTER_OPT}
--author=\"$AUTHOR\"
--abbrev-commit
--oneline
--pretty=format:'$GIT_PRETTY_FORMAT'
--date='$GIT_DATE_FORMAT'
--color=$COLOR
${STAT}"
runStandup
cd "${BASE_DIR}" || exit
done
unset IFS