##// END OF EJS Templates
scm: cvs: code clean up adapter entries()....
Toshi MARUYAMA -
r4966:45cba97088a0
parent child
Show More
@@ -1,425 +1,429
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require 'redmine/scm/adapters/abstract_adapter'
18 require 'redmine/scm/adapters/abstract_adapter'
19
19
20 module Redmine
20 module Redmine
21 module Scm
21 module Scm
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 # raised if scm command exited with error, e.g. unknown revision.
28 # raised if scm command exited with error, e.g. unknown revision.
29 class ScmCommandAborted < CommandFailed; end
29 class ScmCommandAborted < CommandFailed; end
30
30
31 class << self
31 class << self
32 def client_command
32 def client_command
33 @@bin ||= CVS_BIN
33 @@bin ||= CVS_BIN
34 end
34 end
35
35
36 def sq_bin
36 def sq_bin
37 @@sq_bin ||= shell_quote(CVS_BIN)
37 @@sq_bin ||= shell_quote(CVS_BIN)
38 end
38 end
39
39
40 def client_version
40 def client_version
41 @@client_version ||= (scm_command_version || [])
41 @@client_version ||= (scm_command_version || [])
42 end
42 end
43
43
44 def client_available
44 def client_available
45 client_version_above?([1, 12])
45 client_version_above?([1, 12])
46 end
46 end
47
47
48 def scm_command_version
48 def scm_command_version
49 scm_version = scm_version_from_command_line.dup
49 scm_version = scm_version_from_command_line.dup
50 if scm_version.respond_to?(:force_encoding)
50 if scm_version.respond_to?(:force_encoding)
51 scm_version.force_encoding('ASCII-8BIT')
51 scm_version.force_encoding('ASCII-8BIT')
52 end
52 end
53 if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}m)
53 if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}m)
54 m[2].scan(%r{\d+}).collect(&:to_i)
54 m[2].scan(%r{\d+}).collect(&:to_i)
55 end
55 end
56 end
56 end
57
57
58 def scm_version_from_command_line
58 def scm_version_from_command_line
59 shellout("#{sq_bin} --version") { |io| io.read }.to_s
59 shellout("#{sq_bin} --version") { |io| io.read }.to_s
60 end
60 end
61 end
61 end
62
62
63 # Guidelines for the input:
63 # Guidelines for the input:
64 # url -> the project-path, relative to the cvsroot (eg. module name)
64 # url -> the project-path, relative to the cvsroot (eg. module name)
65 # root_url -> the good old, sometimes damned, CVSROOT
65 # root_url -> the good old, sometimes damned, CVSROOT
66 # login -> unnecessary
66 # login -> unnecessary
67 # password -> unnecessary too
67 # password -> unnecessary too
68 def initialize(url, root_url=nil, login=nil, password=nil,
68 def initialize(url, root_url=nil, login=nil, password=nil,
69 path_encoding=nil)
69 path_encoding=nil)
70 @url = url
70 @url = url
71 @login = login if login && !login.empty?
71 @login = login if login && !login.empty?
72 @password = (password || "") if @login
72 @password = (password || "") if @login
73 #TODO: better Exception here (IllegalArgumentException)
73 #TODO: better Exception here (IllegalArgumentException)
74 raise CommandFailed if root_url.blank?
74 raise CommandFailed if root_url.blank?
75 @root_url = root_url
75 @root_url = root_url
76 end
76 end
77
77
78 def root_url
78 def root_url
79 @root_url
79 @root_url
80 end
80 end
81
81
82 def url
82 def url
83 @url
83 @url
84 end
84 end
85
85
86 def info
86 def info
87 logger.debug "<cvs> info"
87 logger.debug "<cvs> info"
88 Info.new({:root_url => @root_url, :lastrev => nil})
88 Info.new({:root_url => @root_url, :lastrev => nil})
89 end
89 end
90
90
91 def get_previous_revision(revision)
91 def get_previous_revision(revision)
92 CvsRevisionHelper.new(revision).prevRev
92 CvsRevisionHelper.new(revision).prevRev
93 end
93 end
94
94
95 # Returns an Entries collection
95 # Returns an Entries collection
96 # or nil if the given path doesn't exist in the repository
96 # or nil if the given path doesn't exist in the repository
97 # this method is used by the repository-browser (aka LIST)
97 # this method is used by the repository-browser (aka LIST)
98 def entries(path=nil, identifier=nil)
98 def entries(path=nil, identifier=nil)
99 logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'"
99 logger.debug "<cvs> entries '#{path}' with identifier '#{identifier}'"
100 path_with_project="#{url}#{with_leading_slash(path)}"
100 path_with_project="#{url}#{with_leading_slash(path)}"
101 entries = Entries.new
101 entries = Entries.new
102 cmd_args = %w|rls -e|
102 cmd_args = %w|rls -e|
103 cmd_args << "-D" << time_to_cvstime(identifier) if identifier
103 cmd_args << "-D" << time_to_cvstime(identifier) if identifier
104 cmd_args << path_with_project
104 cmd_args << path_with_project
105 scm_cmd(*cmd_args) do |io|
105 scm_cmd(*cmd_args) do |io|
106 io.each_line(){|line|
106 io.each_line() do |line|
107 fields=line.chop.split('/',-1)
107 fields = line.chop.split('/',-1)
108 logger.debug(">>InspectLine #{fields.inspect}")
108 logger.debug(">>InspectLine #{fields.inspect}")
109
110 if fields[0]!="D"
109 if fields[0]!="D"
111 entries << Entry.new({:name => fields[-5],
110 entries << Entry.new(
111 {
112 :name => fields[-5],
112 #:path => fields[-4].include?(path)?fields[-4]:(path + "/"+ fields[-4]),
113 #:path => fields[-4].include?(path)?fields[-4]:(path + "/"+ fields[-4]),
113 :path => "#{path}/#{fields[-5]}",
114 :path => "#{path}/#{fields[-5]}",
114 :kind => 'file',
115 :kind => 'file',
115 :size => nil,
116 :size => nil,
116 :lastrev => Revision.new({
117 :lastrev => Revision.new(
117 :revision => fields[-4],
118 {
118 :name => fields[-4],
119 :revision => fields[-4],
119 :time => Time.parse(fields[-3]),
120 :name => fields[-4],
120 :author => ''
121 :time => Time.parse(fields[-3]),
122 :author => ''
123 })
121 })
124 })
122 })
123 else
125 else
124 entries << Entry.new({:name => fields[1],
126 entries << Entry.new(
127 {
128 :name => fields[1],
125 :path => "#{path}/#{fields[1]}",
129 :path => "#{path}/#{fields[1]}",
126 :kind => 'dir',
130 :kind => 'dir',
127 :size => nil,
131 :size => nil,
128 :lastrev => nil
132 :lastrev => nil
129 })
133 })
130 end
134 end
131 }
135 end
132 end
136 end
133 entries.sort_by_name
137 entries.sort_by_name
134 rescue ScmCommandAborted
138 rescue ScmCommandAborted
135 nil
139 nil
136 end
140 end
137
141
138 STARTLOG="----------------------------"
142 STARTLOG="----------------------------"
139 ENDLOG ="============================================================================="
143 ENDLOG ="============================================================================="
140
144
141 # Returns all revisions found between identifier_from and identifier_to
145 # Returns all revisions found between identifier_from and identifier_to
142 # in the repository. both identifier have to be dates or nil.
146 # in the repository. both identifier have to be dates or nil.
143 # these method returns nothing but yield every result in block
147 # these method returns nothing but yield every result in block
144 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}, &block)
148 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}, &block)
145 logger.debug "<cvs> revisions path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
149 logger.debug "<cvs> revisions path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
146
150
147 path_with_project="#{url}#{with_leading_slash(path)}"
151 path_with_project="#{url}#{with_leading_slash(path)}"
148 cmd_args = %w|rlog|
152 cmd_args = %w|rlog|
149 cmd_args << "-d" << ">#{time_to_cvstime_rlog(identifier_from)}" if identifier_from
153 cmd_args << "-d" << ">#{time_to_cvstime_rlog(identifier_from)}" if identifier_from
150 cmd_args << path_with_project
154 cmd_args << path_with_project
151 scm_cmd(*cmd_args) do |io|
155 scm_cmd(*cmd_args) do |io|
152 state="entry_start"
156 state="entry_start"
153
157
154 commit_log=String.new
158 commit_log=String.new
155 revision=nil
159 revision=nil
156 date=nil
160 date=nil
157 author=nil
161 author=nil
158 entry_path=nil
162 entry_path=nil
159 entry_name=nil
163 entry_name=nil
160 file_state=nil
164 file_state=nil
161 branch_map=nil
165 branch_map=nil
162
166
163 io.each_line() do |line|
167 io.each_line() do |line|
164
168
165 if state!="revision" && /^#{ENDLOG}/ =~ line
169 if state!="revision" && /^#{ENDLOG}/ =~ line
166 commit_log=String.new
170 commit_log=String.new
167 revision=nil
171 revision=nil
168 state="entry_start"
172 state="entry_start"
169 end
173 end
170
174
171 if state=="entry_start"
175 if state=="entry_start"
172 branch_map=Hash.new
176 branch_map=Hash.new
173 if /^RCS file: #{Regexp.escape(root_url_path)}\/#{Regexp.escape(path_with_project)}(.+),v$/ =~ line
177 if /^RCS file: #{Regexp.escape(root_url_path)}\/#{Regexp.escape(path_with_project)}(.+),v$/ =~ line
174 entry_path = normalize_cvs_path($1)
178 entry_path = normalize_cvs_path($1)
175 entry_name = normalize_path(File.basename($1))
179 entry_name = normalize_path(File.basename($1))
176 logger.debug("Path #{entry_path} <=> Name #{entry_name}")
180 logger.debug("Path #{entry_path} <=> Name #{entry_name}")
177 elsif /^head: (.+)$/ =~ line
181 elsif /^head: (.+)$/ =~ line
178 entry_headRev = $1 #unless entry.nil?
182 entry_headRev = $1 #unless entry.nil?
179 elsif /^symbolic names:/ =~ line
183 elsif /^symbolic names:/ =~ line
180 state="symbolic" #unless entry.nil?
184 state="symbolic" #unless entry.nil?
181 elsif /^#{STARTLOG}/ =~ line
185 elsif /^#{STARTLOG}/ =~ line
182 commit_log=String.new
186 commit_log=String.new
183 state="revision"
187 state="revision"
184 end
188 end
185 next
189 next
186 elsif state=="symbolic"
190 elsif state=="symbolic"
187 if /^(.*):\s(.*)/ =~ (line.strip)
191 if /^(.*):\s(.*)/ =~ (line.strip)
188 branch_map[$1]=$2
192 branch_map[$1]=$2
189 else
193 else
190 state="tags"
194 state="tags"
191 next
195 next
192 end
196 end
193 elsif state=="tags"
197 elsif state=="tags"
194 if /^#{STARTLOG}/ =~ line
198 if /^#{STARTLOG}/ =~ line
195 commit_log = ""
199 commit_log = ""
196 state="revision"
200 state="revision"
197 elsif /^#{ENDLOG}/ =~ line
201 elsif /^#{ENDLOG}/ =~ line
198 state="head"
202 state="head"
199 end
203 end
200 next
204 next
201 elsif state=="revision"
205 elsif state=="revision"
202 if /^#{ENDLOG}/ =~ line || /^#{STARTLOG}/ =~ line
206 if /^#{ENDLOG}/ =~ line || /^#{STARTLOG}/ =~ line
203 if revision
207 if revision
204
208
205 revHelper=CvsRevisionHelper.new(revision)
209 revHelper=CvsRevisionHelper.new(revision)
206 revBranch="HEAD"
210 revBranch="HEAD"
207
211
208 branch_map.each() do |branch_name,branch_point|
212 branch_map.each() do |branch_name,branch_point|
209 if revHelper.is_in_branch_with_symbol(branch_point)
213 if revHelper.is_in_branch_with_symbol(branch_point)
210 revBranch=branch_name
214 revBranch=branch_name
211 end
215 end
212 end
216 end
213
217
214 logger.debug("********** YIELD Revision #{revision}::#{revBranch}")
218 logger.debug("********** YIELD Revision #{revision}::#{revBranch}")
215
219
216 yield Revision.new({
220 yield Revision.new({
217 :time => date,
221 :time => date,
218 :author => author,
222 :author => author,
219 :message=>commit_log.chomp,
223 :message=>commit_log.chomp,
220 :paths => [{
224 :paths => [{
221 :revision => revision,
225 :revision => revision,
222 :branch=> revBranch,
226 :branch=> revBranch,
223 :path=>entry_path,
227 :path=>entry_path,
224 :name=>entry_name,
228 :name=>entry_name,
225 :kind=>'file',
229 :kind=>'file',
226 :action=>file_state
230 :action=>file_state
227 }]
231 }]
228 })
232 })
229 end
233 end
230
234
231 commit_log=String.new
235 commit_log=String.new
232 revision=nil
236 revision=nil
233
237
234 if /^#{ENDLOG}/ =~ line
238 if /^#{ENDLOG}/ =~ line
235 state="entry_start"
239 state="entry_start"
236 end
240 end
237 next
241 next
238 end
242 end
239
243
240 if /^branches: (.+)$/ =~ line
244 if /^branches: (.+)$/ =~ line
241 #TODO: version.branch = $1
245 #TODO: version.branch = $1
242 elsif /^revision (\d+(?:\.\d+)+).*$/ =~ line
246 elsif /^revision (\d+(?:\.\d+)+).*$/ =~ line
243 revision = $1
247 revision = $1
244 elsif /^date:\s+(\d+.\d+.\d+\s+\d+:\d+:\d+)/ =~ line
248 elsif /^date:\s+(\d+.\d+.\d+\s+\d+:\d+:\d+)/ =~ line
245 date = Time.parse($1)
249 date = Time.parse($1)
246 author = /author: ([^;]+)/.match(line)[1]
250 author = /author: ([^;]+)/.match(line)[1]
247 file_state = /state: ([^;]+)/.match(line)[1]
251 file_state = /state: ([^;]+)/.match(line)[1]
248 #TODO: linechanges only available in CVS.... maybe a feature our SVN implementation. i'm sure, they are
252 #TODO: linechanges only available in CVS.... maybe a feature our SVN implementation. i'm sure, they are
249 # useful for stats or something else
253 # useful for stats or something else
250 # linechanges =/lines: \+(\d+) -(\d+)/.match(line)
254 # linechanges =/lines: \+(\d+) -(\d+)/.match(line)
251 # unless linechanges.nil?
255 # unless linechanges.nil?
252 # version.line_plus = linechanges[1]
256 # version.line_plus = linechanges[1]
253 # version.line_minus = linechanges[2]
257 # version.line_minus = linechanges[2]
254 # else
258 # else
255 # version.line_plus = 0
259 # version.line_plus = 0
256 # version.line_minus = 0
260 # version.line_minus = 0
257 # end
261 # end
258 else
262 else
259 commit_log << line unless line =~ /^\*\*\* empty log message \*\*\*/
263 commit_log << line unless line =~ /^\*\*\* empty log message \*\*\*/
260 end
264 end
261 end
265 end
262 end
266 end
263 end
267 end
264 rescue ScmCommandAborted
268 rescue ScmCommandAborted
265 Revisions.new
269 Revisions.new
266 end
270 end
267
271
268 def diff(path, identifier_from, identifier_to=nil)
272 def diff(path, identifier_from, identifier_to=nil)
269 logger.debug "<cvs> diff path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
273 logger.debug "<cvs> diff path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
270 path_with_project="#{url}#{with_leading_slash(path)}"
274 path_with_project="#{url}#{with_leading_slash(path)}"
271 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{shell_quote path_with_project}"
275 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{shell_quote path_with_project}"
272 diff = []
276 diff = []
273 shellout(cmd) do |io|
277 shellout(cmd) do |io|
274 io.each_line do |line|
278 io.each_line do |line|
275 diff << line
279 diff << line
276 end
280 end
277 end
281 end
278 return nil if $? && $?.exitstatus != 0
282 return nil if $? && $?.exitstatus != 0
279 diff
283 diff
280 end
284 end
281
285
282 def cat(path, identifier=nil)
286 def cat(path, identifier=nil)
283 identifier = (identifier) ? identifier : "HEAD"
287 identifier = (identifier) ? identifier : "HEAD"
284 logger.debug "<cvs> cat path:'#{path}',identifier #{identifier}"
288 logger.debug "<cvs> cat path:'#{path}',identifier #{identifier}"
285 path_with_project="#{url}#{with_leading_slash(path)}"
289 path_with_project="#{url}#{with_leading_slash(path)}"
286 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} co"
290 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} co"
287 cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier
291 cmd << " -D \"#{time_to_cvstime(identifier)}\"" if identifier
288 cmd << " -p #{shell_quote path_with_project}"
292 cmd << " -p #{shell_quote path_with_project}"
289 cat = nil
293 cat = nil
290 shellout(cmd) do |io|
294 shellout(cmd) do |io|
291 io.binmode
295 io.binmode
292 cat = io.read
296 cat = io.read
293 end
297 end
294 return nil if $? && $?.exitstatus != 0
298 return nil if $? && $?.exitstatus != 0
295 cat
299 cat
296 end
300 end
297
301
298 def annotate(path, identifier=nil)
302 def annotate(path, identifier=nil)
299 identifier = (identifier) ? identifier.to_i : "HEAD"
303 identifier = (identifier) ? identifier.to_i : "HEAD"
300 logger.debug "<cvs> annotate path:'#{path}',identifier #{identifier}"
304 logger.debug "<cvs> annotate path:'#{path}',identifier #{identifier}"
301 path_with_project="#{url}#{with_leading_slash(path)}"
305 path_with_project="#{url}#{with_leading_slash(path)}"
302 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rannotate -r#{identifier} #{shell_quote path_with_project}"
306 cmd = "#{self.class.sq_bin} -d #{shell_quote root_url} rannotate -r#{identifier} #{shell_quote path_with_project}"
303 blame = Annotate.new
307 blame = Annotate.new
304 shellout(cmd) do |io|
308 shellout(cmd) do |io|
305 io.each_line do |line|
309 io.each_line do |line|
306 next unless line =~ %r{^([\d\.]+)\s+\(([^\)]+)\s+[^\)]+\):\s(.*)$}
310 next unless line =~ %r{^([\d\.]+)\s+\(([^\)]+)\s+[^\)]+\):\s(.*)$}
307 blame.add_line($3.rstrip, Revision.new(:revision => $1, :author => $2.strip))
311 blame.add_line($3.rstrip, Revision.new(:revision => $1, :author => $2.strip))
308 end
312 end
309 end
313 end
310 return nil if $? && $?.exitstatus != 0
314 return nil if $? && $?.exitstatus != 0
311 blame
315 blame
312 end
316 end
313
317
314 private
318 private
315
319
316 # Returns the root url without the connexion string
320 # Returns the root url without the connexion string
317 # :pserver:anonymous@foo.bar:/path => /path
321 # :pserver:anonymous@foo.bar:/path => /path
318 # :ext:cvsservername:/path => /path
322 # :ext:cvsservername:/path => /path
319 def root_url_path
323 def root_url_path
320 root_url.to_s.gsub(/^:.+:\d*/, '')
324 root_url.to_s.gsub(/^:.+:\d*/, '')
321 end
325 end
322
326
323 # convert a date/time into the CVS-format
327 # convert a date/time into the CVS-format
324 def time_to_cvstime(time)
328 def time_to_cvstime(time)
325 return nil if time.nil?
329 return nil if time.nil?
326 return Time.now if time == 'HEAD'
330 return Time.now if time == 'HEAD'
327
331
328 unless time.kind_of? Time
332 unless time.kind_of? Time
329 time = Time.parse(time)
333 time = Time.parse(time)
330 end
334 end
331 return time.strftime("%Y-%m-%d %H:%M:%S")
335 return time.strftime("%Y-%m-%d %H:%M:%S")
332 end
336 end
333
337
334 def time_to_cvstime_rlog(time)
338 def time_to_cvstime_rlog(time)
335 return nil if time.nil?
339 return nil if time.nil?
336 t1 = time.clone.localtime
340 t1 = time.clone.localtime
337 return t1.strftime("%Y-%m-%d %H:%M:%S")
341 return t1.strftime("%Y-%m-%d %H:%M:%S")
338 end
342 end
339
343
340 def normalize_cvs_path(path)
344 def normalize_cvs_path(path)
341 normalize_path(path.gsub(/Attic\//,''))
345 normalize_path(path.gsub(/Attic\//,''))
342 end
346 end
343
347
344 def normalize_path(path)
348 def normalize_path(path)
345 path.sub(/^(\/)*(.*)/,'\2').sub(/(.*)(,v)+/,'\1')
349 path.sub(/^(\/)*(.*)/,'\2').sub(/(.*)(,v)+/,'\1')
346 end
350 end
347
351
348 def scm_cmd(*args, &block)
352 def scm_cmd(*args, &block)
349 full_args = [CVS_BIN, '-d', root_url]
353 full_args = [CVS_BIN, '-d', root_url]
350 full_args += args
354 full_args += args
351 ret = shellout(full_args.map { |e| shell_quote e.to_s }.join(' '), &block)
355 ret = shellout(full_args.map { |e| shell_quote e.to_s }.join(' '), &block)
352 if $? && $?.exitstatus != 0
356 if $? && $?.exitstatus != 0
353 raise ScmCommandAborted, "cvs exited with non-zero status: #{$?.exitstatus}"
357 raise ScmCommandAborted, "cvs exited with non-zero status: #{$?.exitstatus}"
354 end
358 end
355 ret
359 ret
356 end
360 end
357 private :scm_cmd
361 private :scm_cmd
358 end
362 end
359
363
360 class CvsRevisionHelper
364 class CvsRevisionHelper
361 attr_accessor :complete_rev, :revision, :base, :branchid
365 attr_accessor :complete_rev, :revision, :base, :branchid
362
366
363 def initialize(complete_rev)
367 def initialize(complete_rev)
364 @complete_rev = complete_rev
368 @complete_rev = complete_rev
365 parseRevision()
369 parseRevision()
366 end
370 end
367
371
368 def branchPoint
372 def branchPoint
369 return @base
373 return @base
370 end
374 end
371
375
372 def branchVersion
376 def branchVersion
373 if isBranchRevision
377 if isBranchRevision
374 return @base+"."+@branchid
378 return @base+"."+@branchid
375 end
379 end
376 return @base
380 return @base
377 end
381 end
378
382
379 def isBranchRevision
383 def isBranchRevision
380 !@branchid.nil?
384 !@branchid.nil?
381 end
385 end
382
386
383 def prevRev
387 def prevRev
384 unless @revision==0
388 unless @revision==0
385 return buildRevision(@revision-1)
389 return buildRevision(@revision-1)
386 end
390 end
387 return buildRevision(@revision)
391 return buildRevision(@revision)
388 end
392 end
389
393
390 def is_in_branch_with_symbol(branch_symbol)
394 def is_in_branch_with_symbol(branch_symbol)
391 bpieces=branch_symbol.split(".")
395 bpieces=branch_symbol.split(".")
392 branch_start="#{bpieces[0..-3].join(".")}.#{bpieces[-1]}"
396 branch_start="#{bpieces[0..-3].join(".")}.#{bpieces[-1]}"
393 return (branchVersion==branch_start)
397 return (branchVersion==branch_start)
394 end
398 end
395
399
396 private
400 private
397 def buildRevision(rev)
401 def buildRevision(rev)
398 if rev== 0
402 if rev== 0
399 if @branchid.nil?
403 if @branchid.nil?
400 @base+".0"
404 @base+".0"
401 else
405 else
402 @base
406 @base
403 end
407 end
404 elsif @branchid.nil?
408 elsif @branchid.nil?
405 @base+"."+rev.to_s
409 @base+"."+rev.to_s
406 else
410 else
407 @base+"."+@branchid+"."+rev.to_s
411 @base+"."+@branchid+"."+rev.to_s
408 end
412 end
409 end
413 end
410
414
411 # Interpretiert die cvs revisionsnummern wie z.b. 1.14 oder 1.3.0.15
415 # Interpretiert die cvs revisionsnummern wie z.b. 1.14 oder 1.3.0.15
412 def parseRevision()
416 def parseRevision()
413 pieces=@complete_rev.split(".")
417 pieces=@complete_rev.split(".")
414 @revision=pieces.last.to_i
418 @revision=pieces.last.to_i
415 baseSize=1
419 baseSize=1
416 baseSize+=(pieces.size/2)
420 baseSize+=(pieces.size/2)
417 @base=pieces[0..-baseSize].join(".")
421 @base=pieces[0..-baseSize].join(".")
418 if baseSize > 2
422 if baseSize > 2
419 @branchid=pieces[-2]
423 @branchid=pieces[-2]
420 end
424 end
421 end
425 end
422 end
426 end
423 end
427 end
424 end
428 end
425 end
429 end
General Comments 0
You need to be logged in to leave comments. Login now