Revision 442:753f1380d6bc app/models/repository

View differences:

app/models/repository/.svn/entries
1 1
10
2 2

  
3 3
dir
4
4993
5
http://redmine.rubyforge.org/svn/trunk/app/models/repository
4
6000
5
http://redmine.rubyforge.org/svn/branches/1.2-stable/app/models/repository
6 6
http://redmine.rubyforge.org/svn
7 7

  
8 8

  
9 9

  
10
2011-03-01T10:27:30.170724Z
11
4982
10
2011-05-19T22:58:38.288878Z
11
5858
12 12
tmaruyama
13 13

  
14 14

  
......
32 32

  
33 33

  
34 34

  
35
2011-03-03T11:40:18.000000Z
36
b9f366b3f38bd42149e09e6ed0ed8755
37
2011-02-28T12:09:32.515358Z
38
4962
35
2011-06-06T13:18:33.000000Z
36
2950b88e98eed34048c7f007a8f7fb21
37
2011-05-12T07:15:39.740135Z
38
5751
39 39
tmaruyama
40 40
has-props
41 41

  
......
58 58

  
59 59

  
60 60

  
61
3358
61
3397
62 62

63 63
bazaar.rb
64 64
file
......
66 66

  
67 67

  
68 68

  
69
2011-03-03T11:40:18.000000Z
70
d6a230859a110341c0d64865248db51c
71
2011-03-01T10:27:30.170724Z
72
4982
69
2011-06-06T13:18:33.000000Z
70
d4568bac22baf6121a7ea8883b59c58c
71
2011-05-18T07:11:41.584755Z
72
5834
73 73
tmaruyama
74 74
has-props
75 75

  
......
92 92

  
93 93

  
94 94

  
95
3877
95
3916
96 96

97 97
git.rb
98 98
file
......
100 100

  
101 101

  
102 102

  
103
2011-03-03T11:40:18.000000Z
104
dfce133f28c5c85af0740865903d5320
105
2011-03-01T05:14:03.146872Z
106
4975
103
2011-06-06T13:18:33.000000Z
104
b12b4b9bf012b30d430ddabf73eb4962
105
2011-05-19T22:58:38.288878Z
106
5858
107 107
tmaruyama
108 108
has-props
109 109

  
......
126 126

  
127 127

  
128 128

  
129
4245
129
5213
130 130

131 131
mercurial.rb
132 132
file
......
134 134

  
135 135

  
136 136

  
137
2011-03-03T11:40:18.000000Z
138
d659744391dfa02d54481d4dd8752930
139
2011-03-01T05:14:03.146872Z
140
4975
137
2011-06-06T13:18:33.000000Z
138
c02be7ffad5bb78d0cc096a7f88c45fc
139
2011-05-12T07:52:14.217350Z
140
5756
141 141
tmaruyama
142 142
has-props
143 143

  
......
160 160

  
161 161

  
162 162

  
163
4022
163
5217
164 164

165 165
filesystem.rb
166 166
file
......
168 168

  
169 169

  
170 170

  
171
2011-03-03T11:40:18.000000Z
172
994276556c2feac05d149117eea01413
173
2011-03-01T05:14:03.146872Z
174
4975
171
2011-06-06T13:18:33.000000Z
172
a2170e3cb1161b0ea016414b724438f0
173
2011-05-12T07:41:08.517774Z
174
5754
175 175
tmaruyama
176 176
has-props
177 177

  
......
194 194

  
195 195

  
196 196

  
197
1451
197
1491
198 198

199 199
cvs.rb
200 200
file
......
202 202

  
203 203

  
204 204

  
205
2011-03-03T11:40:18.000000Z
206
5eecf7abe1216489c4d1c2f6a107c36b
207
2011-03-01T10:27:30.170724Z
208
4982
205
2011-06-06T13:18:33.000000Z
206
a5f74e302ec1d5d5d4a0677b6537c399
207
2011-05-12T07:16:20.564757Z
208
5753
209 209
tmaruyama
210 210
has-props
211 211

  
......
228 228

  
229 229

  
230 230

  
231
6952
231
7651
232 232

233 233
darcs.rb
234 234
file
......
236 236

  
237 237

  
238 238

  
239
2011-03-03T11:40:18.000000Z
240
03bf9128aa09528266cabb76ff0808a9
241
2011-03-01T10:27:30.170724Z
242
4982
239
2011-06-06T13:18:33.000000Z
240
5fa94193e544a8c9d94a2cb501a273de
241
2011-05-12T07:41:29.099665Z
242
5755
243 243
tmaruyama
244 244
has-props
245 245

  
......
262 262

  
263 263

  
264 264

  
265
3826
265
3881
266 266

app/models/repository/.svn/text-base/bazaar.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
21 21
  attr_protected :root_url
22 22
  validates_presence_of :url, :log_encoding
23 23

  
24
  ATTRIBUTE_KEY_NAMES = {
25
      "url"          => "Root directory",
26
      "log_encoding" => "Commit messages encoding",
27
    }
28 24
  def self.human_attribute_name(attribute_key_name)
29
    ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
25
    attr_name = attribute_key_name
26
    if attr_name == "url"
27
      attr_name = "path_to_repository"
28
    end
29
    super(attr_name)
30 30
  end
31 31

  
32 32
  def self.scm_adapter_class
......
47 47
          full_path = File.join(root_url, e.path)
48 48
          e.size = File.stat(full_path).size if File.file?(full_path)
49 49
        end
50
        c = Change.find(:first,
51
                        :include => :changeset,
52
                        :conditions => ["#{Change.table_name}.revision = ? and #{Changeset.table_name}.repository_id = ?", e.lastrev.revision, id],
53
                        :order => "#{Changeset.table_name}.revision DESC")
50
        c = Change.find(
51
               :first,
52
               :include    => :changeset,
53
               :conditions => [
54
                   "#{Change.table_name}.revision = ? and #{Changeset.table_name}.repository_id = ?",
55
                   e.lastrev.revision,
56
                   id
57
                   ],
58
               :order => "#{Changeset.table_name}.revision DESC")
