class VCLog::Adapters::Svn

SVN Adapter.

NOTE: Unfortunately the SVN adapater is very slow. If hits the server every time the ‘svn log’ command is issued. When generating a History that’s two hits for every tag. If anyone knows a better way please have at it –maybe future versions of SVN will improve the situation.

Public Class Methods

new(root) click to toggle source
Calls superclass method VCLog::Adapters::Abstract::new
# File lib/vclog/adapters/svn.rb, line 16
def initialize(root)
  begin
    require 'xmlsimple'
  rescue LoadError
    raise LoadError, "VCLog requires xml-simple for SVN support."
  end
  super(root)
end

Public Instance Methods

email() click to toggle source

TODO: Best solution to SVN email?

# File lib/vclog/adapters/svn.rb, line 119
def email
  @email ||= ENV['EMAIL']
end
extract_changes() click to toggle source

Extract changes.

# File lib/vclog/adapters/svn.rb, line 26
def extract_changes
  log = []

  xml = `svn log -v --xml`.strip

  commits = XmlSimple.xml_in(xml, {'KeyAttr' => 'rev'})
  commits = commits['logentry']

  commits.each do |com|
    rev  = com['revision']
    msg  = [com['msg']].flatten.compact.join('').strip
    who  = [com['author']].flatten.compact.join('').strip
    date = [com['date']].flatten.compact.join('').strip

    files = com['paths'].map{ |h| h['path'].map{ |y| y['content'] } }.flatten

    next if msg.empty?
    next if msg == "*** empty log message ***"

    date = Time.parse(date)

    log << Change.new(:id=>rev, :date=>date, :who=>who, :msg=>msg, :files=>files)
  end

  log
end
extract_tags() click to toggle source

Extract tags.

# File lib/vclog/adapters/svn.rb, line 54
def extract_tags
  list = []
  tagdir = tag_directory

  if tagdir
    tags = Dir.entries(tagdir).select{ |e| e.index('.') != 0 && e =~ /\d(.*)$/ }
  else
    tags = []
  end

  tags.each do |path|
    dir = File.join(tagdir, path)

    # using yaml, but maybe use xml instead?
    info = `svn info #{dir}`
    info = YAML.load(info)
    md = /(\d.*)$/.match(info['Path'])
    name = md ? md[1] : path
    date = info['Last Changed Date']
    who  = info['Last Changed Author']
    rev  = info['Revision']

    # get last commit
    xml = `svn log -l1 --xml #{dir}`
    commits = XmlSimple.xml_in(xml, {'KeyAttr' => 'rev'})
    commit = commits['logentry'].first

    msg  = [commit["msg"]].flatten.compact.join('').strip
    date = [commit["date"]].flatten.compact.join('').strip

    list << Tag.new(:name=>name, :id=>rev, :date=>date, :who=>who, :msg=>msg)
  end
  list
end
repository() click to toggle source
# File lib/vclog/adapters/svn.rb, line 124
def repository
  info['Repository Root']
end
tag(ref, label, date, message) click to toggle source

TODO: Need to effect svn tag date. How?

# File lib/vclog/adapters/svn.rb, line 134
def tag(ref, label, date, message)
  file = tempfile("message", message)

  Dir.chdir(root) do
    cmd = %[svn copy -r #{ref} -F "#{mfile.path}" . #{tag_directory}/#{label}]
    puts cmd if $DEBUG
    `#{cmd}` unless $DRYRUN
  end
end
tag_directory() click to toggle source

This isn’t perfect, but is there really anyway for it to be? It ascends up the current directory tree looking for the best candidate for a tags directory.

# File lib/vclog/adapters/svn.rb, line 92
def tag_directory
  fnd = nil
  dir = root
  while dir != '/' do
    entries = Dir.entries(dir)
    if entries.include?('.svn')
      if entries.include?('tags')
        break(fnd = File.join(dir, 'tags'))
      else
        entries = entries.reject{ |e| e.index('.') == 0 }
        entries = entries.reject{ |e| e !~ /\d$/ }
        break(fnd = dir) unless entries.empty?
      end
    else
      break(fnd=nil)
    end
    dir = File.dirname(dir)
  end
  fnd
end
user() click to toggle source
# File lib/vclog/adapters/svn.rb, line 114
def user
  @email ||= `svn propget svn:author`.strip
end
uuid() click to toggle source
# File lib/vclog/adapters/svn.rb, line 129
def uuid
  info['Repository UUID']
end

Private Instance Methods

info() click to toggle source
# File lib/vclog/adapters/svn.rb, line 147
def info
  @info ||= YAML.load(`svn info`.strip)
end