Snippet - svn_grep.rb

Rails and SVN aficionados:

My colleague wrote a lite Ruby wrapper on SVN --xml that helps those
of us getting on in years grep our log for some bygone code.

The result is completely brute force, and does not exclude log entries
that didn't change the grepped lines. This provides an added benefit -
you don't need to pipe | less to slow the output down!

The code also comes with a prototypical unit test illustrating
stubbing out the actual SVN call, and illustrating some of SVN's
sample XML output.

···

--
Phlip

#!/usr/bin/env ruby
require 'optparse'
require 'rexml/document'

module SvnGrepModule
class SvnGrepper

   def initialize(dir)
     @svn = dir
   end

   def find(regex)
     @found_revisions = []
     regex = /#{regex}/
     revisions.each do |revision|
       found = %x[svn cat -r#{revision} #{@svn}].grep(regex)
       if found.length > 0
         puts "#{revision}: #{found}"
         @found_revisions << revision
       end
     end
   end

   def revisions
     doc = xml('log --xml')
     log_entries = REXML::XPath.match(doc, '//logentry')
     return log_entries.collect{ |log| log.attributes['revision'] }
   end

   def xml(command)
     REXML::Document.new(%x[svn #{command} #{@svn}])
   end

   def current_revision
     doc = xml('info --xml')
     @current_revision = REXML::XPath.first(doc, '/info/entry/@revision').value
   end

end
end

if ARGV.include?('test')

require 'test/unit'
require 'rubygems'
require 'mocha'
include SvnGrepModule

class SvnGrepperTest < Test::Unit::TestCase

   def test_svn_grepper
     svn = SvnGrepper.new('/home/wrecker/projects/ibenwrkinondarailroad/config/environment.rb')

     svn.expects(:xml).returns REXML::Document.new("<?xml version='1.0'?>
       <info>
         <entry
             kind='file'
             revision='42'
             path='/home/wrecker/projects/ibenwrkinondarailroad/config/environment.rb'>
           <url>svn://repo/ibenwrkinondarailroad/config/environment.rb</url>
           <repository>
             <root>svn://repo</root>
             <uuid>6f9af763-49f8-0310-a517-bcf8306575d7</uuid>
           </repository>
           <wc-info>
             <schedule>normal</schedule>
             <text-updated>2007-07-19T17:54:02.000000Z</text-updated>
             <checksum>84ed977b7c0185aa70969675781e3d92</checksum>
           </wc-info>
           <commit revision='8902'>
             <author>wrecker</author>
             <date>2007-07-19T18:09:31.817664Z</date>
           </commit>
         </entry>
       </info>")

     assert_kind_of SvnGrepper, svn
     assert_equal '42', svn.current_revision

     svn.expects(:xml).returns REXML::Document.new('<?xml version="1.0"?>
       <log>
       <logentry
          revision="8902">
       <author>wrecker</author>
       <date>2007-07-20T18:09:31.817663Z</date>
       <msg>refactor thingy</msg>
       </logentry>
       <logentry
          revision="8786">
       <author>wrecker</author>
       <date>2007-09-20T16:17:07.292212Z</date>
       <msg>added test for daily_count</msg>
       </logentry>
       <logentry
          revision="8730">
       <author>wrecker</author>
       <date>2007-09-19T20:25:47.765465Z</date>
       <msg>refact-AAARRRR</msg>
       </logentry>
       <logentry
          revision="8711">
       <author>wrecker</author>
       <date>2007-07-11T15:08:20.585929Z</date>
       <msg>Adding yummy COUNTRY_HASH</msg>
       </logentry>')

     assert_equal 4, svn.revisions.length
     # svn.find('DEBUG_LOGGER')
   end

end

else

include SvnGrepModule
svn_dir = ARGV.shift
look_for = ARGV.shift
if File.directory?(svn_dir)
   # TODO if it is a directory, recursively look at the files
else
   SvnGrepper.new(svn_dir).find(look_for)
end

end