Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions readme.md → README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ Or:
## authorship

This is more tricky, and requires Ruby. First run the
`determine_authors.sh` script to get a count of all the authorship
`commits_stats.sh` script to get a count of all the authorship
events in the repo; then run the `tally_authors.rb` Ruby script to sort
the authorship events by name.

You can do all that as a one-liner in bash like this:

ruby tally_authors.rb <(cd /project && /this_dir/determine_authors.sh "js")
ruby tally_authors.rb <(cd /project && /this_dir/commits_stats.sh -d "js")

The code isn't tricky at all, and the output is easy to understand, but
it's also easy to misconstrue. That's the tricky part. A developer
Expand All @@ -47,7 +47,7 @@ commits to small ones, or for several other possible reasons. Exercise
good judgement.

Also, where `file_stats.sh` will examine multiple file types,
`determine_authors.sh` and `tally_authors.rb` assumes you're only
`commits_stats.sh` and `tally_authors.rb` assumes you're only
working with one type of file at a time. Pull requests welcome!

Caveat: Running this code against extremely large projects with very
Expand Down
130 changes: 130 additions & 0 deletions commits_stats.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/bin/bash
CMD=`basename $0`;

# prints the usage message
function usage() {
echo -e "$CMD is a script to extract some basic info on git commits and
authors from the files contained in the current directory.
If invoked without parameters it will output the overall list of commits
count per author (-o) followed by the list of files with the commit count
for each author.
It can also be used to extract information on specific file extensions.\n
Syntax: $CMD [-h|-o|[-c|-a|-d] <filetype>]
\t-h: prints this help
\t-o: displays just the overall commits count per author
\t-c: displays the files ordered by number of commits
\t-a: displays overall commits, and list of commits by author per each file
\t-d: just extract the authors, to be used in conjunction with tally_authors.rb
\t<filetype>: display authors commit count for specific filetypes
\te.g. $CMD js # examines authorship for *.js files
\n"
}

# returns the list of authors
function extract_authors {
for filename in $(find . -iname "${PATTERN}"); do
git log $filename | grep "Author"
done
}

# uses the log of a specific file to capture the number of commits per person
function count_author_commits_per_file {
if [[ ! -n $1 ]]; then
filename=''
else
filename=$1;
fi
git log --pretty=format:"%an <%ae>" $filename | awk '{
authorsCount[$NF]++;
authors[$NF]=$0;
}
END {
for (i in authorsCount)
printf("%d\t%s\n", authorsCount[i], authors[i]);
}';
}

function tally_authors {
if [[ -n $OVERALL_ONLY ]]; then
echo "Overall";
count_author_commits_per_file | sort -k1,1nr -k2,2;
return
fi
for filename in $(find . -iname "${PATTERN}" -not -wholename "*.git*" -not -wholename "*.svn*"); do
authors=`count_author_commits_per_file $filename | sort -k1,1nr -k2,2`;
if [ "$authors" = "" ]; then
continue;
fi
if [ $filename = '.' ]; then
echo "Overall"
else
echo $filename;
fi
echo "$authors";
done
}

function count_commits_per_file {
for filename in $(find . -iname "${PATTERN}" -not -wholename "*.git*" -not -wholename "*.svn*"); do
commits_count=`git rev-list HEAD --count ${filename}`;
if [ $commits_count -gt 0 ]; then
echo -e "${commits_count}\t${filename}";
fi
done
}

function sort_files_by_commits {
file_commits=`count_commits_per_file | sort -k1,1nr -k2,2`;
if [[ -n $ALL_STATS ]]; then
echo "${file_commits}" | while read line; do
tot_commits=`echo ${line} | awk '{ print $1 }'`;
filename=`echo "${line}" | awk '{ sub(/.*\t/, ""); print }'`;
echo ${filename};
echo "${tot_commits} total commit(s)"
count_author_commits_per_file $filename | sort -k1,1nr -k2,2;
echo "";
done
else
echo "$file_commits";
fi
}

while getopts ":hocad" Option
do
case $Option in
h) usage
exit 0
;;
o) OVERALL_ONLY=true
;;
c) FILE_COMMITS_ONLY=true
;;
a) ALL_STATS=true
;;
d) DEPRECATED=true
;;
esac
done

# Decrements the argument pointer so it points to next argument.
# $1 now references the first non-option item supplied on the command-line
# if one exists.
shift $(($OPTIND - 1))

if [ $# -eq 1 ]; then
PATTERN="*.$1";
else
PATTERN='*.*';
fi

if [[ -n $FILE_COMMITS_ONLY ]]; then
sort_files_by_commits;
elif [[ -n $ALL_STATS ]]; then
sort_files_by_commits;
elif [[ -n $DEPRECATED ]]; then
extract_authors;
else
tally_authors "${PATTERN}";
fi

exit 0
2 changes: 2 additions & 0 deletions file_stats.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/bin/bash

function git_history {
git log $filename | grep "Date: "
}
Expand Down