## USAGE:
#
# require 'svn_user_log'
#
# log = SvnUserLog.new('http://svn.mydomain.com/',
# :project => 'Kickass',
# :changeset_uri => 'http://trac.mydomain.com/changeset/',
# :rev_start => "{#{1.day.ago.to_date}}",
# :feed_root => '/www/some_app/public/feeds/')
# log.write_all_feeds
#
require 'rubygems'
require 'hpricot'
require 'active_support'
require 'cgi'
require 'rss/maker'
class SvnUserLog
def initialize(uri, options = {})
@uri = uri
@feed_root = (options[:feed_root] || '.').sub(/\/$/, '')
@changeset_uri = (options[:changeset_uri] || @uri)
@project = options[:project]
@rev_start = options[:rev_start]
@logs = {}
end
def log
# return File.read('c')
return @log if @log
@rev_start ||= "{#{1.day.ago.to_date}}"
command = "svn log -v -r #{@rev_start}:HEAD #{@uri} --xml"
puts command
svn_output = `#{command}`
# File.open('c', 'w') {|f| f.write(svn_output)}
@log = svn_output
end
def users
log_entries.collect {|el| (el/"author").first.innerText}.uniq
end
def write_all_feeds
users.each do |user|
write_feed_for(user)
end
end
def write_feed_for(user)
File.open(feed_filename_for(user), 'w') do |f|
f.write(feed_for(user))
end
end
def feed_filename_for(user)
prefix = @project ? "#{@project}_" : ''
"#{File.dirname(@feed_root)}/#{prefix}svn_changes_by_#{user}.xml"
end
def entries_for(user)
@entries ||= {}
return @entries[user] if @entries[user]
@entries[user] = log_entries.select do |el|
(el/"author").first.innerText.eql?(user.to_s)
end
end
def feed_for(user)
entries = entries_for(user)
RSS::Maker.make("1.0") do |rss|
rss.channel.about = "#{(@project || @uri)} changes by #{user}"
rss.channel.title = "#{(@project || @uri)} changes by #{user}"
rss.channel.link = "#{@uri}?user=#{user}"
rss.channel.description = "Svn updates #{user ? "from #{user}" : ''}"
entries.each do |entry|
if entry.attributes["revision"]
item = rss.items.new_item
item.date = entry.at('date').innerText
item.author = entry.at('author').innerText
item.link = "#{@changeset_uri}#{entry.attributes["revision"]}"
item.title = "Changeset ##{entry.attributes["revision"]} by #{(entry.at "author").innerText}"
content = []
content << entry.at('msg').innerText
content << ''
content << 'Files Modified:'
(entry/"paths/path").collect do |path|
content << "#{path.innerText}"
end
content << ''
content << "Committed at: #{Date.parse(item.date).strftime("%Y-%m-%d %I:%M%p %Z")}"
item.description = content.join("
")
end
end
end
end
def log_entries
(Hpricot.XML(log)/"logentry").reverse
end
end