54 59
        if c
55 60
          e.lastrev.identifier = c.changeset.revision
56
          e.lastrev.name = c.changeset.revision
57
          e.lastrev.author = c.changeset.committer
61
          e.lastrev.name       = c.changeset.revision
62
          e.lastrev.author     = c.changeset.committer
58 63
        end
59 64
      end
60 65
    end
61 66
  end
62
  
67

  
63 68
  def fetch_changesets
64 69
    scm_info = scm.info
65 70
    if scm_info
......
76 81
          revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
77 82
          transaction do
78 83
            revisions.reverse_each do |revision|
79
              changeset = Changeset.create(:repository => self,
80
                                           :revision => revision.identifier, 
81
                                           :committer => revision.author, 
84
              changeset = Changeset.create(:repository   => self,
85
                                           :revision     => revision.identifier,
86
                                           :committer    => revision.author,
82 87
                                           :committed_on => revision.time,
83
                                           :scmid => revision.scmid,
84
                                           :comments => revision.message)
85
              
88
                                           :scmid        => revision.scmid,
89
                                           :comments     => revision.message)
90

  
86 91
              revision.paths.each do |change|
87 92
                Change.create(:changeset => changeset,
88
                              :action => change[:action],
89
                              :path => change[:path],
90
                              :revision => change[:revision])
93
                              :action    => change[:action],
94
                              :path      => change[:path],
95
                              :revision  => change[:revision])
91 96
              end
92 97
            end
93 98
          end unless revisions.nil?
app/models/repository/.svn/text-base/cvs.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
21 21
class Repository::Cvs < Repository
22 22
  validates_presence_of :url, :root_url, :log_encoding
23 23

  
24
  ATTRIBUTE_KEY_NAMES = {
25
      "url"          => "CVSROOT",
26
      "root_url"     => "Module",
27
      "log_encoding" => "Commit messages encoding",
28
    }
29 24
  def self.human_attribute_name(attribute_key_name)
30
    ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
25
    attr_name = attribute_key_name
26
    if attr_name == "root_url"
27
      attr_name = "cvsroot"
28
    elsif attr_name == "url"
29
      attr_name = "cvs_module"
30
    end
31
    super(attr_name)
31 32
  end
32 33

  
33 34
  def self.scm_adapter_class
......
42 43
    rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
43 44
    scm.entry(path, rev.nil? ? nil : rev.committed_on)
44 45
  end
45
  
46

  
46 47
  def entries(path=nil, identifier=nil)
47
    rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
48
    rev = nil
49
    if ! identifier.nil?
50
      rev = changesets.find_by_revision(identifier)
51
      return nil if rev.nil?
52
    end
48 53
    entries = scm.entries(path, rev.nil? ? nil : rev.committed_on)
49 54
    if entries
50 55
      entries.each() do |entry|
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) )
56
        if ( ! entry.lastrev.nil? ) && ( ! entry.lastrev.revision.nil? )
57
          change=changes.find_by_revision_and_path(
58
                     entry.lastrev.revision,
59
                     scm.with_leading_slash(entry.path) )
53 60
          if change
54
            entry.lastrev.identifier=change.changeset.revision
55
            entry.lastrev.author=change.changeset.committer
56
            entry.lastrev.revision=change.revision
57
            entry.lastrev.branch=change.branch
61
            entry.lastrev.identifier = change.changeset.revision
62
            entry.lastrev.revision   = change.changeset.revision
63
            entry.lastrev.author     = change.changeset.committer
64
            # entry.lastrev.branch     = change.branch
58 65
          end
59 66
        end
60 67
      end
61 68
    end
62 69
    entries
63 70
  end
64
  
71

  
65 72
  def cat(path, identifier=nil)
66
    rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
73
    rev = nil
74
    if ! identifier.nil?
75
      rev = changesets.find_by_revision(identifier)
76
      return nil if rev.nil?
77
    end
67 78
    scm.cat(path, rev.nil? ? nil : rev.committed_on)
68 79
  end
69
  
80

  
81
  def annotate(path, identifier=nil)
82
    rev = nil
83
    if ! identifier.nil?
84
      rev = changesets.find_by_revision(identifier)
85
      return nil if rev.nil?
86
    end
87
    scm.annotate(path, rev.nil? ? nil : rev.committed_on)
88
  end
89

  
70 90
  def diff(path, rev, rev_to)
71
    #convert rev to revision. CVS can't handle changesets here
91
    # convert rev to revision. CVS can't handle changesets here
72 92
    diff=[]
73
    changeset_from=changesets.find_by_revision(rev)
74
    if rev_to.to_i > 0 
75
      changeset_to=changesets.find_by_revision(rev_to)
93
    changeset_from = changesets.find_by_revision(rev)
94
    if rev_to.to_i > 0
95
      changeset_to = changesets.find_by_revision(rev_to)
76 96
    end
77 97
    changeset_from.changes.each() do |change_from|
78
      
79
      revision_from=nil
80
      revision_to=nil      
81
      
82
      revision_from=change_from.revision if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
83
      
98
      revision_from = nil
99
      revision_to   = nil
100
      if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
101
        revision_from = change_from.revision
102
      end
84 103
      if revision_from
85 104
        if changeset_to
86 105
          changeset_to.changes.each() do |change_to|
87
            revision_to=change_to.revision if change_to.path==change_from.path 
106
            revision_to = change_to.revision if change_to.path == change_from.path
88 107
          end
89 108
        end
90 109
        unless revision_to
91
          revision_to=scm.get_previous_revision(revision_from)
110
          revision_to = scm.get_previous_revision(revision_from)
92 111
        end
93 112
        file_diff = scm.diff(change_from.path, revision_from, revision_to)
94 113
        diff = diff + file_diff unless file_diff.nil?
......
96 115
    end
97 116
    return diff
98 117
  end
99
  
118

  
100 119
  def fetch_changesets
101 120
    # 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.
121
    # natively cvs doesn't provide any kind of changesets,
122
    # there is only a revision per file.
103 123
    # we now take a guess using the author, the commitlog and the commit-date.
