Skip to content

Instantly share code, notes, and snippets.

@atiw003
Forked from tiegz/git-line-count.rb
Created August 18, 2010 09:28
Show Gist options
  • Save atiw003/534147 to your computer and use it in GitHub Desktop.
Save atiw003/534147 to your computer and use it in GitHub Desktop.
# 1) Put this file in your working directory
# 2) run 'sudo gem install active_support grit'
# 3) run 'ruby git-line-count.rb'
# 4) run 'open loc.html'
# 5) yay
require 'rubygems'
require 'active_support'
require 'grit'
require 'open-uri'
require 'fileutils'
include Grit
repo = Repo.new(".")
MAX_COMMITS = 1_000_000
OUTPUT_FILE = "loc.html"
FILE_EXTENSION = /\.js$/
EXCLUDED_FILES = %w(files.js to.js exclude.js).map { |str| Regexp.escape(str) }.join('|')
EXCLUDED = /#{EXCLUDED_FILES}/i
PER_DAY = true # true = show 1-commit-per-day, false = show all commits
TITLE = "'#{repo.head.name}' branch JavaScript LOC #{PER_DAY ? 'per day' : 'per commit'}"
commits_with_loc = []
total_count = 0 # gets reset every commit
current_date = nil # gets reset every commit
recursive_loc_count = lambda do |tree_or_blob|
if tree_or_blob.is_a?(Grit::Tree)
# A directory
tree_or_blob.contents.each(&recursive_loc_count)
elsif tree_or_blob.is_a?(Grit::Blob) \
&& tree_or_blob.name =~ FILE_EXTENSION \
&& tree_or_blob.name !~ EXCLUDED
# A matched file
total_count += tree_or_blob.data.select { |line| line !~ /^[\n\s\r]*$/ }.count
else
# A non-matched file.
end
end
# puts repo.commits[0].methods.sort.join(', ')
repo.commits('master', MAX_COMMITS).each do |commit|
total_count = 0
this_date = commit.committed_date.to_date
if !PER_DAY || (PER_DAY && this_date != current_date)
# Record this commit as end-of-day commit
current_date = this_date
commit.tree.contents.each(&recursive_loc_count)
commits_with_loc << {
:date => commit.committed_date.to_datetime.strftime("%-m/%-d/%y"),
:id => commit.id,
:loc => total_count
}
else
# The day this commits falls on has already been recorded
end
end
mod = (commits_with_loc.size / 5).round
commits_with_loc.reverse!
html = %Q!
<\!doctype html>
<html>
<head>
<title>LOC Visualization</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css" media="screen">
/* http://raphaeljs.com/demo.css */
body {
background: #000;
color: #fff;
font: 300 100.1% "Helvetica Neue", Helvetica, "Arial Unicode MS", Arial, sans-serif;
}
#holder {
height: 480px;
left: 50%;
margin: -240px 0 0 -320px;
position: absolute;
top: 50%;
width: 800px;
}
#copy {
bottom: 0;
font: 300 .7em "Helvetica Neue", Helvetica, "Arial Unicode MS", Arial, sans-serif;
position: absolute;
right: 1em;
text-align: right;
}
#copy a {
color: #fff;
}
</style>
<script type="text/javascript" charset="utf-8">
/* raphael.js */
#{open('http://github.com/DmitryBaranovskiy/raphael/raw/master/raphael.js').read}
/* raphael.path.methods.js */
#{open('http://github.com/DmitryBaranovskiy/raphael/raw/master/plugins/raphael.path.methods.js').read}
/* jquery.js */
#{open('http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js').read}
/* raphael.js */
#{open('http://raphaeljs.com/analytics.js').read.gsub('"" : "s"', '"" : ""').gsub('height = 250', 'height = 400').gsub('Y * data[i]', 'Y * parseInt(data[i])').gsub('hit', 'LOC').gsub('dot.attr("r", 5);', 'dot.attr("r", 0);').gsub('r.circle(x, y, 5)', 'r.circle(x, y, 0)').gsub('{text: lbl + " September 2008"}', '{text: lbl}')}
</script>
</head>
<body>
<h1 style="text-align: center;">#{TITLE}</h1>
<table id="data">
<tfoot>
<tr>!
commits_with_loc.each_with_index do |commit, index|
html << %Q!
<th>#{commit[:date] if index % mod == 0 || index == commits_with_loc.size - 1}</th>!
end
html << %Q!
</tr>
</tfoot>
<tbody>
<tr>
!
commits_with_loc.each_with_index do |commit, index|
html << %Q!
<td>#{commit[:loc]}</td>!
end
html << %Q!</tr>
</tbody>
</table>
<div id="holder"></div>
<p id="copy">Git LOC-per-commit visualization by @tiegz using <a href="http://grit.rubyforge.org/">grit.rb</a> & <a href="http://raphaeljs.com/">Raphaël</a>—JavaScript Vector Library</p>
</body>
</html>
!
FileUtils.rm_f(OUTPUT_FILE)
f = File.open(OUTPUT_FILE, 'w').write(html)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment