1 | #!/bin/bash
|
---|
2 |
|
---|
3 | # Parses Subversion repository log messages and outputs authors and their
|
---|
4 | # respective number of commits.
|
---|
5 | #
|
---|
6 | # Output can be sorted:
|
---|
7 | #
|
---|
8 | # -a sort output by author name
|
---|
9 | # -c sort output by number of commits
|
---|
10 | #
|
---|
11 | # Output can also be limited to commits from the last year:
|
---|
12 | #
|
---|
13 | # -y display only commits from the last 365 days
|
---|
14 | #
|
---|
15 | # Will run on first 'path' parameter, or on current working directory if no
|
---|
16 | # path is supplied.
|
---|
17 | #
|
---|
18 | # TODO:
|
---|
19 | # - Add option to bin authors and commits by year
|
---|
20 | # - Convert to using XML output from SVN log (i.e. `svn log --xml`)
|
---|
21 |
|
---|
22 | ## Functions
|
---|
23 | #
|
---|
24 |
|
---|
25 | function display_help {
|
---|
26 | echo "usage: ${script_name} [option] [path]" >&2
|
---|
27 | case "${uname_out}" in
|
---|
28 | Linux*)
|
---|
29 | display_help_linux
|
---|
30 | ;;
|
---|
31 | Darwin*)
|
---|
32 | display_help_mac
|
---|
33 | ;;
|
---|
34 | *)
|
---|
35 | ;;
|
---|
36 | esac
|
---|
37 | }
|
---|
38 |
|
---|
39 | function display_help_mac {
|
---|
40 | echo " -h diplay help"
|
---|
41 | echo " -a sort output by author name"
|
---|
42 | echo " -c sort output by number of commits"
|
---|
43 | echo " -y display only commits from the last 365 days"
|
---|
44 | }
|
---|
45 |
|
---|
46 | function display_help_linux {
|
---|
47 | echo " -h | --help diplay help"
|
---|
48 | echo " -a | --authors sort output by author name"
|
---|
49 | echo " -c | --commits sort output by number of commits"
|
---|
50 | echo " -y | --year display only commits from the last 365 days"
|
---|
51 | }
|
---|
52 |
|
---|
53 | function print_authors {
|
---|
54 | i=0
|
---|
55 | until [[ $i -eq "${#authors[@]}" ]]; do
|
---|
56 | printf "%-15s %i\n" "${authors[$i]}" "${commits[$i]}"
|
---|
57 | (( i++ ))
|
---|
58 | done
|
---|
59 | }
|
---|
60 |
|
---|
61 | function print_authors_sorted_by_author {
|
---|
62 | local i=0
|
---|
63 | until [[ $i -eq "${#authors[@]}" ]]; do
|
---|
64 | printf "%-15s %i\n" "${authors[$i]}" "${commits[$i]}"
|
---|
65 | (( i++ ))
|
---|
66 | done |
|
---|
67 | sort -n -k1
|
---|
68 | }
|
---|
69 |
|
---|
70 | function print_authors_sorted_by_commits {
|
---|
71 | local i=0
|
---|
72 | until [[ $i -eq "${#authors[@]}" ]]; do
|
---|
73 | printf "%-15s %i\n" "${authors[$i]}" "${commits[$i]}"
|
---|
74 | (( i++ ))
|
---|
75 | done |
|
---|
76 | sort -rn -k2
|
---|
77 | }
|
---|
78 |
|
---|
79 | ## Initialize conditional variables
|
---|
80 | #
|
---|
81 | one_year_ago=""
|
---|
82 | sort_by_author=0
|
---|
83 | sort_by_commits=0
|
---|
84 | today=""
|
---|
85 |
|
---|
86 | # Retrieve script name
|
---|
87 | script_name=$(basename "$0")
|
---|
88 |
|
---|
89 | ## Retrieve OS
|
---|
90 | #
|
---|
91 | uname_out=$(uname -s)
|
---|
92 | case "${uname_out}" in
|
---|
93 | Linux*)
|
---|
94 | options=$(getopt -n ${script_name} -o hacy --long help,author,commits,year -- "$@")
|
---|
95 | ;;
|
---|
96 | Darwin*)
|
---|
97 | options=$(getopt hacy $*)
|
---|
98 | ;;
|
---|
99 | *)
|
---|
100 | printf "operating system %s not currently supported\n" "${uname_out}" >&2
|
---|
101 | exit 1
|
---|
102 | ;;
|
---|
103 | esac
|
---|
104 |
|
---|
105 | ## Handle options
|
---|
106 | #
|
---|
107 | valid_options=$?
|
---|
108 | if [[ $valid_options -ne 0 ]]; then
|
---|
109 | display_help
|
---|
110 | exit 1
|
---|
111 | fi
|
---|
112 | #echo $options # Uncomment for debugging
|
---|
113 | set -- $options
|
---|
114 |
|
---|
115 | while :
|
---|
116 | do
|
---|
117 | case "$1" in
|
---|
118 | -h | --help)
|
---|
119 | display_help
|
---|
120 | exit 0
|
---|
121 | ;;
|
---|
122 | -a | --author)
|
---|
123 | sort_by_author=1
|
---|
124 | shift
|
---|
125 | ;;
|
---|
126 | -c | --commits)
|
---|
127 | sort_by_commits=1
|
---|
128 | shift
|
---|
129 | ;;
|
---|
130 | -y | --year)
|
---|
131 | today=$(date +%Y-%m-%d)
|
---|
132 | one_year_ago=$(date -v -1y -v +1d +%Y-%m-%d) # Date adjusted 365 days
|
---|
133 | shift
|
---|
134 | ;;
|
---|
135 | --)
|
---|
136 | shift
|
---|
137 | break
|
---|
138 | ;;
|
---|
139 | *)
|
---|
140 | break
|
---|
141 | ;;
|
---|
142 | esac
|
---|
143 | done
|
---|
144 |
|
---|
145 | ## Retrieve path
|
---|
146 | #
|
---|
147 | # If no path was given, use current working directory; if one or more were
|
---|
148 | # given, just use the first one.
|
---|
149 | #
|
---|
150 | path="."
|
---|
151 | num_args=${#@}
|
---|
152 | if [[ $num_args -gt 0 ]]; then
|
---|
153 | path=$1
|
---|
154 | fi
|
---|
155 |
|
---|
156 | authors=()
|
---|
157 | commits=()
|
---|
158 |
|
---|
159 | # Get entire log once
|
---|
160 | if [[ $one_year_ago != "" ]]; then
|
---|
161 | log=$(svn log -r "{${today}}:{${one_year_ago}}" "${path}")
|
---|
162 | else
|
---|
163 | log=$(svn log "${path}")
|
---|
164 | fi
|
---|
165 |
|
---|
166 | data_lines=$(echo "${log}" | egrep "r[0-9]+") # Get only lines from log that contain info we care about
|
---|
167 |
|
---|
168 | while IFS= read line; do
|
---|
169 | author=$(echo "${line}" | awk -F "|" '{print $2}' | tr -d ' ')
|
---|
170 |
|
---|
171 | # Uncomment if we want to treat blank author as "unknown"
|
---|
172 | if [[ "$author" == "" ]]; then
|
---|
173 | author="unknown"
|
---|
174 | fi
|
---|
175 |
|
---|
176 | have_seen_author=0
|
---|
177 | for (( i=0; i<${#authors[@]}; ++i )); do
|
---|
178 | if [[ "${authors[$i]}" == "$author" ]]; then
|
---|
179 | have_seen_author=1
|
---|
180 | break
|
---|
181 | fi
|
---|
182 | done
|
---|
183 |
|
---|
184 | if [[ $have_seen_author -eq 0 ]]; then
|
---|
185 | authors+=("${author}")
|
---|
186 | commits+=(1)
|
---|
187 | else
|
---|
188 | (( commits[$i]++ ))
|
---|
189 | fi
|
---|
190 | done <<< "${data_lines}"
|
---|
191 |
|
---|
192 | ## Print results (sorted, if requested)
|
---|
193 | #
|
---|
194 | # NOTE: If multiple sort options are specified, the order or precedence is
|
---|
195 | # specified as follows.
|
---|
196 | #
|
---|
197 | if [ $sort_by_commits -eq 1 ]; then
|
---|
198 | print_authors_sorted_by_commits
|
---|
199 | elif [ $sort_by_author -eq 1 ]; then
|
---|
200 | print_authors_sorted_by_author
|
---|
201 | else
|
---|
202 | print_authors
|
---|
203 | fi
|
---|