P
Phlip
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:ocument.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.expectsxml).returns REXML:ocument.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.expectsxml).returns REXML:ocument.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
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:ocument.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.expectsxml).returns REXML:ocument.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.expectsxml).returns REXML:ocument.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