File: git-standup

package info (click to toggle)
git-extras 7.4.0-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 2,120 kB
  • sloc: sh: 4,312; python: 994; makefile: 146
file content (301 lines) | stat: -rwxr-xr-x 8,795 bytes parent folder | download
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
#!/usr/bin/env bash

# Code modified from https://github.com/kamranahmedse/git-standup,
# under the MIT LICENSE.
usage() {
    cat <<EOS
    Usage:
    git standup [-a <author name>] [-w <weekstart-weekend>|-d <days-ago>] [-m <max-dir-depth>] [-D date-format] [-L] [-h] [-f] [-B] [-n <number-of-commits] [-F <gpg|authordate>]

    -a      - Specify author to restrict search to, default to current git user.
              Use "-a all" if you don't want the restriction.
    -w      - Specify weekday range to limit search to
    -m      - Specify the depth of recursive directory search
    -L      - Toggle inclusion of symbolic links in recursive directory search
    -d      - Specify the number of days back to include
    -D      - Specify the date format for "git log" (default: relative)
    -h      - Display this help screen
    -f      - Fetch the latest commits beforehand
    -B      - Display the commits in branch groups
    -n      - Limit the number of commits displayed per group
    -F gpg  - Show if commit is GPG signed (G) or not (N)
    -F authordate - Print author date instead of commit date

    Examples:
    git standup -a "John Doe" -w "MON-FRI" -m 3
EOS
}

warn() {
    >&2 echo "${BOLD}${RED}WARNING: $1${NORMAL}"
}

git rev-parse --show-toplevel > /dev/null 2>&1
in_git_repo=$?

# Use colors, but only if connected to a terminal, and that terminal
# supports them.
if command -v tput &>/dev/null; then
    ncolors=$(tput colors)
fi
if [[ -t 1 ]] && [[ -n "$ncolors" ]] && [[ "$ncolors" -ge 8 ]] ; then
    RED="$(tput setaf 1)"
    GREEN="$(tput setaf 2)"
    YELLOW="$(tput setaf 3)"
    BOLD="$(tput bold)"
    NORMAL="$(tput sgr0)"
    BOLD=$(tput bold)
    UNDERLINE=$(tput smul)
    NORMAL=$(tput sgr0)
    COLOR=always
else
    RED=""
    GREEN=""
    YELLOW=""
    BOLD=""
    NORMAL=""
    BOLD=""
    UNDERLINE=""
    NORMAL=""
    COLOR=never
fi

# Only enable exit-on-error after the non-critical colorization stuff,
# which may fail on systems lacking tput or terminfo
set -e

RANGE_SPECIFIED=
COMMIT_DATE_FORMAT=%cd
USE_GPG_FORMAT=no

while getopts "hgfF:Bd:a:w:m:D:n:L" opt; do
    case $opt in
        h)
            usage
            exit 0
            ;;
        a)
            if [[ "$OPTARG" = 'all' ]] ; then
                AUTHOR=".*"
            else
                AUTHOR="$OPTARG"
            fi
            ;;
        d)
            test -n "$RANGE_SPECIFIED" && warn "-d option is conflict with -w"
            RANGE_SPECIFIED=yes
            if [ "$OPTARG" -lt 1 ]; then
                >&2 echo "Specify days less than one is invalid"
                exit 1
            fi
            SINCE="$OPTARG days ago"
            ;;
        w)
            if [ -n "$RANGE_SPECIFIED" ]; then
                warn "-w option is conflict with -d"
                continue
            fi
            RANGE_SPECIFIED=yes

            week_range=${OPTARG}
            week_start="${week_range%%-*}"
            week_start="${week_start:="Mon"}"
            week_end="${week_range##*-}"
            week_end=${week_end:="Fri"}

            ## In case it is the start of week, we need to
            ## show the commits since the last weekend
            shopt -s nocasematch
            if [[ "$week_start" == "$(LC_ALL=C date +%a)" ]] ; then
                SINCE="last $week_end";
            fi
            ;;
        f)
            FETCH_LAST_COMMIT=true
            ;;
        m)
            MAXDEPTH=$((OPTARG + 1))
            if [ "$MAXDEPTH" -lt 1 ]; then
                >&2 echo "Specify depth less than one is invalid"
                exit 1
            fi
            ;;
        L)
            INCLUDE_LINKS=-L
            ;;
        D)
            GIT_DATE_FORMAT=${OPTARG}
            ;;
        g)
            warn "-g option is deprecated, use '-F gpg' instead"
            USE_GPG_FORMAT=yes
            ;;
        B)
            GROUP_BY_BRANCHES=true
            ;;
        n)
            MAX_COMMIT_NUM=${OPTARG}
            ;;
        F)
            case $OPTARG in
                gpg)
                    USE_GPG_FORMAT=yes
                    ;;
                authordate)
                    COMMIT_DATE_FORMAT=%ad
                    ;;
                *)
                    warn "Invalid argument for -F: $OPTARG"
                    usage
                    exit 1
                    ;;
            esac
            ;;
        \?)
            usage
            exit 1
            ;;
    esac
done

shift $((OPTIND-1))