104
    
105
    # last one is the next step to take. the commit-date is not equal for all 
124

  
125
    # last one is the next step to take. the commit-date is not equal for all
106 126
    # commits in one changeset. cvs update the commit-date when the *,v file was touched. so
107 127
    # we use a small delta here, to merge all changes belonging to _one_ changeset
108
    time_delta=10.seconds
109
    
128
    time_delta  = 10.seconds
110 129
    fetch_since = latest_changeset ? latest_changeset.committed_on : nil
111 130
    transaction do
112 131
      tmp_rev_num = 1
113
      scm.revisions('', fetch_since, nil, :with_paths => true) do |revision|
132
      scm.revisions('', fetch_since, nil, :log_encoding => repo_log_encoding) do |revision|
114 133
        # only add the change to the database, if it doen't exists. the cvs log
115
        # is not exclusive at all. 
134
        # is not exclusive at all.
116 135
        tmp_time = revision.time.clone
117 136
        unless changes.find_by_path_and_revision(
118
	           scm.with_leading_slash(revision.paths[0][:path]), revision.paths[0][:revision])
137
	                         scm.with_leading_slash(revision.paths[0][:path]),
138
	                         revision.paths[0][:revision]
139
	                           )
119 140
          cmt = Changeset.normalize_comments(revision.message, repo_log_encoding)
120
          cs = changesets.find(:first, :conditions=>{
121
            :committed_on=>tmp_time - time_delta .. tmp_time + time_delta,
122
            :committer=>revision.author,
123
            :comments=>cmt
124
          })
125
        
126
          # create a new changeset.... 
141
          author_utf8 = Changeset.to_utf8(revision.author, repo_log_encoding)
142
          cs  = changesets.find(
143
            :first,
144
            :conditions => {
145
                :committed_on => tmp_time - time_delta .. tmp_time + time_delta,
146
                :committer    => author_utf8,
147
                :comments     => cmt
148
                }
149
             )
150
          # create a new changeset....
127 151
          unless cs
128 152
            # we use a temporaray revision number here (just for inserting)
129 153
            # later on, we calculate a continous positive number
130 154
            tmp_time2 = tmp_time.clone.gmtime
131
            branch = revision.paths[0][:branch]
132
            scmid = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S")
133
            cs = Changeset.create(:repository => self,
134
                                  :revision => "tmp#{tmp_rev_num}",
135
                                  :scmid => scmid,
136
                                  :committer => revision.author, 
155
            branch    = revision.paths[0][:branch]
156
            scmid     = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S")
157
            cs = Changeset.create(:repository   => self,
158
                                  :revision     => "tmp#{tmp_rev_num}",
159
                                  :scmid        => scmid,
160
                                  :committer    => revision.author,
137 161
                                  :committed_on => tmp_time,
138
                                  :comments => revision.message)
162
                                  :comments     => revision.message)
139 163
            tmp_rev_num += 1
140 164
          end
141
        
142
          #convert CVS-File-States to internal Action-abbrevations
143
          #default action is (M)odified
144
          action="M"
145
          if revision.paths[0][:action]=="Exp" && revision.paths[0][:revision]=="1.1"
146
            action="A" #add-action always at first revision (= 1.1)
147
          elsif revision.paths[0][:action]=="dead"
148
            action="D" #dead-state is similar to Delete
165
          # convert CVS-File-States to internal Action-abbrevations
166
          # default action is (M)odified
167
          action = "M"
168
          if revision.paths[0][:action] == "Exp" && revision.paths[0][:revision] == "1.1"
169
            action = "A" # add-action always at first revision (= 1.1)
170
          elsif revision.paths[0][:action] == "dead"
171
            action = "D" # dead-state is similar to Delete
149 172
          end
150
        
151
          Change.create(:changeset => cs,
152
          :action => action,
153
          :path => scm.with_leading_slash(revision.paths[0][:path]),
154
          :revision => revision.paths[0][:revision],
155
          :branch => revision.paths[0][:branch]
156
          )
173
          Change.create(
174
             :changeset => cs,
175
             :action    => action,
176
             :path      => scm.with_leading_slash(revision.paths[0][:path]),
177
             :revision  => revision.paths[0][:revision],
178
             :branch    => revision.paths[0][:branch]
179
              )
157 180
        end
158 181
      end
159
      
182

  
160 183
      # Renumber new changesets in chronological order
161 184
      changesets.find(
162
              :all, :order => 'committed_on ASC, id ASC', :conditions => "revision LIKE 'tmp%'"
185
              :all,
186
              :order => 'committed_on ASC, id ASC',
187
              :conditions => "revision LIKE 'tmp%'"
163 188
           ).each do |changeset|
164 189
        changeset.update_attribute :revision, next_revision_number
165 190
      end
166 191
    end # transaction
167 192
    @current_revision_number = nil
168 193
  end
169
  
194

  
170 195
  private
171
  
196

  
172 197
  # Returns the next revision number to assign to a CVS changeset
173 198
  def next_revision_number
174 199
    # Need to retrieve existing revision numbers to sort them as integers
app/models/repository/.svn/text-base/darcs.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
20 20
class Repository::Darcs < Repository
21 21
  validates_presence_of :url, :log_encoding
22 22

  
23
  ATTRIBUTE_KEY_NAMES = {
24
      "url"          => "Root directory",
25
      "log_encoding" => "Commit messages encoding",
26
    }
27 23
  def self.human_attribute_name(attribute_key_name)
28
    ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
24
    attr_name = attribute_key_name
25
    if attr_name == "url"
26
      attr_name = "path_to_repository"
27
    end
28
    super(attr_name)
29 29
  end
30 30

  
31 31
  def self.scm_adapter_class
......
36 36
    'Darcs'
37 37
  end
38 38

  
39
  def supports_directory_revisions?
40
    true
41
  end
42

  
39 43
  def entry(path=nil, identifier=nil)
40 44
    patch = identifier.nil? ? nil : changesets.find_by_revision(identifier)
41 45
    scm.entry(path, patch.nil? ? nil : patch.scmid)
42 46
  end
43
  
47

  
44 48
  def entries(path=nil, identifier=nil)
45
    patch = identifier.nil? ? nil : changesets.find_by_revision(identifier)
49
    patch = nil
50
    if ! identifier.nil?
51
      patch = changesets.find_by_revision(identifier)
52
      return nil if patch.nil?
53
    end
46 54
    entries = scm.entries(path, patch.nil? ? nil : patch.scmid)
47 55
    if entries
48 56
      entries.each do |entry|
49 57
        # Search the DB for the entry's last change
50
        changeset = changesets.find_by_scmid(entry.lastrev.scmid) if entry.lastrev && !entry.lastrev.scmid.blank?
58
        if entry.lastrev && !entry.lastrev.scmid.blank?
59
          changeset = changesets.find_by_scmid(entry.lastrev.scmid)
60
        end
51 61
        if changeset
52 62
          entry.lastrev.identifier = changeset.revision
53
          entry.lastrev.name = changeset.revision
54
          entry.lastrev.time = changeset.committed_on
55
          entry.lastrev.author = changeset.committer
63
          entry.lastrev.name       = changeset.revision
64
          entry.lastrev.time       = changeset.committed_on
65
          entry.lastrev.author     = changeset.committer
56 66
        end
57 67
      end
58 68
    end
59 69
    entries
60 70
  end
61
  
71

  
62 72
  def cat(path, identifier=nil)
63 73
    patch = identifier.nil? ? nil : changesets.find_by_revision(identifier.to_s)
64 74
    scm.cat(path, patch.nil? ? nil : patch.scmid)
65 75
  end
66
  
76

  
67 77
  def diff(path, rev, rev_to)
68 78
    patch_from = changesets.find_by_revision(rev)
69 79
    return nil if patch_from.nil?
......
73 83
    end
74 84
    patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil) : nil
75 85
  end
76
  
86

  
77 87
  def fetch_changesets
78 88
    scm_info = scm.info
79 89
    if scm_info
80 90
      db_last_id = latest_changeset ? latest_changeset.scmid : nil
81
      next_rev = latest_changeset ? latest_changeset.revision.to_i + 1 : 1      
91
      next_rev   = latest_changeset ? latest_changeset.revision.to_i + 1 : 1
82 92
      # latest revision in the repository
83
      scm_revision = scm_info.lastrev.scmid      
93
      scm_revision = scm_info.lastrev.scmid
84 94
      unless changesets.find_by_scmid(scm_revision)
85 95
        revisions = scm.revisions('', db_last_id, nil, :with_path => true)
86 96
        transaction do
87 97
          revisions.reverse_each do |revision|
88
            changeset = Changeset.create(:repository => self,
89
                                         :revision => next_rev,
90
                                         :scmid => revision.scmid,
91
                                         :committer => revision.author, 
98
            changeset = Changeset.create(:repository   => self,
99
                                         :revision     => next_rev,
100
                                         :scmid        => revision.scmid,
101
                                         :committer    => revision.author,
92 102
                                         :committed_on => revision.time,
93
                                         :comments => revision.message)
94
                                         
103
                                         :comments     => revision.message)
95 104
            revision.paths.each do |change|
96 105
              changeset.create_change(change)
97 106
            end
app/models/repository/.svn/text-base/filesystem.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# FileSystem adapter
5 5
# File written by Paul Rivier, at Demotera.
......
8 8
# modify it under the terms of the GNU General Public License
9 9
# as published by the Free Software Foundation; either version 2
10 10
# of the License, or (at your option) any later version.
11
# 
11
#
12 12
# This program is distributed in the hope that it will be useful,
13 13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14 14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 15
# GNU General Public License for more details.
16
# 
16
#
17 17
# You should have received a copy of the GNU General Public License
18 18
# along with this program; if not, write to the Free Software
19 19
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
24 24
  attr_protected :root_url
25 25
  validates_presence_of :url
26 26

  
27
  ATTRIBUTE_KEY_NAMES = {
28
      "url"          => "Root directory",
29
    }
30 27
  def self.human_attribute_name(attribute_key_name)
31
    ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
28
    attr_name = attribute_key_name
29
    if attr_name == "url"
30
      attr_name = "root_directory"
31
    end
32
    super(attr_name)
32 33
  end
33 34

  
34 35
  def self.scm_adapter_class
......
39 40
    'Filesystem'
40 41
  end
41 42

  
43
  def supports_all_revisions?
44
    false
45
  end
46

  
42 47
  def entries(path=nil, identifier=nil)
43 48
    scm.entries(path, identifier)
44 49
  end
......
46 51
  def fetch_changesets
47 52
    nil
48 53
  end
49
  
50 54
end
app/models/repository/.svn/text-base/git.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
# Copyright (C) 2007  Patrick Aljord patcito@ŋmail.com
4
#
4 5
# This program is free software; you can redistribute it and/or
5 6
# modify it under the terms of the GNU General Public License
6 7
# as published by the Free Software Foundation; either version 2
7 8
# of the License, or (at your option) any later version.
8
# 
9
#
9 10
# This program is distributed in the hope that it will be useful,
10 11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 13
# GNU General Public License for more details.
13
# 
14
#
14 15
# You should have received a copy of the GNU General Public License
15 16
# along with this program; if not, write to the Free Software
16 17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
21 22
  attr_protected :root_url
22 23
  validates_presence_of :url
23 24

  
24
  ATTRIBUTE_KEY_NAMES = {
25
      "url"          => "Path to repository",
26
    }
27 25
  def self.human_attribute_name(attribute_key_name)
28
    ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
26
    attr_name = attribute_key_name
27
    if attr_name == "url"
28
      attr_name = "path_to_repository"
29
    end
30
    super(attr_name)
29 31
  end
30 32

  
31 33
  def self.scm_adapter_class
......
36 38
    'Git'
37 39
  end
38 40

  
41
  def report_last_commit
42
    extra_report_last_commit
43
  end
44

  
45
  def extra_report_last_commit
46
    return false if extra_info.nil?
47
    v = extra_info["extra_report_last_commit"]
48
    return false if v.nil?
49
    v.to_s != '0'
50
  end
51

  
52
  def supports_directory_revisions?
53
    true
54
  end
55

  
39 56
  def repo_log_encoding
40 57
    'UTF-8'
41 58
  end
......
65 82
    changesets.find(:first, :conditions => ['scmid LIKE ?', "#{name}%"])
66 83
  end
67 84

  
68
  # With SCM's that have a sequential commit numbering, redmine is able to be
69
  # clever and only fetch changesets going forward from the most recent one
70
  # it knows about.  However, with git, you never know if people have merged
71
  # commits into the middle of the repository history, so we should parse
72
  # the entire log. Since it's way too slow for large repositories, we only
73
  # parse 1 week before the last known commit.
85
  def entries(path=nil, identifier=nil)
86
    scm.entries(path,
87
                identifier,
88
                options = {:report_last_commit => extra_report_last_commit})
89
  end
90

  
91
  # In Git and Mercurial, revisions are not in date order.
92
  # Redmine Mercurial fixed issues.
93
  #    * Redmine Takes Too Long On Large Mercurial Repository
94
  #      http://www.redmine.org/issues/3449
95
  #    * Sorting for changesets might go wrong on Mercurial repos
96
  #      http://www.redmine.org/issues/3567
97
  #
98
  # Database revision column is text, so Redmine can not sort by revision.
99
  # Mercurial has revision number, and revision number guarantees revision order.
100
  # Redmine Mercurial model stored revisions ordered by database id to database.
101
  # So, Redmine Mercurial model can use correct ordering revisions.
102
  #
103
  # Redmine Mercurial adapter uses "hg log -r 0:tip --limit 10"
104
  # to get limited revisions from old to new.
105
  # But, Git 1.7.3.4 does not support --reverse with -n or --skip.
106
  #
74 107
  # The repository can still be fully reloaded by calling #clear_changesets
75 108
  # before fetching changesets (eg. for offline resync)
76 109
  def fetch_changesets
77
    c = changesets.find(:first, :order => 'committed_on DESC')
78
    since = (c ? c.committed_on - 7.days : nil)
79

  
80
    revisions = scm.revisions('', nil, nil, :all => true, :since => since)
81
    return if revisions.nil? || revisions.empty?
82

  
83
    recent_changesets = changesets.find(:all, :conditions => ['committed_on >= ?', since])
84

  
85
    # Clean out revisions that are no longer in git
86
    recent_changesets.each {|c| c.destroy unless revisions.detect {|r| r.scmid.to_s == c.scmid.to_s }}
87

  
88
    # Subtract revisions that redmine already knows about
89
    recent_revisions = recent_changesets.map{|c| c.scmid}
90
    revisions.reject!{|r| recent_revisions.include?(r.scmid)}
91

  
92
    # Save the remaining ones to the database
93
    unless revisions.nil?
94
      revisions.each do |rev|
110
    scm_brs = branches
111
    return if scm_brs.nil? || scm_brs.empty?
112
    h1 = extra_info || {}
113
    h  = h1.dup
114
    h["branches"]       ||= {}
115
    h["db_consistent"]  ||= {}
116
    if changesets.count == 0
117
      h["db_consistent"]["ordering"] = 1
118
      merge_extra_info(h)
119
      self.save
120
    elsif ! h["db_consistent"].has_key?("ordering")
121
      h["db_consistent"]["ordering"] = 0
122
      merge_extra_info(h)
123
      self.save
124
    end
125
    scm_brs.each do |br|
126
      from_scmid = nil
127
      from_scmid = h["branches"][br]["last_scmid"] if h["branches"][br]
128
      h["branches"][br] ||= {}
129
      scm.revisions('', from_scmid, br, {:reverse => true}) do |rev|
130
        db_rev = find_changeset_by_name(rev.revision)
95 131
        transaction do
96
          changeset = Changeset.new(
97
              :repository => self,
98
              :revision   => rev.identifier,
99
              :scmid      => rev.scmid,
100
              :committer  => rev.author, 
101
              :committed_on => rev.time,
102
              :comments   => rev.message)
103
            
104
          if changeset.save
105
            rev.paths.each do |file|
106
              Change.create(
107
                  :changeset => changeset,
108
                  :action    => file[:action],
109
                  :path      => file[:path])
110
            end
132
          if db_rev.nil?
133
            save_revision(rev)
111 134
          end
135
          h["branches"][br]["last_scmid"] = rev.scmid
136
          merge_extra_info(h)
137
          self.save
112 138
        end
113 139
      end
114 140
    end
115 141
  end
116 142

  
143
  def save_revision(rev)
144
    changeset = Changeset.new(
145
              :repository   => self,
146
              :revision     => rev.identifier,
147
              :scmid        => rev.scmid,
148
              :committer    => rev.author,
149
              :committed_on => rev.time,
150
              :comments     => rev.message
151
              )
152
    if changeset.save
153
      rev.paths.each do |file|
154
        Change.create(
155
                  :changeset => changeset,
156
                  :action    => file[:action],
157
                  :path      => file[:path])
158
      end
159
    end
160
  end
161
  private :save_revision
162

  
117 163
  def latest_changesets(path,rev,limit=10)
118 164
    revisions = scm.revisions(path, nil, rev, :limit => limit, :all => false)
119 165
    return [] if revisions.nil? || revisions.empty?
120 166

  
121 167
    changesets.find(
122
      :all, 
168
      :all,
123 169
      :conditions => [
124
        "scmid IN (?)", 
170
        "scmid IN (?)",
125 171
        revisions.map!{|c| c.scmid}
126 172
      ],
127 173
      :order => 'committed_on DESC'
app/models/repository/.svn/text-base/mercurial.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
26 26

  
27 27
  FETCH_AT_ONCE = 100  # number of changesets to fetch at once
28 28

  
29
  ATTRIBUTE_KEY_NAMES = {
30
      "url"          => "Root directory",
31
    }
32 29
  def self.human_attribute_name(attribute_key_name)
33
    ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
30
    attr_name = attribute_key_name
31
    if attr_name == "url"
32
      attr_name = "path_to_repository"
33
    end
34
    super(attr_name)
34 35
  end
35 36

  
36 37
  def self.scm_adapter_class
......
41 42
    'Mercurial'
42 43
  end
43 44

  
45
  def supports_directory_revisions?
46
    true
47
  end
48

  
44 49
  def repo_log_encoding
45 50
    'UTF-8'
46 51
  end
......
55 60
    changeset.scmid
56 61
  end
57 62

  
58
  def branches
59
    nil
60
  end
61

  
62
  def tags
63
    nil
64
  end
65

  
66 63
  def diff_format_revisions(cs, cs_to, sep=':')
67 64
    super(cs, cs_to, ' ')
68 65
  end
......
80 77
  end
81 78

  
82 79
  # Returns the latest changesets for +path+; sorted by revision number
83
  # Default behavior is to search in cached changesets
80
  #
81
  # Because :order => 'id DESC' is defined at 'has_many',
82
  # there is no need to set 'order'.
83
  # But, MySQL test fails.
84
  # Sqlite3 and PostgreSQL pass.
85
  # Is this MySQL bug?
84 86
  def latest_changesets(path, rev, limit=10)
85
    if path.blank?
86
      changesets.find(:all, :include => :user, :limit => limit)
87
    else
88
      changesets.find(:all, :select => "DISTINCT #{Changeset.table_name}.*",
89
                      :joins => :changes,
90
                      :conditions => ["#{Change.table_name}.path = ? OR #{Change.table_name}.path LIKE ? ESCAPE ?",
91
                                      path.with_leading_slash,
92
                                      "#{path.with_leading_slash.gsub(/[%_\\]/) { |s| "\\#{s}" }}/%", '\\'],
93
                      :include => :user, :limit => limit)
87
    changesets.find(:all, :include => :user,
88
                    :conditions => latest_changesets_cond(path, rev, limit),
89
                    :limit => limit, :order => "#{Changeset.table_name}.id DESC")
90
  end
91

  
92
  def latest_changesets_cond(path, rev, limit)
93
    cond, args = [], []
94
    if scm.branchmap.member? rev
95
      # Mercurial named branch is *stable* in each revision.
96
      # So, named branch can be stored in database.
97
      # Mercurial provides *bookmark* which is equivalent with git branch.
98
      # But, bookmark is not implemented.
99
      cond << "#{Changeset.table_name}.scmid IN (?)"
100
      # Revisions in root directory and sub directory are not equal.
101
      # So, in order to get correct limit, we need to get all revisions.
102
      # But, it is very heavy.
103
      # Mercurial does not treat direcotry.
104
      # So, "hg log DIR" is very heavy.
105
      branch_limit = path.blank? ? limit : ( limit * 5 )
106
      args << scm.nodes_in_branch(rev, :limit => branch_limit)
107
    elsif last = rev ? find_changeset_by_name(scm.tagmap[rev] || rev) : nil
108
      cond << "#{Changeset.table_name}.id <= ?"
109
      args << last.id
94 110
    end
111

  
112
    unless path.blank?
113
      cond << "EXISTS (SELECT * FROM #{Change.table_name}
114
                 WHERE #{Change.table_name}.changeset_id = #{Changeset.table_name}.id
115
                 AND (#{Change.table_name}.path = ?
116
                       OR #{Change.table_name}.path LIKE ? ESCAPE ?))"
117
      args << path.with_leading_slash
118
      args << "#{path.with_leading_slash.gsub(/[%_\\]/) { |s| "\\#{s}" }}/%" << '\\'
119
    end
120

  
121
    [cond.join(' AND '), *args] unless cond.empty?
95 122
  end
123
  private :latest_changesets_cond
96 124

  
97 125
  def fetch_changesets
98 126
    scm_rev = scm.info.lastrev.revision.to_i
app/models/repository/.svn/text-base/subversion.rb.svn-base
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
30 30
    'Subversion'
31 31
  end
32 32

  
33
  def supports_directory_revisions?
34
    true
35
  end
36

  
33 37
  def repo_log_encoding
34 38
    'UTF-8'
35 39
  end
......
38 42
    revisions = scm.revisions(path, rev, nil, :limit => limit)
39 43
    revisions ? changesets.find_all_by_revision(revisions.collect(&:identifier), :order => "committed_on DESC", :include => :user) : []
40 44
  end
41
  
45

  
42 46
  # Returns a path relative to the url of the repository
43 47
  def relative_path(path)
44 48
    path.gsub(Regexp.new("^\/?#{Regexp.escape(relative_url)}"), '')
45 49
  end
46
  
50

  
47 51
  def fetch_changesets
48 52
    scm_info = scm.info
49 53
    if scm_info
......
60 64
          revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
61 65
          revisions.reverse_each do |revision|
62 66
            transaction do
63
              changeset = Changeset.create(:repository => self,
64
                                           :revision => revision.identifier, 
65
                                           :committer => revision.author, 
67
              changeset = Changeset.create(:repository   => self,
68
                                           :revision     => revision.identifier,
69
                                           :committer    => revision.author,
66 70
                                           :committed_on => revision.time,
67
                                           :comments => revision.message)
68
              
71
                                           :comments     => revision.message)
72

  
69 73
              revision.paths.each do |change|
70 74
                changeset.create_change(change)
71 75
              end unless changeset.new_record?
......
76 80
      end
77 81
    end
78 82
  end
79
  
83

  
80 84
  private
81
  
85

  
82 86
  # Returns the relative url of the repository
83 87
  # Eg: root_url = file:///var/svn/foo
84 88
  #     url      = file:///var/svn/foo/bar
app/models/repository/bazaar.rb
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
21 21
  attr_protected :root_url
22 22
  validates_presence_of :url, :log_encoding
23 23

  
24
  ATTRIBUTE_KEY_NAMES = {
25
      "url"          => "Root directory",
26
      "log_encoding" => "Commit messages encoding",
27
    }
28 24
  def self.human_attribute_name(attribute_key_name)
29
    ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
25
    attr_name = attribute_key_name
26
    if attr_name == "url"
27
      attr_name = "path_to_repository"
28
    end
29
    super(attr_name)
30 30
  end
31 31

  
32 32
  def self.scm_adapter_class
......
47 47
          full_path = File.join(root_url, e.path)
48 48
          e.size = File.stat(full_path).size if File.file?(full_path)
49 49
        end
50
        c = Change.find(:first,
51
                        :include => :changeset,
52
                        :conditions => ["#{Change.table_name}.revision = ? and #{Changeset.table_name}.repository_id = ?", e.lastrev.revision, id],
53
                        :order => "#{Changeset.table_name}.revision DESC")
50
        c = Change.find(
51
               :first,
52
               :include    => :changeset,
53
               :conditions => [
54
                   "#{Change.table_name}.revision = ? and #{Changeset.table_name}.repository_id = ?",
55
                   e.lastrev.revision,
56
                   id
57
                   ],
58
               :order => "#{Changeset.table_name}.revision DESC")
54 59
        if c
55 60
          e.lastrev.identifier = c.changeset.revision
56
          e.lastrev.name = c.changeset.revision
57
          e.lastrev.author = c.changeset.committer
61
          e.lastrev.name       = c.changeset.revision
62
          e.lastrev.author     = c.changeset.committer
58 63
        end
59 64
      end
60 65
    end
61 66
  end
62
  
67

  
63 68
  def fetch_changesets
64 69
    scm_info = scm.info
65 70
    if scm_info
......
76 81
          revisions = scm.revisions('', identifier_to, identifier_from, :with_paths => true)
77 82
          transaction do
78 83
            revisions.reverse_each do |revision|
79
              changeset = Changeset.create(:repository => self,
80
                                           :revision => revision.identifier, 
81
                                           :committer => revision.author, 
84
              changeset = Changeset.create(:repository   => self,
85
                                           :revision     => revision.identifier,
86
                                           :committer    => revision.author,
82 87
                                           :committed_on => revision.time,
83
                                           :scmid => revision.scmid,
84
                                           :comments => revision.message)
85
              
88
                                           :scmid        => revision.scmid,
89
                                           :comments     => revision.message)
90

  
86 91
              revision.paths.each do |change|
87 92
                Change.create(:changeset => changeset,
88
                              :action => change[:action],
89
                              :path => change[:path],
90
                              :revision => change[:revision])
93
                              :action    => change[:action],
94
                              :path      => change[:path],
95
                              :revision  => change[:revision])
91 96
              end
92 97
            end
93 98
          end unless revisions.nil?
app/models/repository/cvs.rb
1
# redMine - project management software
2
# Copyright (C) 2006-2007  Jean-Philippe Lang
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3 3
#
4 4
# This program is free software; you can redistribute it and/or
5 5
# modify it under the terms of the GNU General Public License
6 6
# as published by the Free Software Foundation; either version 2
7 7
# of the License, or (at your option) any later version.
8
# 
8
#
9 9
# This program is distributed in the hope that it will be useful,
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU General Public License for more details.
13
# 
13
#
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
......
21 21
class Repository::Cvs < Repository
22 22
  validates_presence_of :url, :root_url, :log_encoding
23 23

  
24
  ATTRIBUTE_KEY_NAMES = {
25
      "url"          => "CVSROOT",
26
      "root_url"     => "Module",
27
      "log_encoding" => "Commit messages encoding",
28
    }
29 24
  def self.human_attribute_name(attribute_key_name)
30
    ATTRIBUTE_KEY_NAMES[attribute_key_name] || super
25
    attr_name = attribute_key_name
26
    if attr_name == "root_url"
27
      attr_name = "cvsroot"
28
    elsif attr_name == "url"
29
      attr_name = "cvs_module"
30
    end
31
    super(attr_name)
31 32
  end
32 33

  
33 34
  def self.scm_adapter_class
......
42 43
    rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
43 44
    scm.entry(path, rev.nil? ? nil : rev.committed_on)
44 45
  end
45
  
46

  
46 47
  def entries(path=nil, identifier=nil)
47
    rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
48
    rev = nil
49
    if ! identifier.nil?
50
      rev = changesets.find_by_revision(identifier)
51
      return nil if rev.nil?
52
    end
48 53
    entries = scm.entries(path, rev.nil? ? nil : rev.committed_on)
49 54
    if entries
50 55
      entries.each() do |entry|
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) )
56
        if ( ! entry.lastrev.nil? ) && ( ! entry.lastrev.revision.nil? )
57
          change=changes.find_by_revision_and_path(
58
                     entry.lastrev.revision,
59
                     scm.with_leading_slash(entry.path) )
53 60
          if change
54
            entry.lastrev.identifier=change.changeset.revision
55
            entry.lastrev.author=change.changeset.committer
56
            entry.lastrev.revision=change.revision
57
            entry.lastrev.branch=change.branch
61
            entry.lastrev.identifier = change.changeset.revision
62
            entry.lastrev.revision   = change.changeset.revision
63
            entry.lastrev.author     = change.changeset.committer
64
            # entry.lastrev.branch     = change.branch
58 65
          end
59 66
        end
60 67
      end
61 68
    end
62 69
    entries
63 70
  end
64
  
71

  
65 72
  def cat(path, identifier=nil)
66
    rev = identifier.nil? ? nil : changesets.find_by_revision(identifier)
73
    rev = nil
74
    if ! identifier.nil?
75
      rev = changesets.find_by_revision(identifier)
76
      return nil if rev.nil?
77
    end
67 78
    scm.cat(path, rev.nil? ? nil : rev.committed_on)
68 79
  end
69
  
80

  
81
  def annotate(path, identifier=nil)
82
    rev = nil
83
    if ! identifier.nil?
84
      rev = changesets.find_by_revision(identifier)
85
      return nil if rev.nil?
86
    end
87
    scm.annotate(path, rev.nil? ? nil : rev.committed_on)
88
  end
89

  
70 90
  def diff(path, rev, rev_to)
71
    #convert rev to revision. CVS can't handle changesets here
