## 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