]> source.dussan.org Git - redmine.git/commitdiff
Changes SubversionAdapter to use ActiveSupport::XmlMini API for XML parsing.
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 13 Feb 2010 13:58:05 +0000 (13:58 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sat, 13 Feb 2010 13:58:05 +0000 (13:58 +0000)
This allows easy switching to one of the faster XML parsers supported by XmlMini (eg. libxml-ruby).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3424 e93f8b46-1217-0410-a6f0-8f06a7374b81

lib/redmine/scm/adapters/subversion_adapter.rb

index dccb39fe6ea750e3ba003a5d04372f4a2b621539..73814f9398c0d124c96d0c960ce0191e80e91f0b 100644 (file)
@@ -1,5 +1,5 @@
-# redMine - project management software\r
-# Copyright (C) 2006-2007  Jean-Philippe Lang\r
+# Redmine - project management software\r
+# Copyright (C) 2006-2010  Jean-Philippe Lang\r
 #\r
 # This program is free software; you can redistribute it and/or\r
 # modify it under the terms of the GNU General Public License\r
@@ -16,7 +16,6 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
 \r
 require 'redmine/scm/adapters/abstract_adapter'\r
-require 'rexml/document'\r
 require 'uri'\r
 \r
 module Redmine\r
@@ -52,14 +51,15 @@ module Redmine
           cmd << credentials_string\r
           info = nil\r
           shellout(cmd) do |io|\r
+            output = io.read\r
             begin\r
-              doc = REXML::Document.new(io)\r
+              doc = ActiveSupport::XmlMini.parse(output)\r
               #root_url = doc.elements["info/entry/repository/root"].text          \r
-              info = Info.new({:root_url => doc.elements["info/entry/repository/root"].text,\r
+              info = Info.new({:root_url => doc['info']['entry']['repository']['root']['__content__'],\r
                                :lastrev => Revision.new({\r
-                                 :identifier => doc.elements["info/entry/commit"].attributes['revision'],\r
-                                 :time => Time.parse(doc.elements["info/entry/commit/date"].text).localtime,\r
-                                 :author => (doc.elements["info/entry/commit/author"] ? doc.elements["info/entry/commit/author"].text : "")\r
+                                 :identifier => doc['info']['entry']['commit']['revision'],\r
+                                 :time => Time.parse(doc['info']['entry']['commit']['date']['__content__']).localtime,\r
+                                 :author => (doc['info']['entry']['commit']['author'] ? doc['info']['entry']['commit']['author']['__content__'] : "")\r
                                })\r
                              })\r
             rescue\r
@@ -82,22 +82,22 @@ module Redmine
           shellout(cmd) do |io|\r
             output = io.read\r
             begin\r
-              doc = REXML::Document.new(output)\r
-              doc.elements.each("lists/list/entry") do |entry|\r
-                commit = entry.elements['commit']\r
-                commit_date = commit.elements['date']\r
+              doc = ActiveSupport::XmlMini.parse(output)\r
+              each_xml_element(doc['lists']['list'], 'entry') do |entry|\r
+                commit = entry['commit']\r
+                commit_date = commit['date']\r
                 # Skip directory if there is no commit date (usually that\r
                 # means that we don't have read access to it)\r
-                next if entry.attributes['kind'] == 'dir' && commit_date.nil?\r
-                name = entry.elements['name'].text\r
+                next if entry['kind'] == 'dir' && commit_date.nil?\r
+                name = entry['name']['__content__']\r
                 entries << Entry.new({:name => URI.unescape(name),\r
                             :path => ((path.empty? ? "" : "#{path}/") + name),\r
-                            :kind => entry.attributes['kind'],\r
-                            :size => ((s = entry.elements['size']) ? s.text.to_i : nil),\r
+                            :kind => entry['kind'],\r
+                            :size => ((s = entry['size']) ? s['__content__'].to_i : nil),\r
                             :lastrev => Revision.new({\r
-                              :identifier => commit.attributes['revision'],\r
-                              :time => Time.parse(commit_date.text).localtime,\r
-                              :author => ((a = commit.elements['author']) ? a.text : nil)\r
+                              :identifier => commit['revision'],\r
+                              :time => Time.parse(commit_date['__content__'].to_s).localtime,\r
+                              :author => ((a = commit['author']) ? a['__content__'] : nil)\r
                               })\r
                             })\r
               end\r
@@ -122,9 +122,9 @@ module Redmine
           shellout(cmd) do |io|\r
             output = io.read\r
             begin\r
-              doc = REXML::Document.new(output)\r
-              doc.elements.each("properties/target/property") do |property|\r
-                properties[ property.attributes['name'] ] = property.text\r
+              doc = ActiveSupport::XmlMini.parse(output)\r
+              each_xml_element(doc['properties']['target'], 'property') do |property|\r
+                properties[ property['name'] ] = property['__content__'].to_s\r
               end\r
             rescue\r
             end\r
@@ -144,23 +144,24 @@ module Redmine
           cmd << " --limit #{options[:limit].to_i}" if options[:limit]\r
           cmd << ' ' + target(URI.escape(path))\r
           shellout(cmd) do |io|\r
+            output = io.read\r
             begin\r
-              doc = REXML::Document.new(io)\r
-              doc.elements.each("log/logentry") do |logentry|\r
+              doc = ActiveSupport::XmlMini.parse(output)\r
+              each_xml_element(doc['log'], 'logentry') do |logentry|\r
                 paths = []\r
-                logentry.elements.each("paths/path") do |path|\r
-                  paths << {:action => path.attributes['action'],\r
-                            :path => path.text,\r
-                            :from_path => path.attributes['copyfrom-path'],\r
-                            :from_revision => path.attributes['copyfrom-rev']\r
+                each_xml_element(logentry['paths'], 'path') do |path|\r
+                  paths << {:action => path['action'],\r
+                            :path => path['__content__'],\r
+                            :from_path => path['copyfrom-path'],\r
+                            :from_revision => path['copyfrom-rev']\r
                             }\r
-                end\r
+                end if logentry['paths'] && logentry['paths']['path']\r
                 paths.sort! { |x,y| x[:path] <=> y[:path] }\r
                 \r
-                revisions << Revision.new({:identifier => logentry.attributes['revision'],\r
-                              :author => (logentry.elements['author'] ? logentry.elements['author'].text : ""),\r
-                              :time => Time.parse(logentry.elements['date'].text).localtime,\r
-                              :message => logentry.elements['msg'].text,\r
+                revisions << Revision.new({:identifier => logentry['revision'],\r
+                              :author => (logentry['author'] ? logentry['author']['__content__'] : ""),\r
+                              :time => Time.parse(logentry['date']['__content__'].to_s).localtime,\r
+                              :message => logentry['msg']['__content__'],\r
                               :paths => paths\r
                             })\r
               end\r
@@ -228,6 +229,20 @@ module Redmine
           str << " --no-auth-cache --non-interactive"\r
           str\r
         end\r
+        \r
+        # Helper that iterates over the child elements of a xml node\r
+        # MiniXml returns a hash when a single child is found or an array of hashes for multiple children\r
+        def each_xml_element(node, name)\r
+          if node && node[name]\r
+            if node[name].is_a?(Hash)\r
+              yield node[name]\r
+            else\r
+              node[name].each do |element|\r
+                yield element\r
+              end\r
+            end\r
+          end\r
+        end\r
       end\r
     end\r
   end\r