comparison lib/redmine/scm/adapters/darcs_adapter.rb @ 245:051f544170fe

* Update to SVN trunk revision 4993
author Chris Cannam
date Thu, 03 Mar 2011 11:42:28 +0000
parents 0579821a129a
children cbce1fd3b1b7
comparison
equal deleted inserted replaced
244:8972b600f4fb 245:051f544170fe
18 require 'redmine/scm/adapters/abstract_adapter' 18 require 'redmine/scm/adapters/abstract_adapter'
19 require 'rexml/document' 19 require 'rexml/document'
20 20
21 module Redmine 21 module Redmine
22 module Scm 22 module Scm
23 module Adapters 23 module Adapters
24 class DarcsAdapter < AbstractAdapter 24 class DarcsAdapter < AbstractAdapter
25 # Darcs executable name 25 # Darcs executable name
26 DARCS_BIN = Redmine::Configuration['scm_darcs_command'] || "darcs" 26 DARCS_BIN = Redmine::Configuration['scm_darcs_command'] || "darcs"
27 27
28 class << self 28 class << self
29 def client_command
30 @@bin ||= DARCS_BIN
31 end
32
33 def sq_bin
34 @@sq_bin ||= shell_quote(DARCS_BIN)
35 end
36
29 def client_version 37 def client_version
30 @@client_version ||= (darcs_binary_version || []) 38 @@client_version ||= (darcs_binary_version || [])
31 end 39 end
32 40
41 def client_available
42 !client_version.empty?
43 end
44
33 def darcs_binary_version 45 def darcs_binary_version
34 darcsversion = darcs_binary_version_from_command_line 46 darcsversion = darcs_binary_version_from_command_line.dup
47 if darcsversion.respond_to?(:force_encoding)
48 darcsversion.force_encoding('ASCII-8BIT')
49 end
35 if m = darcsversion.match(%r{\A(.*?)((\d+\.)+\d+)}) 50 if m = darcsversion.match(%r{\A(.*?)((\d+\.)+\d+)})
36 m[2].scan(%r{\d+}).collect(&:to_i) 51 m[2].scan(%r{\d+}).collect(&:to_i)
37 end 52 end
38 end 53 end
39 54
40 def darcs_binary_version_from_command_line 55 def darcs_binary_version_from_command_line
41 shellout("#{DARCS_BIN} --version") { |io| io.read }.to_s 56 shellout("#{sq_bin} --version") { |io| io.read }.to_s
42 end 57 end
43 end 58 end
44 59
45 def initialize(url, root_url=nil, login=nil, password=nil) 60 def initialize(url, root_url=nil, login=nil, password=nil,
61 path_encoding=nil)
46 @url = url 62 @url = url
47 @root_url = url 63 @root_url = url
48 end 64 end
49 65
50 def supports_cat? 66 def supports_cat?
55 # Get info about the darcs repository 71 # Get info about the darcs repository
56 def info 72 def info
57 rev = revisions(nil,nil,nil,{:limit => 1}) 73 rev = revisions(nil,nil,nil,{:limit => 1})
58 rev ? Info.new({:root_url => @url, :lastrev => rev.last}) : nil 74 rev ? Info.new({:root_url => @url, :lastrev => rev.last}) : nil
59 end 75 end
60 76
61 # Returns an Entries collection 77 # Returns an Entries collection
62 # or nil if the given path doesn't exist in the repository 78 # or nil if the given path doesn't exist in the repository
63 def entries(path=nil, identifier=nil) 79 def entries(path=nil, identifier=nil)
64 path_prefix = (path.blank? ? '' : "#{path}/") 80 path_prefix = (path.blank? ? '' : "#{path}/")
65 if path.blank? 81 if path.blank?
66 path = ( self.class.client_version_above?([2, 2, 0]) ? @url : '.' ) 82 path = ( self.class.client_version_above?([2, 2, 0]) ? @url : '.' )
67 end 83 end
68 entries = Entries.new 84 entries = Entries.new
69 cmd = "#{DARCS_BIN} annotate --repodir #{shell_quote @url} --xml-output" 85 cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --xml-output"
70 cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier 86 cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier
71 cmd << " #{shell_quote path}" 87 cmd << " #{shell_quote path}"
72 shellout(cmd) do |io| 88 shellout(cmd) do |io|
73 begin 89 begin
74 doc = REXML::Document.new(io) 90 doc = REXML::Document.new(io)
84 end 100 end
85 end 101 end
86 return nil if $? && $?.exitstatus != 0 102 return nil if $? && $?.exitstatus != 0
87 entries.compact.sort_by_name 103 entries.compact.sort_by_name
88 end 104 end
89 105
90 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}) 106 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
91 path = '.' if path.blank? 107 path = '.' if path.blank?
92 revisions = Revisions.new 108 revisions = Revisions.new
93 cmd = "#{DARCS_BIN} changes --repodir #{shell_quote @url} --xml-output" 109 cmd = "#{self.class.sq_bin} changes --repodir #{shell_quote @url} --xml-output"
94 cmd << " --from-match #{shell_quote("hash #{identifier_from}")}" if identifier_from 110 cmd << " --from-match #{shell_quote("hash #{identifier_from}")}" if identifier_from
95 cmd << " --last #{options[:limit].to_i}" if options[:limit] 111 cmd << " --last #{options[:limit].to_i}" if options[:limit]
96 shellout(cmd) do |io| 112 shellout(cmd) do |io|
97 begin 113 begin
98 doc = REXML::Document.new(io) 114 doc = REXML::Document.new(io)
111 end 127 end
112 end 128 end
113 return nil if $? && $?.exitstatus != 0 129 return nil if $? && $?.exitstatus != 0
114 revisions 130 revisions
115 end 131 end
116 132
117 def diff(path, identifier_from, identifier_to=nil) 133 def diff(path, identifier_from, identifier_to=nil)
118 path = '*' if path.blank? 134 path = '*' if path.blank?
119 cmd = "#{DARCS_BIN} diff --repodir #{shell_quote @url}" 135 cmd = "#{self.class.sq_bin} diff --repodir #{shell_quote @url}"
120 if identifier_to.nil? 136 if identifier_to.nil?
121 cmd << " --match #{shell_quote("hash #{identifier_from}")}" 137 cmd << " --match #{shell_quote("hash #{identifier_from}")}"
122 else 138 else
123 cmd << " --to-match #{shell_quote("hash #{identifier_from}")}" 139 cmd << " --to-match #{shell_quote("hash #{identifier_from}")}"
124 cmd << " --from-match #{shell_quote("hash #{identifier_to}")}" 140 cmd << " --from-match #{shell_quote("hash #{identifier_to}")}"
131 end 147 end
132 end 148 end
133 return nil if $? && $?.exitstatus != 0 149 return nil if $? && $?.exitstatus != 0
134 diff 150 diff
135 end 151 end
136 152
137 def cat(path, identifier=nil) 153 def cat(path, identifier=nil)
138 cmd = "#{DARCS_BIN} show content --repodir #{shell_quote @url}" 154 cmd = "#{self.class.sq_bin} show content --repodir #{shell_quote @url}"
139 cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier 155 cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier
140 cmd << " #{shell_quote path}" 156 cmd << " #{shell_quote path}"
141 cat = nil 157 cat = nil
142 shellout(cmd) do |io| 158 shellout(cmd) do |io|
143 io.binmode 159 io.binmode
146 return nil if $? && $?.exitstatus != 0 162 return nil if $? && $?.exitstatus != 0
147 cat 163 cat
148 end 164 end
149 165
150 private 166 private
151 167
152 # Returns an Entry from the given XML element 168 # Returns an Entry from the given XML element
153 # or nil if the entry was deleted 169 # or nil if the entry was deleted
154 def entry_from_xml(element, path_prefix) 170 def entry_from_xml(element, path_prefix)
155 modified_element = element.elements['modified'] 171 modified_element = element.elements['modified']
156 if modified_element.elements['modified_how'].text.match(/removed/) 172 if modified_element.elements['modified_how'].text.match(/removed/)
157 return nil 173 return nil
158 end 174 end
159 175
160 Entry.new({:name => element.attributes['name'], 176 Entry.new({:name => element.attributes['name'],
161 :path => path_prefix + element.attributes['name'], 177 :path => path_prefix + element.attributes['name'],
162 :kind => element.name == 'file' ? 'file' : 'dir', 178 :kind => element.name == 'file' ? 'file' : 'dir',
163 :size => nil, 179 :size => nil,
164 :lastrev => Revision.new({ 180 :lastrev => Revision.new({
165 :identifier => nil, 181 :identifier => nil,
166 :scmid => modified_element.elements['patch'].attributes['hash'] 182 :scmid => modified_element.elements['patch'].attributes['hash']
167 }) 183 })
168 }) 184 })
169 end 185 end
170 186
171 def get_paths_for_patch(hash) 187 def get_paths_for_patch(hash)
172 paths = get_paths_for_patch_raw(hash) 188 paths = get_paths_for_patch_raw(hash)
173 if self.class.client_version_above?([2, 4]) 189 if self.class.client_version_above?([2, 4])
194 paths.concat mod_paths 210 paths.concat mod_paths
195 paths.concat other_paths 211 paths.concat other_paths
196 end 212 end
197 paths 213 paths
198 end 214 end
199 215
200 # Retrieve changed paths for a single patch 216 # Retrieve changed paths for a single patch
201 def get_paths_for_patch_raw(hash) 217 def get_paths_for_patch_raw(hash)
202 cmd = "#{DARCS_BIN} annotate --repodir #{shell_quote @url} --summary --xml-output" 218 cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --summary --xml-output"
203 cmd << " --match #{shell_quote("hash #{hash}")} " 219 cmd << " --match #{shell_quote("hash #{hash}")} "
204 paths = [] 220 paths = []
205 shellout(cmd) do |io| 221 shellout(cmd) do |io|
206 begin 222 begin
207 # Darcs xml output has multiple root elements in this case (tested with darcs 1.0.7) 223 # Darcs xml output has multiple root elements in this case (tested with darcs 1.0.7)