Skip to content

Instantly share code, notes, and snippets.

@kakutani
Last active August 29, 2015 14:02
Show Gist options
  • Save kakutani/566cfc1b4beff456d90d to your computer and use it in GitHub Desktop.
Save kakutani/566cfc1b4beff456d90d to your computer and use it in GitHub Desktop.
Ruby Commit Count for RubyKaigi 2014

Ruby Commit Count Since v2_0_0_0

...until the latest release on each branche (trunk, ruby_2_0, ruby_1_9_3)

  *  1: nobu        1870 # 100% discount(free as free-beer)
  *  2: akr          716 # |
  *  3: nagachika    488 # |
  *  4: svn          449 # |
  *  5: ko1          423 # |
  *  6: naruse       339 # |
  *  7: zzak         290 # |
  *  8: usa          276 # |
  *  9: kazu         149 # |
  * 10: drbrain      114 # 100% discount(free as free-beer)
  * 11: glass         95 # 50% discount
  * 12: knu           89 # |
  * 13: hsbt          82 # |
  * 14: tmm1          80 # |
  * 15: charliesome   75 # |
  * 16: kou           72 # |
  * 17: kosaki        60 # |
  * 18: a_matsuda     49 # |
  * 19: marcandre     49 # |
  * 20: ktsj          47 # |
  * 21: mrkn          45 # |
  * 22: tarui         45 # |
  * 23: eregon        43 # |
  * 24: normal        39 # |
  * 25: tenderlove    31 # |
  * 26: xibbar        28 # |
  * 27: nari          27 # |
  * 28: shugo         24 # |
  * 29: tadf          20 # 50% discount
  * 30: sorah         15 # 25% discount
  * 31: ayumin        14 # |
  * 32: shirosaki     14 # |
  * 33: nagai         11 # |
  * 34: ngoto         10 # |
  * 35: mame           9 # |
  * 36: emboss         8 # |
  * 37: yugui          8 # |
  * 38: headius        7 # |
  * 39: jeg2           5 # |
  * 40: kouji          5 # |
  * 41: ryan           4 # |
  * 42: duerst         3 # |
  * 43: kanemoto       3 # |
  * 44: takano32       3 # |
  * 45: eban           2 # |
  * 46: luislavena     2 # |
  * 47: matz           2 # |
  * 48: suke           2 # |
  * 49: arton          1 # |
  * 50: shyouhei       1 # 25% discount

trunk (r39474:45877)

  • 1: nobu 1865
  • 2: akr 716
  • 3: svn 438
  • 4: ko1 423
  • 5: naruse 339
  • 6: zzak 289
  • 7: kazu 149
  • 8: drbrain 114
  • 9: usa 103
  • 10: glass 95
  • 11: knu 89
  • 12: hsbt 82
  • 13: tmm1 80
  • 14: charliesome 75
  • 15: kou 72
  • 16: kosaki 60
  • 17: a_matsuda 49
  • 18: marcandre 49
  • 19: ktsj 47
  • 20: mrkn 45
  • 21: tarui 45
  • 22: eregon 43
  • 23: normal 39
  • 24: tenderlove 31
  • 25: xibbar 28
  • 26: nari 27
  • 27: shugo 24
  • 28: tadf 20
  • 29: nagachika 19
  • 30: sorah 15
  • 31: ayumin 14
  • 32: shirosaki 14
  • 33: ngoto 10
  • 34: mame 9
  • 35: nagai 9
  • 36: emboss 8
  • 37: yugui 8
  • 38: headius 7
  • 39: jeg2 5
  • 40: kouji 5
  • 41: ryan 4
  • 42: duerst 3
  • 43: kanemoto 3
  • 44: takano32 3
  • 45: eban 2
  • 46: luislavena 2
  • 47: matz 2
  • 48: suke 2
  • 49: arton 1
  • 50: shyouhei 1

ruby_2_0_0 (r39474:45883)

  • 1: nagachika 469
  • 2: usa 15
  • 3: svn 7
  • 4: nobu 2
  • 5: nagai 1
  • 6: zzak 1

ruby_1_9_3 (r39474:45962)

  • 1: usa 158
  • 2: svn 4
  • 3: nobu 3
  • 4: nagai 1
require 'open3'
require 'nokogiri'
SINCE_REV = 39474
LATEST_REL_REVS = {
trunk: 45877,
ruby_2_0_0: 45883,
ruby_1_9_3: 45962
}
SVN_URL_BASE = 'http://svn.ruby-lang.org/repos/ruby'
def svn_log(branch)
branches = 'branches' unless branch == :trunk
svn_url = [SVN_URL_BASE, branches, branch].compact.join('/')
rev_between = "#{SINCE_REV}:#{LATEST_REL_REVS[branch]}"
Open3.capture2("svn log --xml -r#{rev_between} #{svn_url}")[0]
end
# [[author, count], [author, count], ...]
COUNT_DESC_NAME_ASC = ->(a, b) { (c = b[1] <=> a[1]) == 0 ? a[0] <=> b[0] : c }
def authors_count(log_xml)
authors = Nokogiri(log_xml).search('logentry > author').map(&:text)
authors.each_with_object(Hash.new(0)){|author, count|
count[author] += 1 }.to_a.sort(&COUNT_DESC_NAME_ASC)
end
def fetch_svn_log_xml(branch)
fname = "svn-log-#{branch}.xml"
if File.exist?(fname)
File.read(fname)
else
log_xml = svn_log(branch)
log_xml.tap{|s| File.write(fname, s) }
end
end
# {:branch => [[author,count], ...], :branch => [...]}
commits = LATEST_REL_REVS.keys.each_with_object({}) do |branch, c|
xml = fetch_svn_log_xml(branch)
c[branch] = authors_count(xml)
end
# [[author, count], [author, count], ...]
total = commits.each_with_object(Hash.new(0)) do |(_branch, commits), sum|
commits.each do |author, count|
sum[author] += count
end
end.sort(&COUNT_DESC_NAME_ASC)
RANK_MAX_LENGTH = total.size.to_s.size
NAME_MAX_LENGTH = total.map{|c| c[0].size}.max
COUNT_MAX_LENGTH = total.map{|c| c[1].to_s.size}.max
def _rank(r); "%#{RANK_MAX_LENGTH}d" % r end
def _author(a); "%-#{NAME_MAX_LENGTH}s" % a end
def _count(c); "%#{COUNT_MAX_LENGTH}d" % c end
def _between(b)
return "" if b == :total
"(r" << [SINCE_REV, LATEST_REL_REVS[b]].join(':') << ")"
end
output = commits.to_a.unshift([:total, total])
output.each do |(branch, count)|
puts "#### #{branch} #{_between(branch)}"
print "\n"
count.each.with_index(1) do |(a, c), idx|
puts " * #{_rank(idx)}: #{_author(a)} #{_count(c)}"
end
print "\n"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment