Skip to content

Commit 222c4b2

Browse files
committed
Add script to rank files by commit counts
1 parent 5854d44 commit 222c4b2

1 file changed

Lines changed: 135 additions & 0 deletions

File tree

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Counts the number of times each file has been modified (i.e., included in a commit) and prints a ranked list.
4+
#
5+
6+
7+
# VARIABLES #
8+
9+
# Define a file path filter:
10+
file_path_filter=''
11+
12+
# Define the number of files to show:
13+
num_files=20
14+
15+
16+
# FUNCTIONS #
17+
18+
# Defines an error handler.
19+
#
20+
# $1 - error status
21+
on_error() {
22+
exit "$1"
23+
}
24+
25+
# Prints usage information.
26+
usage() {
27+
echo '' >&2
28+
echo 'Usage: rank_files_by_commit_counts [options]' >&2
29+
echo '' >&2
30+
echo 'Options:' >&2
31+
echo '' >&2
32+
echo ' -h, --help Print this message.' >&2
33+
echo ' --filter filter File path filter.' >&2
34+
echo ' -n, --numfiles count Number of files to show.' >&2
35+
echo '' >&2
36+
}
37+
38+
# Ranks files.
39+
#
40+
# $1 - filter
41+
# $2 - number of files to print
42+
rank() {
43+
# * `git log`
44+
# - Get commit logs, reporting renames (`-M`) and copies (`-C`), and only show the names of modified files.
45+
# * `grep -v '^$'`
46+
# - Remove empty lines.
47+
# * `grep "$1"`
48+
# - Filter file paths using a provided filter.
49+
# * `sort`
50+
# - Sort in alphabetical order.
51+
# * `uniq -c`
52+
# - Remove and count repeats.
53+
# * `sort -r`
54+
# - Sort in reverse order such that higher counts come first.
55+
# * `head`
56+
# - Only show a specified number of files.
57+
git log --all -M -C --name-only --format='format:' | grep -v '^$' | grep "$1" | sort | uniq -c | sort -r | head -n "$2"
58+
}
59+
60+
# Main execution sequence.
61+
main() {
62+
rank "${file_path_filter}" "${num_files}"
63+
exit 0
64+
}
65+
66+
# Parse command-line options...
67+
while :; do
68+
case "$1" in
69+
'-h' | '--help')
70+
usage
71+
exit 0
72+
;;
73+
74+
'-n' | '--numfiles')
75+
if [[ -n "$2" ]]; then
76+
num_files="$2"
77+
shift
78+
else
79+
printf 'ERROR: "-n, --numfiles" option requires a non-empty option argument.\n' >&2
80+
on_error 1
81+
fi
82+
;;
83+
'-n='?* | '--numfiles='?*)
84+
# Delete everything up to "=" and assign the remainder:
85+
num_files="${1#*=}"
86+
;;
87+
88+
'-n=' | '--numfiles=')
89+
# Handle empty `-n=` and `--numfiles=` options:
90+
printf 'ERROR: "-n, --numfiles" option requires a non-empty option argument.\n' >&2
91+
on_error 1
92+
;;
93+
94+
'--filter')
95+
if [[ -n "$2" ]]; then
96+
file_path_filter="$2"
97+
shift
98+
else
99+
printf 'ERROR: "--filter" option requires a non-empty option argument.\n' >&2
100+
on_error 1
101+
fi
102+
;;
103+
104+
'--filter='?*)
105+
# Delete everything up to "=" and assign the remainder:
106+
file_path_filter="${1#*=}"
107+
;;
108+
109+
'--filter=')
110+
# Handle empty `--filter=` option:
111+
printf 'ERROR: "--filter" option requires a non-empty option argument.\n' >&2
112+
on_error 1
113+
;;
114+
115+
'--')
116+
# End of all options:
117+
shift
118+
break
119+
;;
120+
121+
-?*)
122+
printf 'WARNING: unknown option (ignored): %s\n.' "$1" >&2
123+
break
124+
;;
125+
126+
*)
127+
# Default case (e.g., if no more options) break out of loop:
128+
break
129+
esac
130+
131+
shift
132+
done
133+
134+
# Run main:
135+
main

0 commit comments

Comments
 (0)