diff --git a/lib/redmine/scm/adapters/subversion_adapter.rb b/lib/redmine/scm/adapters/subversion_adapter.rb index a0a07f8..e57efb4 100644 --- a/lib/redmine/scm/adapters/subversion_adapter.rb +++ b/lib/redmine/scm/adapters/subversion_adapter.rb @@ -235,19 +235,35 @@ module Redmine def annotate(path, identifier=nil) identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD" - cmd = "#{self.class.sq_bin} blame #{target(path)}@#{identifier}" + cmd = "#{self.class.sq_bin} cat #{target(path)}@#{identifier}" + cmd << credentials_string + cat = nil + shellout(cmd) do |io| + io.binmode + cat = io.read + end + return nil if $? && $?.exitstatus != 0 + lines = cat.split(/\n|\r\n/) + cmd = "#{self.class.sq_bin} blame --xml #{target(path)}@#{identifier}" cmd << credentials_string blame = Annotate.new shellout(cmd) do |io| - io.each_line do |line| - next unless line =~ %r{^\s*(\d+)\s*(\S+)\s(.*)$} - rev = $1 - blame.add_line($3.rstrip, - Revision.new( - :identifier => rev, - :revision => rev, - :author => $2.strip - )) + output = io.read + if output.respond_to?(:force_encoding) + output.force_encoding('UTF-8') + end + begin + doc = ActiveSupport::XmlMini.parse(output) + each_xml_element(doc['blame']['target'], 'entry') do |entry| + line = lines[entry['line-number'].to_i + 1] + blame.add_line(line, + Revision.new( + :identifier => entry['commit']['revision'], + :revision => entry['commit']['revision'], + :author => entry['commit']['author']['__content__'] + )) + end + rescue end end return nil if $? && $?.exitstatus != 0