Created
September 11, 2008 20:16
-
-
Save mislav/10301 to your computer and use it in GitHub Desktop.
Generates an adds/removes-based scoreboard for a git project
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Usage: | |
$ ruby git-scoreboard.rb | |
You can also specify a range of commits: | |
$ ruby git-scoreboard.rb v1.2..HEAD | |
## Outputs: | |
Most adds: | |
1. Mislav Marohnic 36430 | |
2. Steve Jobs 4329 | |
3. Bill Gates 2144 | |
Most deletes: | |
1. Bill Gates 12736 | |
2. Mislav Marohnic 926 | |
3. Steve Jobs 903 | |
## Note: | |
This script ignores these files: | |
* extensions: sql, xml, yml | |
* everything under "vendor/" or "log/" | |
* Prototype and script.aculo.us |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
## Scoreboard for git projects with multiple people committing. | |
## This is a better version of: git log --pretty=format:%an | sort | uniq -ci | sort -r | head -n30 | |
scoreboard = {} | |
author = commit_id = changes_per_commit = nil | |
commits = [] | |
# TODO: ignore file moves :( | |
ignore_mode = false | |
$ignore_pattern = %r! | |
(?: | |
\.(?: sql | xml | ya?ml ) | # ignored file extensions | |
/javascripts/(?: builder|controls|effects|scriptaculous|prototype )\.js | | |
(?: ^ | |
public/dispatch\.\w{2,4} | | |
public/\d{3}.html | | |
config/boot.rb | |
) | |
)$ | | |
\b(?: vendor | log )/ # otherwise the winner would be the one who freezes rails | |
!x | |
log = `git log --no-merges -p --pretty=format:"##%an|%h" #{ARGV.join(' ')}` | |
log.each_line do |line| | |
if line =~ %r{^diff .+ a/(.+) b/(.+)\n$} | |
## start of a file | |
path = $1 | |
ignore_mode = path =~ $ignore_pattern | |
puts "ignored: " + path if ignore_mode and $VERBOSE | |
else | |
case line[0,2] | |
when '##' | |
## start of a commit | |
# record last commit info: | |
commits << [commit_id, changes_per_commit] if commit_id | |
# initialize metadata: | |
author, commit_id = line[2..-2].split('|') | |
scoreboard[author] ||= [0, 0] | |
changes_per_commit = 0 | |
when '+ ', '- ' | |
## the main stuff! | |
unless ignore_mode | |
scoreboard[author][line[0,1] == '+' ? 0 : 1] += 1 | |
changes_per_commit += 1 | |
end | |
end | |
end | |
end | |
everyone = scoreboard.to_a | |
# names with multibyte chars screw this up, but whatever: | |
longest_name = scoreboard.keys.compact.sort_by { |name| name.length }.last.length | |
def output(entries, index, width) | |
entries.reverse.each_with_index do |entry, i| | |
puts sprintf(' %2d. %s %d', i + 1, entry[0].ljust(width), entry[1][index]) | |
break if i == 29 | |
end | |
end | |
puts "Most adds:" | |
output(everyone.sort_by { |entry| entry[1][0] }, 0, longest_name) | |
puts "\nMost deletes:" | |
output(everyone.sort_by { |entry| entry[1][1] }, 1, longest_name) | |
if $VERBOSE | |
largest = commits.sort_by { |c| c[1] }[-4..-1].reverse.map { |c| c[0] } | |
puts "\nLargest commits: #{largest.join(', ')}" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment