##// END OF EJS Templates
scm: cvs: code clean up model....
Toshi MARUYAMA -
r4964:bf032661f757
parent child
Show More
@@ -1,180 +1,182
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/cvs_adapter'
18 require 'redmine/scm/adapters/cvs_adapter'
19 require 'digest/sha1'
19 require 'digest/sha1'
20
20
21 class Repository::Cvs < Repository
21 class Repository::Cvs < Repository
22 validates_presence_of :url, :root_url, :log_encoding
22 validates_presence_of :url, :root_url, :log_encoding
23
23
24 ATTRIBUTE_KEY_NAMES = {
24 ATTRIBUTE_KEY_NAMES = {
25 "url" => "CVSROOT",
25 "url" => "CVSROOT",
26 "root_url" => "Module",
26 "root_url" => "Module",
27 "log_encoding" => "Commit messages encoding",
27 "log_encoding" => "Commit messages encoding",
28 }
28 }
29 def self.human_attribute_name(attribute_key_name)
29 def self.human_attribute_name(attribute_key_name)
30 ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
30 ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
31 end
31 end
32
32
33 def self.scm_adapter_class
33 def self.scm_adapter_class
34 Redmine::Scm::Adapters::CvsAdapter
34 Redmine::Scm::Adapters::CvsAdapter
35 end
35 end
36
36
37 def self.scm_name
37 def self.scm_name
38 'CVS'
38 'CVS'
39 end
39 end
40
40
41 def entry(path=nil, identifier=nil)
41 def entry(path=nil, identifier=nil)
42 rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
42 rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
43 scm.entry(path, rev.nil? ? nil : rev.committed_on)
43 scm.entry(path, rev.nil? ? nil : rev.committed_on)
44 end
44 end
45
45
46 def entries(path=nil, identifier=nil)
46 def entries(path=nil, identifier=nil)
47 rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
47 rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
48 entries = scm.entries(path, rev.nil? ? nil : rev.committed_on)
48 entries = scm.entries(path, rev.nil? ? nil : rev.committed_on)
49 if entries
49 if entries
50 entries.each() do |entry|
50 entries.each() do |entry|
51 unless entry.lastrev.nil? || entry.lastrev.identifier
51 unless entry.lastrev.nil? || entry.lastrev.identifier
52 change=changes.find_by_revision_and_path( entry.lastrev.revision, scm.with_leading_slash(entry.path) )
52 change=changes.find_by_revision_and_path(
53 entry.lastrev.revision,
54 scm.with_leading_slash(entry.path) )
53 if change
55 if change
54 entry.lastrev.identifier=change.changeset.revision
56 entry.lastrev.identifier = change.changeset.revision
55 entry.lastrev.author=change.changeset.committer
57 entry.lastrev.author = change.changeset.committer
56 entry.lastrev.revision=change.revision
58 entry.lastrev.revision = change.revision
57 entry.lastrev.branch=change.branch
59 entry.lastrev.branch = change.branch
58 end
60 end
59 end
61 end
60 end
62 end
61 end
63 end
62 entries
64 entries
63 end
65 end
64
66
65 def cat(path, identifier=nil)
67 def cat(path, identifier=nil)
66 rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
68 rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
67 scm.cat(path, rev.nil? ? nil : rev.committed_on)
69 scm.cat(path, rev.nil? ? nil : rev.committed_on)
68 end
70 end
69
71
70 def diff(path, rev, rev_to)
72 def diff(path, rev, rev_to)
71 #convert rev to revision. CVS can't handle changesets here
73 #convert rev to revision. CVS can't handle changesets here
72 diff=[]
74 diff=[]
73 changeset_from=changesets.find_by_revision(rev)
75 changeset_from=changesets.find_by_revision(rev)
74 if rev_to.to_i > 0
76 if rev_to.to_i > 0
75 changeset_to=changesets.find_by_revision(rev_to)
77 changeset_to=changesets.find_by_revision(rev_to)
76 end
78 end
77 changeset_from.changes.each() do |change_from|
79 changeset_from.changes.each() do |change_from|
78
80
79 revision_from=nil
81 revision_from=nil
80 revision_to=nil
82 revision_to=nil
81
83
82 revision_from=change_from.revision if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
84 revision_from=change_from.revision if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
83
85
84 if revision_from
86 if revision_from
85 if changeset_to
87 if changeset_to
86 changeset_to.changes.each() do |change_to|
88 changeset_to.changes.each() do |change_to|
87 revision_to=change_to.revision if change_to.path==change_from.path
89 revision_to=change_to.revision if change_to.path==change_from.path
88 end
90 end
89 end
91 end
90 unless revision_to
92 unless revision_to
91 revision_to=scm.get_previous_revision(revision_from)
93 revision_to=scm.get_previous_revision(revision_from)
92 end
94 end
93 file_diff = scm.diff(change_from.path, revision_from, revision_to)
95 file_diff = scm.diff(change_from.path, revision_from, revision_to)
94 diff = diff + file_diff unless file_diff.nil?
96 diff = diff + file_diff unless file_diff.nil?
95 end
97 end
96 end
98 end
97 return diff
99 return diff
98 end
100 end
99
101
100 def fetch_changesets
102 def fetch_changesets
101 # some nifty bits to introduce a commit-id with cvs
103 # some nifty bits to introduce a commit-id with cvs
102 # natively cvs doesn't provide any kind of changesets, there is only a revision per file.
104 # natively cvs doesn't provide any kind of changesets, there is only a revision per file.
103 # we now take a guess using the author, the commitlog and the commit-date.
105 # we now take a guess using the author, the commitlog and the commit-date.
104
106
105 # last one is the next step to take. the commit-date is not equal for all
107 # last one is the next step to take. the commit-date is not equal for all
106 # commits in one changeset. cvs update the commit-date when the *,v file was touched. so
108 # commits in one changeset. cvs update the commit-date when the *,v file was touched. so
107 # we use a small delta here, to merge all changes belonging to _one_ changeset
109 # we use a small delta here, to merge all changes belonging to _one_ changeset
108 time_delta=10.seconds
110 time_delta=10.seconds
109
111
110 fetch_since = latest_changeset ? latest_changeset.committed_on : nil
112 fetch_since = latest_changeset ? latest_changeset.committed_on : nil
111 transaction do
113 transaction do
112 tmp_rev_num = 1
114 tmp_rev_num = 1
113 scm.revisions('', fetch_since, nil, :with_paths => true) do |revision|
115 scm.revisions('', fetch_since, nil, :with_paths => true) do |revision|
114 # only add the change to the database, if it doen't exists. the cvs log
116 # only add the change to the database, if it doen't exists. the cvs log
115 # is not exclusive at all.
117 # is not exclusive at all.
116 tmp_time = revision.time.clone
118 tmp_time = revision.time.clone
117 unless changes.find_by_path_and_revision(
119 unless changes.find_by_path_and_revision(
118 scm.with_leading_slash(revision.paths[0][:path]), revision.paths[0][:revision])
120 scm.with_leading_slash(revision.paths[0][:path]), revision.paths[0][:revision])
119 cmt = Changeset.normalize_comments(revision.message, repo_log_encoding)
121 cmt = Changeset.normalize_comments(revision.message, repo_log_encoding)
120 cs = changesets.find(:first, :conditions=>{
122 cs = changesets.find(:first, :conditions=>{
121 :committed_on=>tmp_time - time_delta .. tmp_time + time_delta,
123 :committed_on=>tmp_time - time_delta .. tmp_time + time_delta,
122 :committer=>revision.author,
124 :committer=>revision.author,
123 :comments=>cmt
125 :comments=>cmt
124 })
126 })
125
127
126 # create a new changeset....
128 # create a new changeset....
127 unless cs
129 unless cs
128 # we use a temporaray revision number here (just for inserting)
130 # we use a temporaray revision number here (just for inserting)
129 # later on, we calculate a continous positive number
131 # later on, we calculate a continous positive number
130 tmp_time2 = tmp_time.clone.gmtime
132 tmp_time2 = tmp_time.clone.gmtime
131 branch = revision.paths[0][:branch]
133 branch = revision.paths[0][:branch]
132 scmid = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S")
134 scmid = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S")
133 cs = Changeset.create(:repository => self,
135 cs = Changeset.create(:repository => self,
134 :revision => "tmp#{tmp_rev_num}",
136 :revision => "tmp#{tmp_rev_num}",
135 :scmid => scmid,
137 :scmid => scmid,
136 :committer => revision.author,
138 :committer => revision.author,
137 :committed_on => tmp_time,
139 :committed_on => tmp_time,
138 :comments => revision.message)
140 :comments => revision.message)
139 tmp_rev_num += 1
141 tmp_rev_num += 1
140 end
142 end
141
143
142 #convert CVS-File-States to internal Action-abbrevations
144 #convert CVS-File-States to internal Action-abbrevations
143 #default action is (M)odified
145 #default action is (M)odified
144 action="M"
146 action="M"
145 if revision.paths[0][:action]=="Exp" && revision.paths[0][:revision]=="1.1"
147 if revision.paths[0][:action]=="Exp" && revision.paths[0][:revision]=="1.1"
146 action="A" #add-action always at first revision (= 1.1)
148 action="A" #add-action always at first revision (= 1.1)
147 elsif revision.paths[0][:action]=="dead"
149 elsif revision.paths[0][:action]=="dead"
148 action="D" #dead-state is similar to Delete
150 action="D" #dead-state is similar to Delete
149 end
151 end
150
152
151 Change.create(:changeset => cs,
153 Change.create(:changeset => cs,
152 :action => action,
154 :action => action,
153 :path => scm.with_leading_slash(revision.paths[0][:path]),
155 :path => scm.with_leading_slash(revision.paths[0][:path]),
154 :revision => revision.paths[0][:revision],
156 :revision => revision.paths[0][:revision],
155 :branch => revision.paths[0][:branch]
157 :branch => revision.paths[0][:branch]
156 )
158 )
157 end
159 end
158 end
160 end
159
161
160 # Renumber new changesets in chronological order
162 # Renumber new changesets in chronological order
161 changesets.find(
163 changesets.find(
162 :all, :order => 'committed_on ASC, id ASC', :conditions => "revision LIKE 'tmp%'"
164 :all, :order => 'committed_on ASC, id ASC', :conditions => "revision LIKE 'tmp%'"
163 ).each do |changeset|
165 ).each do |changeset|
164 changeset.update_attribute :revision, next_revision_number
166 changeset.update_attribute :revision, next_revision_number
165 end
167 end
166 end # transaction
168 end # transaction
167 @current_revision_number = nil
169 @current_revision_number = nil
168 end
170 end
169
171
170 private
172 private
171
173
172 # Returns the next revision number to assign to a CVS changeset
174 # Returns the next revision number to assign to a CVS changeset
173 def next_revision_number
175 def next_revision_number
174 # Need to retrieve existing revision numbers to sort them as integers
176 # Need to retrieve existing revision numbers to sort them as integers
175 sql = "SELECT revision FROM #{Changeset.table_name} "
177 sql = "SELECT revision FROM #{Changeset.table_name} "
176 sql << "WHERE repository_id = #{id} AND revision NOT LIKE 'tmp%'"
178 sql << "WHERE repository_id = #{id} AND revision NOT LIKE 'tmp%'"
177 @current_revision_number ||= (connection.select_values(sql).collect(&:to_i).max || 0)
179 @current_revision_number ||= (connection.select_values(sql).collect(&:to_i).max || 0)
178 @current_revision_number += 1
180 @current_revision_number += 1
179 end
181 end
180 end
182 end
General Comments 0
You need to be logged in to leave comments. Login now