Skip to content

Instantly share code, notes, and snippets.

@tobinharris
Created February 8, 2009 18:01
Show Gist options
  • Save tobinharris/60442 to your computer and use it in GitHub Desktop.
Save tobinharris/60442 to your computer and use it in GitHub Desktop.
# SVN Sparkline
#
# By Tobin Harris (http://www.tobinharris.com)
#
#
# Project to generate an activity sparkline for an public SVN repository.
#
# Outputs a *javascript snippet* that can be included in a HTML document.
#
# Usage:
# ruby svn_analyze.rb [Project Name] [SVN public repo]
#
# Eg:
# ruby svn_analyze.rb "NHibernate" http://nhibernate.svn.sourceforge.net/svnroot/nhibernate > /htdocs/widget.js
#
# Once you've output the widget, you can include it in your Javascript like this
#
# <p>Here is a sparkline: <script src="widget.js"></script>, nice huh!</p>
#
require 'rexml/document'
require 'date'
#puts ARGV.inspect
# svn log --limit 10 --xml https://nhibernate.svn.sourceforge.net/svnroot/nhibernate
test = false || ARGV.include?("--test")
ARGV.delete("--test")
project = ARGV[0] || "NHibernate"
repo = ARGV[1] || "http://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk"
test_repo = "example_log.xml"
cmd = "svn log --limit 200 --xml "
xml = ""
def seconds_to_human_interval(secs)
secs = secs * -1 if secs < 0
minute = 60
hour = minute * 60
day = hour * 24
week = day * 7
month = week * 4
year = month * 12
times = [
{:minute => minute},
{:hour => hour},
{:day => day},
{:week => week},
{:month => month},
{:year => year}
]
times.reverse.each do |el|
return secs / el.values[0].to_i, el.keys[0].to_s if secs >= el.values[0].to_i
end
return secs, "second"
end
class LogEntry
attr_accessor :author
attr_accessor :date
attr_accessor :notes
end
sparkline_template = %Q{document.write("<img src='http://chart.apis.google.com/chart?\
cht=ls\
&chs=30x15\
&chd=t:DATA\
&chds=0,20\
&chls=2\
' onclick='alert(\\"TEXT\\")'>");
}
if not test then
IO.popen("#{cmd}#{repo}") do |out|
xml = out.readlines.to_s
end
else
xml = IO.read("example_log.xml")
end
entries = Array.new
authors = Array.new
dates = Array.new
doc = REXML::Document.new(xml)
doc.elements.each('log/logentry') do |entry|
e = LogEntry.new
e.author = entry.elements['author'].text
e.date = Time::mktime(entry.elements['date'].text[0..3].to_i, entry.elements['date'].text[5..6].to_i, entry.elements['date'].text[8..9].to_i)
e.notes = entry.elements['msg'].text
entries << e
end
authors = entries.collect{|e| e.author}
data = seconds_to_human_interval(Time.new - entries.first.date)
end_data = seconds_to_human_interval(Time.new - entries.last.date)
txt = "The #{project} code base was last updated by #{entries.first.author} #{data[0].round} #{data[1]}s ago"
txt = txt + ". #{entries.length} updates by #{authors.uniq.join(', ')} in the last #{end_data[0].round} #{end_data[1]}s"
puts "// nhibernate_stats.js"
#daily data points for last 3 days, count of updates per day
data_points = Array.new
(-7..0).each do |ago|
to_match = (Time.new - 60*60*24*ago*-1).strftime('%Y-%m-%d')
found = entries.select{|e| e.date.strftime('%Y-%m-%d') == to_match}
#puts "#{to_match}, #{found.length}"
data_points << found.length
end
puts
puts sparkline_template.sub(/DATA/, data_points.join(",")).sub(/TEXT/,txt)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment