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