##// END OF EJS Templates
scm remove trailing white-spaces in abstract adapter....
Toshi MARUYAMA -
r5517:8df05b9a6dff
parent child
Show More
@@ -1,347 +1,347
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require 'cgi'
19 19
20 20 module Redmine
21 21 module Scm
22 22 module Adapters
23 23 class CommandFailed < StandardError #:nodoc:
24 24 end
25 25
26 26 class AbstractAdapter #:nodoc:
27 27 class << self
28 28 def client_command
29 29 ""
30 30 end
31 31
32 32 # Returns the version of the scm client
33 33 # Eg: [1, 5, 0] or [] if unknown
34 34 def client_version
35 35 []
36 36 end
37 37
38 38 # Returns the version string of the scm client
39 39 # Eg: '1.5.0' or 'Unknown version' if unknown
40 40 def client_version_string
41 41 v = client_version || 'Unknown version'
42 42 v.is_a?(Array) ? v.join('.') : v.to_s
43 43 end
44 44
45 45 # Returns true if the current client version is above
46 46 # or equals the given one
47 47 # If option is :unknown is set to true, it will return
48 48 # true if the client version is unknown
49 49 def client_version_above?(v, options={})
50 50 ((client_version <=> v) >= 0) || (client_version.empty? && options[:unknown])
51 51 end
52 52
53 53 def client_available
54 54 true
55 55 end
56 56
57 57 def shell_quote(str)
58 58 if Redmine::Platform.mswin?
59 59 '"' + str.gsub(/"/, '\\"') + '"'
60 60 else
61 61 "'" + str.gsub(/'/, "'\"'\"'") + "'"
62 62 end
63 63 end
64 64 end
65 65
66 66 def initialize(url, root_url=nil, login=nil, password=nil,
67 67 path_encoding=nil)
68 68 @url = url
69 69 @login = login if login && !login.empty?
70 70 @password = (password || "") if @login
71 71 @root_url = root_url.blank? ? retrieve_root_url : root_url
72 72 end
73 73
74 74 def adapter_name
75 75 'Abstract'
76 76 end
77 77
78 78 def supports_cat?
79 79 true
80 80 end
81 81
82 82 def supports_annotate?
83 83 respond_to?('annotate')
84 84 end
85 85
86 86 def root_url
87 87 @root_url
88 88 end
89 89
90 90 def url
91 91 @url
92 92 end
93
93
94 94 # get info about the svn repository
95 95 def info
96 96 return nil
97 97 end
98
98
99 99 # Returns the entry identified by path and revision identifier
100 100 # or nil if entry doesn't exist in the repository
101 101 def entry(path=nil, identifier=nil)
102 102 parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
103 103 search_path = parts[0..-2].join('/')
104 104 search_name = parts[-1]
105 105 if search_path.blank? && search_name.blank?
106 106 # Root entry
107 107 Entry.new(:path => '', :kind => 'dir')
108 108 else
109 109 # Search for the entry in the parent directory
110 110 es = entries(search_path, identifier)
111 111 es ? es.detect {|e| e.name == search_name} : nil
112 112 end
113 113 end
114 114
115 115 # Returns an Entries collection
116 116 # or nil if the given path doesn't exist in the repository
117 117 def entries(path=nil, identifier=nil)
118 118 return nil
119 119 end
120 120
121 121 def branches
122 122 return nil
123 123 end
124 124
125 125 def tags
126 126 return nil
127 127 end
128 128
129 129 def default_branch
130 130 return nil
131 131 end
132 132
133 133 def properties(path, identifier=nil)
134 134 return nil
135 135 end
136 136
137 137 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
138 138 return nil
139 139 end
140 140
141 141 def diff(path, identifier_from, identifier_to=nil)
142 142 return nil
143 143 end
144 144
145 145 def cat(path, identifier=nil)
146 146 return nil
147 147 end
148 148
149 149 def with_leading_slash(path)
150 150 path ||= ''
151 151 (path[0,1]!="/") ? "/#{path}" : path
152 152 end
153 153
154 154 def with_trailling_slash(path)
155 155 path ||= ''
156 156 (path[-1,1] == "/") ? path : "#{path}/"
157 157 end
158 158
159 159 def without_leading_slash(path)
160 160 path ||= ''
161 161 path.gsub(%r{^/+}, '')
162 162 end
163 163
164 164 def without_trailling_slash(path)
165 165 path ||= ''
166 166 (path[-1,1] == "/") ? path[0..-2] : path
167 167 end
168 168
169 169 def shell_quote(str)
170 170 self.class.shell_quote(str)
171 171 end
172 172
173 173 private
174 174 def retrieve_root_url
175 175 info = self.info
176 176 info ? info.root_url : nil
177 177 end
178 178
179 179 def target(path)
180 180 path ||= ''
181 181 base = path.match(/^\//) ? root_url : url
182 182 shell_quote("#{base}/#{path}".gsub(/[?<>\*]/, ''))
183 183 end
184 184
185 185 def logger
186 186 self.class.logger
187 187 end
188 188
189 189 def shellout(cmd, &block)
190 190 self.class.shellout(cmd, &block)
191 191 end
192 192
193 193 def self.logger
194 194 RAILS_DEFAULT_LOGGER
195 195 end
196 196
197 197 def self.shellout(cmd, &block)
198 198 logger.debug "Shelling out: #{strip_credential(cmd)}" if logger && logger.debug?
199 199 if Rails.env == 'development'
200 200 # Capture stderr when running in dev environment
201 201 cmd = "#{cmd} 2>>#{RAILS_ROOT}/log/scm.stderr.log"
202 202 end
203 203 begin
204 204 if RUBY_VERSION < '1.9'
205 205 mode = "r+"
206 206 else
207 207 mode = "r+:ASCII-8BIT"
208 208 end
209 209 IO.popen(cmd, mode) do |io|
210 210 io.close_write
211 211 block.call(io) if block_given?
212 212 end
213 213 rescue Errno::ENOENT => e
214 214 msg = strip_credential(e.message)
215 215 # The command failed, log it and re-raise
216 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}")
217 217 raise CommandFailed.new(msg)
218 218 end
219 219 end
220 220
221 221 # Hides username/password in a given command
222 222 def self.strip_credential(cmd)
223 223 q = (Redmine::Platform.mswin? ? '"' : "'")
224 224 cmd.to_s.gsub(/(\-\-(password|username))\s+(#{q}[^#{q}]+#{q}|[^#{q}]\S+)/, '\\1 xxxx')
225 225 end
226 226
227 227 def strip_credential(cmd)
228 228 self.class.strip_credential(cmd)
229 229 end
230 230
231 231 def scm_iconv(to, from, str)
232 232 return nil if str.nil?
233 233 return str if to == from
234 234 begin
235 235 Iconv.conv(to, from, str)
236 236 rescue Iconv::Failure => err
237 237 logger.error("failed to convert from #{from} to #{to}. #{err}")
238 238 nil
239 239 end
240 240 end
241 241 end
242 242
243 243 class Entries < Array
244 244 def sort_by_name
245 245 sort {|x,y|
246 246 if x.kind == y.kind
247 247 x.name.to_s <=> y.name.to_s
248 248 else
249 249 x.kind <=> y.kind
250 250 end
251 251 }
252 252 end
253
253
254 254 def revisions
255 255 revisions ||= Revisions.new(collect{|entry| entry.lastrev}.compact)
256 256 end
257 257 end
258
258
259 259 class Info
260 260 attr_accessor :root_url, :lastrev
261 261 def initialize(attributes={})
262 262 self.root_url = attributes[:root_url] if attributes[:root_url]
263 263 self.lastrev = attributes[:lastrev]
264 264 end
265 265 end
266
266
267 267 class Entry
268 268 attr_accessor :name, :path, :kind, :size, :lastrev
269 269 def initialize(attributes={})
270 270 self.name = attributes[:name] if attributes[:name]
271 271 self.path = attributes[:path] if attributes[:path]
272 272 self.kind = attributes[:kind] if attributes[:kind]
273 273 self.size = attributes[:size].to_i if attributes[:size]
274 274 self.lastrev = attributes[:lastrev]
275 275 end
276
276
277 277 def is_file?
278 278 'file' == self.kind
279 279 end
280
280
281 281 def is_dir?
282 282 'dir' == self.kind
283 283 end
284
284
285 285 def is_text?
286 286 Redmine::MimeType.is_type?('text', name)
287 287 end
288 288 end
289 289
290 290 class Revisions < Array
291 291 def latest
292 292 sort {|x,y|
293 293 unless x.time.nil? or y.time.nil?
294 294 x.time <=> y.time
295 295 else
296 296 0
297 297 end
298 298 }.last
299 299 end
300 300 end
301 301
302 302 class Revision
303 303 attr_accessor :scmid, :name, :author, :time, :message,
304 304 :paths, :revision, :branch, :identifier
305 305
306 306 def initialize(attributes={})
307 307 self.identifier = attributes[:identifier]
308 308 self.scmid = attributes[:scmid]
309 309 self.name = attributes[:name] || self.identifier
310 310 self.author = attributes[:author]
311 311 self.time = attributes[:time]
312 312 self.message = attributes[:message] || ""
313 313 self.paths = attributes[:paths]
314 314 self.revision = attributes[:revision]
315 315 self.branch = attributes[:branch]
316 316 end
317 317
318 318 # Returns the readable identifier.
319 319 def format_identifier
320 320 self.identifier.to_s
321 321 end
322 322 end
323 323
324 324 class Annotate
325 325 attr_reader :lines, :revisions
326 326
327 327 def initialize
328 328 @lines = []
329 329 @revisions = []
330 330 end
331 331
332 332 def add_line(line, revision)
333 333 @lines << line
334 334 @revisions << revision
335 335 end
336 336
337 337 def content
338 338 content = lines.join("\n")
339 339 end
340 340
341 341 def empty?
342 342 lines.empty?
343 343 end
344 344 end
345 345 end
346 346 end
347 347 end
General Comments 0
You need to be logged in to leave comments. Login now