91
    # convert rev to revision. CVS can't handle changesets here
72 92
    diff=[]
73
    changeset_from=changesets.find_by_revision(rev)
74
    if rev_to.to_i > 0 
75
      changeset_to=changesets.find_by_revision(rev_to)
93
    changeset_from = changesets.find_by_revision(rev)
94
    if rev_to.to_i > 0
95
      changeset_to = changesets.find_by_revision(rev_to)
76 96
    end
77 97
    changeset_from.changes.each() do |change_from|
78
      
79
      revision_from=nil
80
      revision_to=nil      
81
      
82
      revision_from=change_from.revision if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
83
      
98
      revision_from = nil
99
      revision_to   = nil
100
      if path.nil? || (change_from.path.starts_with? scm.with_leading_slash(path))
101
        revision_from = change_from.revision
102
      end
84 103
      if revision_from
85 104
        if changeset_to
86 105
          changeset_to.changes.each() do |change_to|
87
            revision_to=change_to.revision if change_to.path==change_from.path 
106
            revision_to = change_to.revision if change_to.path == change_from.path
88 107
          end
89 108
        end
90 109
        unless revision_to
91
          revision_to=scm.get_previous_revision(revision_from)
110
          revision_to = scm.get_previous_revision(revision_from)
92 111
        end
93 112
        file_diff = scm.diff(change_from.path, revision_from, revision_to)
94 113
        diff = diff + file_diff unless file_diff.nil?
......
96 115
    end
97 116
    return diff
98 117
  end
99
  
118

  
100 119
  def fetch_changesets
101 120
    # 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.
121
    # natively cvs doesn't provide any kind of changesets,
122
    # there is only a revision per file.
103 123
    # we now take a guess using the author, the commitlog and the commit-date.
104
    
105
    # last one is the next step to take. the commit-date is not equal for all 
124

  
125
    # last one is the next step to take. the commit-date is not equal for all
106 126
    # commits in one changeset. cvs update the commit-date when the *,v file was touched. so
107 127
    # we use a small delta here, to merge all changes belonging to _one_ changeset
108
    time_delta=10.seconds
109
    
128
    time_delta  = 10.seconds
110 129
    fetch_since = latest_changeset ? latest_changeset.committed_on : nil
111 130
    transaction do
112 131
      tmp_rev_num = 1
113
      scm.revisions('', fetch_since, nil, :with_paths => true) do |revision|
132
      scm.revisions('', fetch_since, nil, :log_encoding => repo_log_encoding) do |revision|
114 133
        # only add the change to the database, if it doen't exists. the cvs log
115
        # is not exclusive at all. 
134
        # is not exclusive at all.
116 135
        tmp_time = revision.time.clone
117 136
        unless changes.find_by_path_and_revision(
118
	           scm.with_leading_slash(revision.paths[0][:path]), revision.paths[0][:revision])
137
	                         scm.with_leading_slash(revision.paths[0][:path]),
138
	                         revision.paths[0][:revision]
139
	                           )
119 140
          cmt = Changeset.normalize_comments(revision.message, repo_log_encoding)
120
          cs = changesets.find(:first, :conditions=>{
121
            :committed_on=>tmp_time - time_delta .. tmp_time + time_delta,
122
            :committer=>revision.author,
123
            :comments=>cmt
124
          })
125
        
126
          # create a new changeset.... 
141
          author_utf8 = Changeset.to_utf8(revision.author, repo_log_encoding)
142
          cs  = changesets.find(
143
            :first,
144
            :conditions => {
145
                :committed_on => tmp_time - time_delta .. tmp_time + time_delta,
146
                :committer    => author_utf8,
147
                :comments     => cmt
148
                }
149
             )
150
          # create a new changeset....
127 151
          unless cs
128 152
            # we use a temporaray revision number here (just for inserting)
129 153
            # later on, we calculate a continous positive number
130 154
            tmp_time2 = tmp_time.clone.gmtime
131
            branch = revision.paths[0][:branch]
132
            scmid = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S")
133
            cs = Changeset.create(:repository => self,
134
                                  :revision => "tmp#{tmp_rev_num}",
135
                                  :scmid => scmid,
136
                                  :committer => revision.author, 
155
            branch    = revision.paths[0][:branch]
156
            scmid     = branch + "-" + tmp_time2.strftime("%Y%m%d-%H%M%S")
157
            cs = Changeset.create(:repository   => self,
158
                                  :revision     => "tmp#{tmp_rev_num}",
159
                                  :scmid        => scmid,
160
                                  :committer    => revision.author,
137 161
                                  :committed_on => tmp_time,
138
                                  :comments => revision.message)
162
                                  :comments     => revision.message)
139 163
            tmp_rev_num += 1
140 164
          end
141
        
142
          #convert CVS-File-States to internal Action-abbrevations
143
          #default action is (M)odified
144
          action="M"
145
          if revision.paths[0][:action]=="Exp" && revision.paths[0][:revision]=="1.1"
146
            action="A" #add-action always at first revision (= 1.1)
147
          elsif revision.paths[0][:action]=="dead"
148
            action="D" #dead-state is similar to Delete
165
          # convert CVS-File-States to internal Action-abbrevations
166
          # default action is (M)odified
167
          action = "M"
168
          if revision.paths[0][:action] == "Exp" && revision.paths[0][:revision] == "1.1"
169
            action = "A" # add-action always at first revision (= 1.1)
170
          elsif revision.paths[0][:action] == "dead"
171
            action = "D" # dead-state is similar to Delete
149 172
          end
150
        
151
          Change.create(:changeset => cs,
152
          :action => action,
153
          :path => scm.with_leading_slash(revision.paths[0][:path]),
154
          :revision => revision.paths[0][:revision],
155
          :branch => revision.paths[0][:branch]
156
          )
173
          Change.create(
174
             :changeset => cs,
175
             :action    => action,
176
             :path      => scm.with_leading_slash(revision.paths[0][:path]),
177
             :revision  => revision.paths[0][:revision],
178
             :branch    => revision.paths[0][:branch]
179
              )
157 180
        end
158 181
      end
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff