comparison lib/redmine/scm/adapters/.svn/text-base/abstract_adapter.rb.svn-base @ 245:051f544170fe

* Update to SVN trunk revision 4993
author Chris Cannam
date Thu, 03 Mar 2011 11:42:28 +0000
parents 8661b858af72
children cbce1fd3b1b7
comparison
equal deleted inserted replaced
244:8972b600f4fb 245:051f544170fe
17 17
18 require 'cgi' 18 require 'cgi'
19 19
20 module Redmine 20 module Redmine
21 module Scm 21 module Scm
22 module Adapters 22 module Adapters
23 class CommandFailed < StandardError #:nodoc: 23 class CommandFailed < StandardError #:nodoc:
24 end 24 end
25 25
26 class AbstractAdapter #:nodoc: 26 class AbstractAdapter #:nodoc:
27 class << self 27 class << self
28 def client_command
29 ""
30 end
31
28 # Returns the version of the scm client 32 # Returns the version of the scm client
29 # Eg: [1, 5, 0] or [] if unknown 33 # Eg: [1, 5, 0] or [] if unknown
30 def client_version 34 def client_version
31 [] 35 []
32 end 36 end
33 37
34 # Returns the version string of the scm client 38 # Returns the version string of the scm client
35 # Eg: '1.5.0' or 'Unknown version' if unknown 39 # Eg: '1.5.0' or 'Unknown version' if unknown
36 def client_version_string 40 def client_version_string
37 v = client_version || 'Unknown version' 41 v = client_version || 'Unknown version'
38 v.is_a?(Array) ? v.join('.') : v.to_s 42 v.is_a?(Array) ? v.join('.') : v.to_s
39 end 43 end
40 44
41 # Returns true if the current client version is above 45 # Returns true if the current client version is above
42 # or equals the given one 46 # or equals the given one
43 # If option is :unknown is set to true, it will return 47 # If option is :unknown is set to true, it will return
44 # true if the client version is unknown 48 # true if the client version is unknown
45 def client_version_above?(v, options={}) 49 def client_version_above?(v, options={})
46 ((client_version <=> v) >= 0) || (client_version.empty? && options[:unknown]) 50 ((client_version <=> v) >= 0) || (client_version.empty? && options[:unknown])
47 end 51 end
48 end 52
49 53 def client_available
50 def initialize(url, root_url=nil, login=nil, password=nil) 54 true
55 end
56
57 def shell_quote(str)
58 if Redmine::Platform.mswin?
59 '"' + str.gsub(/"/, '\\"') + '"'
60 else
61 "'" + str.gsub(/'/, "'\"'\"'") + "'"
62 end
63 end
64 end
65
66 def initialize(url, root_url=nil, login=nil, password=nil,
67 path_encoding=nil)
51 @url = url 68 @url = url
52 @login = login if login && !login.empty? 69 @login = login if login && !login.empty?
53 @password = (password || "") if @login 70 @password = (password || "") if @login
54 @root_url = root_url.blank? ? retrieve_root_url : root_url 71 @root_url = root_url.blank? ? retrieve_root_url : root_url
55 end 72 end
56 73
57 def adapter_name 74 def adapter_name
58 'Abstract' 75 'Abstract'
59 end 76 end
60 77
61 def supports_cat? 78 def supports_cat?
62 true 79 true
63 end 80 end
64 81
65 def supports_annotate? 82 def supports_annotate?
66 respond_to?('annotate') 83 respond_to?('annotate')
67 end 84 end
68 85
69 def root_url 86 def root_url
70 @root_url 87 @root_url
71 end 88 end
72 89
73 def url 90 def url
74 @url 91 @url
75 end 92 end
76 93
77 # get info about the svn repository 94 # get info about the svn repository
136 153
137 def with_trailling_slash(path) 154 def with_trailling_slash(path)
138 path ||= '' 155 path ||= ''
139 (path[-1,1] == "/") ? path : "#{path}/" 156 (path[-1,1] == "/") ? path : "#{path}/"
140 end 157 end
141 158
142 def without_leading_slash(path) 159 def without_leading_slash(path)
143 path ||= '' 160 path ||= ''
144 path.gsub(%r{^/+}, '') 161 path.gsub(%r{^/+}, '')
145 end 162 end
146 163
147 def without_trailling_slash(path) 164 def without_trailling_slash(path)
148 path ||= '' 165 path ||= ''
149 (path[-1,1] == "/") ? path[0..-2] : path 166 (path[-1,1] == "/") ? path[0..-2] : path
150 end 167 end
151 168
152 def shell_quote(str) 169 def shell_quote(str)
153 if Redmine::Platform.mswin? 170 self.class.shell_quote(str)
154 '"' + str.gsub(/"/, '\\"') + '"'
155 else
156 "'" + str.gsub(/'/, "'\"'\"'") + "'"
157 end
158 end 171 end
159 172
160 private 173 private
161 def retrieve_root_url 174 def retrieve_root_url
162 info = self.info 175 info = self.info
166 def target(path) 179 def target(path)
167 path ||= '' 180 path ||= ''
168 base = path.match(/^\//) ? root_url : url 181 base = path.match(/^\//) ? root_url : url
169 shell_quote("#{base}/#{path}".gsub(/[?<>\*]/, '')) 182 shell_quote("#{base}/#{path}".gsub(/[?<>\*]/, ''))
170 end 183 end
171 184
172 def logger 185 def logger
173 self.class.logger 186 self.class.logger
174 end 187 end
175 188
176 def shellout(cmd, &block) 189 def shellout(cmd, &block)
177 self.class.shellout(cmd, &block) 190 self.class.shellout(cmd, &block)
178 end 191 end
179 192
180 def self.logger 193 def self.logger
181 RAILS_DEFAULT_LOGGER 194 RAILS_DEFAULT_LOGGER
182 end 195 end
183 196
184 def self.shellout(cmd, &block) 197 def self.shellout(cmd, &block)
185 logger.debug "Shelling out: #{strip_credential(cmd)}" if logger && logger.debug? 198 logger.debug "Shelling out: #{strip_credential(cmd)}" if logger && logger.debug?
186 if Rails.env == 'development' 199 if Rails.env == 'development'
187 # Capture stderr when running in dev environment 200 # Capture stderr when running in dev environment
188 cmd = "#{cmd} 2>>#{RAILS_ROOT}/log/scm.stderr.log" 201 cmd = "#{cmd} 2>>#{RAILS_ROOT}/log/scm.stderr.log"
189 end 202 end
190 begin 203 begin
191 IO.popen(cmd, "r+") do |io| 204 if RUBY_VERSION < '1.9'
205 mode = "r+"
206 else
207 mode = "r+:ASCII-8BIT"
208 end
209 IO.popen(cmd, mode) do |io|
192 io.close_write 210 io.close_write
193 block.call(io) if block_given? 211 block.call(io) if block_given?
194 end 212 end
195 rescue Errno::ENOENT => e 213 rescue Errno::ENOENT => e
196 msg = strip_credential(e.message) 214 msg = strip_credential(e.message)
197 # The command failed, log it and re-raise 215 # The command failed, log it and re-raise
198 logger.error("SCM command failed, make sure that your SCM binary (eg. svn) is in PATH (#{ENV['PATH']}): #{strip_credential(cmd)}\n with: #{msg}") 216 logger.error("SCM command failed, make sure that your SCM binary (eg. svn) is in PATH (#{ENV['PATH']}): #{strip_credential(cmd)}\n with: #{msg}")
199 raise CommandFailed.new(msg) 217 raise CommandFailed.new(msg)
200 end 218 end
201 end 219 end
202 220
203 # Hides username/password in a given command 221 # Hides username/password in a given command
204 def self.strip_credential(cmd) 222 def self.strip_credential(cmd)
205 q = (Redmine::Platform.mswin? ? '"' : "'") 223 q = (Redmine::Platform.mswin? ? '"' : "'")
206 cmd.to_s.gsub(/(\-\-(password|username))\s+(#{q}[^#{q}]+#{q}|[^#{q}]\S+)/, '\\1 xxxx') 224 cmd.to_s.gsub(/(\-\-(password|username))\s+(#{q}[^#{q}]+#{q}|[^#{q}]\S+)/, '\\1 xxxx')
207 end 225 end
208 226
209 def strip_credential(cmd) 227 def strip_credential(cmd)
210 self.class.strip_credential(cmd) 228 self.class.strip_credential(cmd)
211 end 229 end
212 end 230
213 231 def scm_iconv(to, from, str)
232 return nil if str.nil?
233 return str if to == from
234 begin
235 Iconv.conv(to, from, str)
236 rescue Iconv::Failure => err
237 logger.error("failed to convert from #{from} to #{to}. #{err}")
238 nil
239 end
240 end
241 end
242
214 class Entries < Array 243 class Entries < Array
215 def sort_by_name 244 def sort_by_name
216 sort {|x,y| 245 sort {|x,y|
217 if x.kind == y.kind 246 if x.kind == y.kind
218 x.name.to_s <=> y.name.to_s 247 x.name.to_s <=> y.name.to_s
219 else 248 else
220 x.kind <=> y.kind 249 x.kind <=> y.kind
221 end 250 end
222 } 251 }
223 end 252 end
224 253
225 def revisions 254 def revisions
226 revisions ||= Revisions.new(collect{|entry| entry.lastrev}.compact) 255 revisions ||= Revisions.new(collect{|entry| entry.lastrev}.compact)
227 end 256 end
293 322
294 # Returns the readable identifier. 323 # Returns the readable identifier.
295 def format_identifier 324 def format_identifier
296 identifier 325 identifier
297 end 326 end
298 327 end
299 def save(repo) 328
300 Changeset.transaction do
301 changeset = Changeset.new(
302 :repository => repo,
303 :revision => identifier,
304 :scmid => scmid,
305 :committer => author,
306 :committed_on => time,
307 :comments => message)
308
309 if changeset.save
310 paths.each do |file|
311 Change.create(
312 :changeset => changeset,
313 :action => file[:action],
314 :path => file[:path])
315 end
316 end
317 end
318 end
319 end
320
321 class Annotate 329 class Annotate
322 attr_reader :lines, :revisions 330 attr_reader :lines, :revisions
323 331
324 def initialize 332 def initialize
325 @lines = [] 333 @lines = []