Revision 442:753f1380d6bc app/models/repository/.svn/text-base

View differences:

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

Also available in: Unified diff