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