if [[ $# -gt 0 ]]; then
    warn "please upgrade to new-style interface. Run 'git help standup' to get more info."
    if [[ $# -gt 3 ]] ; then
        usage
        exit 1
    fi
    AUTHOR=$1
    SINCE=$2
    UNTIL=$3
fi

AUTHOR=${AUTHOR:="$(git config user.name || echo '')"}
if [ -z "${AUTHOR}" ]; then
    warn "please configure an author with 'git config user.name' or specify an author via '-a'"
    exit 1
fi

FETCH_LAST_COMMIT=${FETCH_LAST_COMMIT:=false}
MAXDEPTH=${MAXDEPTH:=2}
GIT_PRETTY_FORMAT="%Cred%h%Creset - %s %Cgreen(${COMMIT_DATE_FORMAT}) %C(bold blue)<%an>%Creset"
GIT_DATE_FORMAT=${GIT_DATE_FORMAT:=relative}
if [[ "$USE_GPG_FORMAT" == 'yes' ]]; then
    GIT_PRETTY_FORMAT="$GIT_PRETTY_FORMAT %C(yellow)gpg: %G?%Creset"
fi

# Handle config of implicit week
IMPLICIT_WEEK=$(git config --get git-extras.standup.implicit-week || echo '')
if [[ -z "$RANGE_SPECIFIED" ]] && [[ -n "${IMPLICIT_WEEK}" ]]; then
    week_start=${IMPLICIT_WEEK%%-*}
    week_end=${IMPLICIT_WEEK##*-}
    shopt -s nocasematch
    if [[ "$week_start" == "$(LC_ALL=C date +%a)" ]]; then
        SINCE="last $week_end"
    fi
    UNTIL=today
else
    SINCE=${SINCE:=yesterday}
    UNTIL=${UNTIL:=today}
fi

GIT_LOG_COMMAND="git --no-pager log \
    --no-merges
    --since \"$SINCE\"
    --until \"$UNTIL\"
    --author=\"$AUTHOR\"
    --abbrev-commit
    --oneline
    --color=$COLOR
    --pretty=format:'$GIT_PRETTY_FORMAT'
    --date='$GIT_DATE_FORMAT'"
if [[ -n "$MAX_COMMIT_NUM" ]]; then
    GIT_LOG_COMMAND="$GIT_LOG_COMMAND --max-count=$MAX_COMMIT_NUM"
fi

git_output() {
    if [ "$GROUP_BY_BRANCHES" = true ]; then
        local branches
        branches=$(git branch --sort=-committerdate | awk '{print substr($0, 3)}')
        for branch in $branches; do
            # shellcheck disable=SC2086
            if output=$(eval $GIT_LOG_COMMAND "$branch"); then
                if [[ -n "$output" ]] ;  then
                    echo "${GREEN}${branch}${NORMAL}"
                    echo "$output"
                    echo ""
                fi
            fi
            # TODO optimize:return if the latest commit of a branch is earlier than the 'since' day
        done
    else
        # shellcheck disable=SC2086
        eval $GIT_LOG_COMMAND --all
    fi
}

## For when the command has been run in a non-repo directory
if [[ $in_git_repo != 0 ]]; then
    ## Set delimiter to newline for the loop
    IFS=$'\n'
    ## Recursively search for git repositories
    # shellcheck disable=SC2086
    PROJECT_DIRS=$(find $INCLUDE_LINKS . -maxdepth "$MAXDEPTH" -mindepth 0 -name .git)

    # Fetch the latest commits, if required
    if [ "$FETCH_LAST_COMMIT" = true ]; then

        echo "${BOLD}${GREEN}Fetching commits ..${NORMAL}"

        # Foreach of the project directories, fetch the commits
        for DIR in $PROJECT_DIRS; do
            DIR="$(dirname "$DIR")"
            pushd "$DIR" > /dev/null

            if [[ -d ".git" ]] ; then
                echo "   ${YELLOW}$(basename "$DIR")${NORMAL}"
                git fetch --all > /dev/null 2>&1
            fi

            popd > /dev/null
        done
    fi

    # Get the standup details for each of the projects
    for DIR in $PROJECT_DIRS; do
        DIR="$(dirname "$DIR")"
        pushd "$DIR" > /dev/null
        ## Show the detail only if it is a git repository
        if [[ -d ".git" || -f ".git" ]] ; then
            if GITOUT=$(git_output); then
                ## Only output if there is some activities
                if [[ -n "$GITOUT" ]] ;  then
                    echo "${BOLD}${UNDERLINE}${YELLOW}$(basename "$DIR")${NORMAL}"
                    echo "$GITOUT"
                    echo ""
                fi
            else
                echo "Repository under $DIR could not be queried." >&2
            fi
        fi
        popd > /dev/null
    done
else
    if [ "$FETCH_LAST_COMMIT" = true ]; then
        echo "${GREEN}Fetching commits ..${NORMAL}"
        git fetch --all > /dev/null 2>&1
    fi

    if GITOUT=$(git_output); then
        if [[ -n "$GITOUT" ]] ;  then
            echo "$GITOUT"
        else
            if [[ $AUTHOR = '.*' ]] ; then
                AUTHOR="all the contributors"
            fi

            echo "${YELLOW}Seems like $AUTHOR did nothing!${NORMAL}"
        fi
    fi
fi