Mercurial > hg > soundsoftware-site
comparison lib/redmine/scm/adapters/.svn/text-base/cvs_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 | 0579821a129a |
children | eeebe205a056 cbce1fd3b1b7 |
comparison
equal
deleted
inserted
replaced
244:8972b600f4fb | 245:051f544170fe |
---|---|
22 module Adapters | 22 module Adapters |
23 class CvsAdapter < AbstractAdapter | 23 class CvsAdapter < AbstractAdapter |
24 | 24 |
25 # CVS executable name | 25 # CVS executable name |
26 CVS_BIN = Redmine::Configuration['scm_cvs_command'] || "cvs" | 26 CVS_BIN = Redmine::Configuration['scm_cvs_command'] || "cvs" |
27 | 27 |
28 class << self | |
29 def client_command | |
30 @@bin ||= CVS_BIN | |
31 end | |
32 | |
33 def sq_bin | |
34 @@sq_bin ||= shell_quote(CVS_BIN) | |
35 end | |
36 | |
37 def client_version | |
38 @@client_version ||= (scm_command_version || []) | |
39 end | |
40 | |
41 def client_available | |
42 client_version_above?([1, 12]) | |
43 end | |
44 | |
45 def scm_command_version | |
46 scm_version = scm_version_from_command_line.dup | |
47 if scm_version.respond_to?(:force_encoding) | |
48 scm_version.force_encoding('ASCII-8BIT') | |
49 end | |
50 if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}m) | |
51 m[2].scan(%r{\d+}).collect(&:to_i) | |
52 end | |
53 end | |
54 | |
55 def scm_version_from_command_line | |
56 shellout("#{sq_bin} --version") { |io| io.read }.to_s | |
57 end | |
58 end | |
59 | |
28 # Guidelines for the input: | 60 # Guidelines for the input: |
29 # url -> the project-path, relative to the cvsroot (eg. module name) | 61 # url -> the project-path, relative to the cvsroot (eg. module name) |
30 # root_url -> the good old, sometimes damned, CVSROOT | 62 # root_url -> the good old, sometimes damned, CVSROOT |
31 # login -> unnecessary | 63 # login -> unnecessary |
32 # password -> unnecessary too | 64 # password -> unnecessary too |
33 def initialize(url, root_url=nil, login=nil, password=nil) | 65 def initialize(url, root_url=nil, login=nil, password=nil, |
66 path_encoding=nil) | |
34 @url = url | 67 @url = url |
35 @login = login if login && !login.empty? | 68 @login = login if login && !login.empty? |
36 @password = (password || "") if @login | 69 @password = (password || "") if @login |
37 #TODO: better Exception here (IllegalArgumentException) | 70 #TODO: better Exception here (IllegalArgumentException) |
38 raise CommandFailed if root_url.blank? | 71 raise CommandFailed if root_url.blank? |
39 @root_url = root_url | 72 @root_url = root_url |
40 end | 73 end |
41 | 74 |
42 def root_url | 75 def root_url |
43 @root_url | 76 @root_url |
44 end | 77 end |
45 | 78 |
46 def url | 79 def url |
47 @url | 80 @url |
48 end | 81 end |
49 | 82 |
50 def info | 83 def info |
51 logger.debug "<cvs> info" | 84 logger.debug "<cvs> info" |
52 Info.new({:root_url => @root_url, :lastrev => nil}) | 85 Info.new({:root_url => @root_url, :lastrev => nil}) |
53 end | 86 end |
54 | 87 |
55 def get_previous_revision(revision) | 88 def get_previous_revision(revision) |
56 CvsRevisionHelper.new(revision).prevRev | 89 CvsRevisionHelper.new(revision).prevRev |
57 end | 90 end |
58 | 91 |
59 # Returns an Entries collection | 92 # Returns an Entries collection |
60 # or nil if the given path doesn't exist in the repository | 93 # or nil if the given path doesn't exist in the repository |
61 # this method is used by the repository-browser (aka LIST) | 94 # this method is used by the repository-browser (aka LIST) |
62 def entries(path=nil, identifier=nil) | 95 def entries(path=nil, identifier=nil) |
63 logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'" | 96 logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'" |
64 path_with_project="#{url}#{with_leading_slash(path)}" | 97 path_with_project="#{url}#{with_leading_slash(path)}" |
65 entries = Entries.new | 98 entries = Entries.new |
66 cmd = "#{CVS_BIN} -d #{shell_quote root_url} rls -e" | 99 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rls -e" |
67 cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier | 100 cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier |
68 cmd << " #{shell_quote path_with_project}" | 101 cmd << " #{shell_quote path_with_project}" |
69 shellout(cmd) do |io| | 102 shellout(cmd) do |io| |
70 io.each_line(){|line| | 103 io.each_line(){|line| |
71 fields=line.chop.split('/',-1) | 104 fields=line.chop.split('/',-1) |
72 logger.debug(">>InspectLine #{fields.inspect}") | 105 logger.debug(">>InspectLine #{fields.inspect}") |
73 | 106 |
74 if fields[0]!="D" | 107 if fields[0]!="D" |
75 entries << Entry.new({:name => fields[-5], | 108 entries << Entry.new({:name => fields[-5], |
76 #:path => fields[-4].include?(path)?fields[-4]:(path + "/"+ fields[-4]), | 109 #:path => fields[-4].include?(path)?fields[-4]:(path + "/"+ fields[-4]), |
77 :path => "#{path}/#{fields[-5]}", | 110 :path => "#{path}/#{fields[-5]}", |
78 :kind => 'file', | 111 :kind => 'file', |
94 end | 127 end |
95 } | 128 } |
96 end | 129 end |
97 return nil if $? && $?.exitstatus != 0 | 130 return nil if $? && $?.exitstatus != 0 |
98 entries.sort_by_name | 131 entries.sort_by_name |
99 end | 132 end |
100 | 133 |
101 STARTLOG="----------------------------" | 134 STARTLOG="----------------------------" |
102 ENDLOG ="=============================================================================" | 135 ENDLOG ="=============================================================================" |
103 | 136 |
104 # Returns all revisions found between identifier_from and identifier_to | 137 # Returns all revisions found between identifier_from and identifier_to |
105 # in the repository. both identifier have to be dates or nil. | 138 # in the repository. both identifier have to be dates or nil. |
106 # these method returns nothing but yield every result in block | 139 # these method returns nothing but yield every result in block |
107 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}, &block) | 140 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}, &block) |
108 logger.debug "<cvs> revisions path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}" | 141 logger.debug "<cvs> revisions path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}" |
109 | 142 |
110 path_with_project="#{url}#{with_leading_slash(path)}" | 143 path_with_project="#{url}#{with_leading_slash(path)}" |
111 cmd = "#{CVS_BIN} -d #{shell_quote root_url} rlog" | 144 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rlog" |
112 cmd << " -d\">#{time_to_cvstime_rlog(identifier_from)}\"" if identifier_from | 145 cmd << " -d\">#{time_to_cvstime_rlog(identifier_from)}\"" if identifier_from |
113 cmd << " #{shell_quote path_with_project}" | 146 cmd << " #{shell_quote path_with_project}" |
114 shellout(cmd) do |io| | 147 shellout(cmd) do |io| |
115 state="entry_start" | 148 state="entry_start" |
116 | 149 |
121 entry_path=nil | 154 entry_path=nil |
122 entry_name=nil | 155 entry_name=nil |
123 file_state=nil | 156 file_state=nil |
124 branch_map=nil | 157 branch_map=nil |
125 | 158 |
126 io.each_line() do |line| | 159 io.each_line() do |line| |
127 | 160 |
128 if state!="revision" && /^#{ENDLOG}/ =~ line | 161 if state!="revision" && /^#{ENDLOG}/ =~ line |
129 commit_log=String.new | 162 commit_log=String.new |
130 revision=nil | 163 revision=nil |
131 state="entry_start" | 164 state="entry_start" |
160 elsif /^#{ENDLOG}/ =~ line | 193 elsif /^#{ENDLOG}/ =~ line |
161 state="head" | 194 state="head" |
162 end | 195 end |
163 next | 196 next |
164 elsif state=="revision" | 197 elsif state=="revision" |
165 if /^#{ENDLOG}/ =~ line || /^#{STARTLOG}/ =~ line | 198 if /^#{ENDLOG}/ =~ line || /^#{STARTLOG}/ =~ line |
166 if revision | 199 if revision |
167 | 200 |
168 revHelper=CvsRevisionHelper.new(revision) | 201 revHelper=CvsRevisionHelper.new(revision) |
169 revBranch="HEAD" | 202 revBranch="HEAD" |
170 | 203 |
171 branch_map.each() do |branch_name,branch_point| | 204 branch_map.each() do |branch_name,branch_point| |
172 if revHelper.is_in_branch_with_symbol(branch_point) | 205 if revHelper.is_in_branch_with_symbol(branch_point) |
174 end | 207 end |
175 end | 208 end |
176 | 209 |
177 logger.debug("********** YIELD Revision #{revision}::#{revBranch}") | 210 logger.debug("********** YIELD Revision #{revision}::#{revBranch}") |
178 | 211 |
179 yield Revision.new({ | 212 yield Revision.new({ |
180 :time => date, | 213 :time => date, |
181 :author => author, | 214 :author => author, |
182 :message=>commit_log.chomp, | 215 :message=>commit_log.chomp, |
183 :paths => [{ | 216 :paths => [{ |
184 :revision => revision, | 217 :revision => revision, |
186 :path=>entry_path, | 219 :path=>entry_path, |
187 :name=>entry_name, | 220 :name=>entry_name, |
188 :kind=>'file', | 221 :kind=>'file', |
189 :action=>file_state | 222 :action=>file_state |
190 }] | 223 }] |
191 }) | 224 }) |
192 end | 225 end |
193 | 226 |
194 commit_log=String.new | 227 commit_log=String.new |
195 revision=nil | 228 revision=nil |
196 | 229 |
197 if /^#{ENDLOG}/ =~ line | 230 if /^#{ENDLOG}/ =~ line |
198 state="entry_start" | 231 state="entry_start" |
199 end | 232 end |
200 next | 233 next |
201 end | 234 end |
202 | 235 |
203 if /^branches: (.+)$/ =~ line | 236 if /^branches: (.+)$/ =~ line |
204 #TODO: version.branch = $1 | 237 #TODO: version.branch = $1 |
205 elsif /^revision (\d+(?:\.\d+)+).*$/ =~ line | 238 elsif /^revision (\d+(?:\.\d+)+).*$/ =~ line |
206 revision = $1 | 239 revision = $1 |
207 elsif /^date:\s+(\d+.\d+.\d+\s+\d+:\d+:\d+)/ =~ line | 240 elsif /^date:\s+(\d+.\d+.\d+\s+\d+:\d+:\d+)/ =~ line |
214 # unless linechanges.nil? | 247 # unless linechanges.nil? |
215 # version.line_plus = linechanges[1] | 248 # version.line_plus = linechanges[1] |
216 # version.line_minus = linechanges[2] | 249 # version.line_minus = linechanges[2] |
217 # else | 250 # else |
218 # version.line_plus = 0 | 251 # version.line_plus = 0 |
219 # version.line_minus = 0 | 252 # version.line_minus = 0 |
220 # end | 253 # end |
221 else | 254 else |
222 commit_log << line unless line =~ /^\*\*\* empty log message \*\*\*/ | 255 commit_log << line unless line =~ /^\*\*\* empty log message \*\*\*/ |
223 end | 256 end |
224 end | 257 end |
225 end | 258 end |
226 end | 259 end |
227 end | 260 end |
228 | 261 |
229 def diff(path, identifier_from, identifier_to=nil) | 262 def diff(path, identifier_from, identifier_to=nil) |
230 logger.debug "<cvs> diff path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}" | 263 logger.debug "<cvs> diff path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}" |
231 path_with_project="#{url}#{with_leading_slash(path)}" | 264 path_with_project="#{url}#{with_leading_slash(path)}" |
232 cmd = "#{CVS_BIN} -d #{shell_quote root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{shell_quote path_with_project}" | 265 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{shell_quote path_with_project}" |
233 diff = [] | 266 diff = [] |
234 shellout(cmd) do |io| | 267 shellout(cmd) do |io| |
235 io.each_line do |line| | 268 io.each_line do |line| |
236 diff << line | 269 diff << line |
237 end | 270 end |
238 end | 271 end |
239 return nil if $? && $?.exitstatus != 0 | 272 return nil if $? && $?.exitstatus != 0 |
240 diff | 273 diff |
241 end | 274 end |
242 | 275 |
243 def cat(path, identifier=nil) | 276 def cat(path, identifier=nil) |
244 identifier = (identifier) ? identifier : "HEAD" | 277 identifier = (identifier) ? identifier : "HEAD" |
245 logger.debug "<cvs> cat path:'#{path}',identifier #{identifier}" | 278 logger.debug "<cvs> cat path:'#{path}',identifier #{identifier}" |
246 path_with_project="#{url}#{with_leading_slash(path)}" | 279 path_with_project="#{url}#{with_leading_slash(path)}" |
247 cmd = "#{CVS_BIN} -d #{shell_quote root_url} co" | 280 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} co" |
248 cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier | 281 cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier |
249 cmd << " -p #{shell_quote path_with_project}" | 282 cmd << " -p #{shell_quote path_with_project}" |
250 cat = nil | 283 cat = nil |
251 shellout(cmd) do |io| | 284 shellout(cmd) do |io| |
285 io.binmode | |
252 cat = io.read | 286 cat = io.read |
253 end | 287 end |
254 return nil if $? && $?.exitstatus != 0 | 288 return nil if $? && $?.exitstatus != 0 |
255 cat | 289 cat |
256 end | 290 end |
257 | 291 |
258 def annotate(path, identifier=nil) | 292 def annotate(path, identifier=nil) |
259 identifier = (identifier) ? identifier.to_i : "HEAD" | 293 identifier = (identifier) ? identifier.to_i : "HEAD" |
260 logger.debug "<cvs> annotate path:'#{path}',identifier #{identifier}" | 294 logger.debug "<cvs> annotate path:'#{path}',identifier #{identifier}" |
261 path_with_project="#{url}#{with_leading_slash(path)}" | 295 path_with_project="#{url}#{with_leading_slash(path)}" |
262 cmd = "#{CVS_BIN} -d #{shell_quote root_url} rannotate -r#{identifier} #{shell_quote path_with_project}" | 296 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rannotate -r#{identifier} #{shell_quote path_with_project}" |
263 blame = Annotate.new | 297 blame = Annotate.new |
264 shellout(cmd) do |io| | 298 shellout(cmd) do |io| |
265 io.each_line do |line| | 299 io.each_line do |line| |
266 next unless line =~ %r{^([\d\.]+)\s+\(([^\)]+)\s+[^\)]+\):\s(.*)$} | 300 next unless line =~ %r{^([\d\.]+)\s+\(([^\)]+)\s+[^\)]+\):\s(.*)$} |
267 blame.add_line($3.rstrip, Revision.new(:revision => $1, :author => $2.strip)) | 301 blame.add_line($3.rstrip, Revision.new(:revision => $1, :author => $2.strip)) |
268 end | 302 end |
269 end | 303 end |
270 return nil if $? && $?.exitstatus != 0 | 304 return nil if $? && $?.exitstatus != 0 |
271 blame | 305 blame |
272 end | 306 end |
273 | 307 |
274 private | 308 private |
275 | 309 |
276 # Returns the root url without the connexion string | 310 # Returns the root url without the connexion string |
277 # :pserver:anonymous@foo.bar:/path => /path | 311 # :pserver:anonymous@foo.bar:/path => /path |
278 # :ext:cvsservername:/path => /path | 312 # :ext:cvsservername:/path => /path |
279 def root_url_path | 313 def root_url_path |
280 root_url.to_s.gsub(/^:.+:\d*/, '') | 314 root_url.to_s.gsub(/^:.+:\d*/, '') |
343 end | 377 end |
344 | 378 |
345 private | 379 private |
346 def buildRevision(rev) | 380 def buildRevision(rev) |
347 if rev== 0 | 381 if rev== 0 |
348 @base | 382 if @branchid.nil? |
383 @base+".0" | |
384 else | |
385 @base | |
386 end | |
349 elsif @branchid.nil? | 387 elsif @branchid.nil? |
350 @base+"."+rev.to_s | 388 @base+"."+rev.to_s |
351 else | 389 else |
352 @base+"."+@branchid+"."+rev.to_s | 390 @base+"."+@branchid+"."+rev.to_s |
353 end | 391 end |