##// END OF EJS Templates
scm: git: override entries() in model for browsing tree performance (#7047)....
Toshi MARUYAMA -
r5535:12f4b8b6d94c
parent child
Show More
@@ -1,159 +1,163
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 # Copyright (C) 2007 Patrick Aljord patcito@ŋmail.com
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.
17 17
18 18 require 'redmine/scm/adapters/git_adapter'
19 19
20 20 class Repository::Git < Repository
21 21 attr_protected :root_url
22 22 validates_presence_of :url
23 23
24 24 def self.human_attribute_name(attribute_key_name)
25 25 attr_name = attribute_key_name
26 26 if attr_name == "url"
27 27 attr_name = "path_to_repository"
28 28 end
29 29 super(attr_name)
30 30 end
31 31
32 32 def self.scm_adapter_class
33 33 Redmine::Scm::Adapters::GitAdapter
34 34 end
35 35
36 36 def self.scm_name
37 37 'Git'
38 38 end
39 39
40 40 def supports_directory_revisions?
41 41 true
42 42 end
43 43
44 44 def repo_log_encoding
45 45 'UTF-8'
46 46 end
47 47
48 48 # Returns the identifier for the given git changeset
49 49 def self.changeset_identifier(changeset)
50 50 changeset.scmid
51 51 end
52 52
53 53 # Returns the readable identifier for the given git changeset
54 54 def self.format_changeset_identifier(changeset)
55 55 changeset.revision[0, 8]
56 56 end
57 57
58 58 def branches
59 59 scm.branches
60 60 end
61 61
62 62 def tags
63 63 scm.tags
64 64 end
65 65
66 66 def find_changeset_by_name(name)
67 67 return nil if name.nil? || name.empty?
68 68 e = changesets.find(:first, :conditions => ['revision = ?', name.to_s])
69 69 return e if e
70 70 changesets.find(:first, :conditions => ['scmid LIKE ?', "#{name}%"])
71 71 end
72 72
73 def entries(path=nil, identifier=nil)
74 scm.entries(path, identifier)
75 end
76
73 77 # In Git and Mercurial, revisions are not in date order.
74 78 # Mercurial fixed issues.
75 79 # * Redmine Takes Too Long On Large Mercurial Repository
76 80 # http://www.redmine.org/issues/3449
77 81 # * Sorting for changesets might go wrong on Mercurial repos
78 82 # http://www.redmine.org/issues/3567
79 83 # Database revision column is text, so Redmine can not sort by revision.
80 84 # Mercurial has revision number, and revision number guarantees revision order.
81 85 # Mercurial adapter uses "hg log -r 0:tip --limit 10"
82 86 # to get limited revisions from old to new.
83 87 # And Mercurial model stored revisions ordered by database id in database.
84 88 # So, Mercurial can use correct order revisions.
85 89 #
86 90 # But, Git 1.7.3.4 does not support --reverse with -n or --skip.
87 91 #
88 92 # With SCM's that have a sequential commit numbering, redmine is able to be
89 93 # clever and only fetch changesets going forward from the most recent one
90 94 # it knows about.
91 95 # However, with git, you never know if people have merged
92 96 # commits into the middle of the repository history, so we should parse
93 97 # the entire log.
94 98 #
95 99 # Since it's way too slow for large repositories,
96 100 # we only parse 1 week before the last known commit.
97 101 #
98 102 # The repository can still be fully reloaded by calling #clear_changesets
99 103 # before fetching changesets (eg. for offline resync)
100 104 def fetch_changesets
101 105 c = changesets.find(:first, :order => 'committed_on DESC')
102 106 since = (c ? c.committed_on - 7.days : nil)
103 107
104 108 revisions = scm.revisions('', nil, nil, {:all => true, :since => since, :reverse => true})
105 109 return if revisions.nil? || revisions.empty?
106 110
107 111 recent_changesets = changesets.find(:all, :conditions => ['committed_on >= ?', since])
108 112
109 113 # Clean out revisions that are no longer in git
110 114 recent_changesets.each {|c| c.destroy unless revisions.detect {|r| r.scmid.to_s == c.scmid.to_s }}
111 115
112 116 # Subtract revisions that redmine already knows about
113 117 recent_revisions = recent_changesets.map{|c| c.scmid}
114 118 revisions.reject!{|r| recent_revisions.include?(r.scmid)}
115 119
116 120 # Save the remaining ones to the database
117 121 unless revisions.nil?
118 122 revisions.each do |rev|
119 123 transaction do
120 124 save_revision(rev)
121 125 end
122 126 end
123 127 end
124 128 end
125 129
126 130 def save_revision(rev)
127 131 changeset = Changeset.new(
128 132 :repository => self,
129 133 :revision => rev.identifier,
130 134 :scmid => rev.scmid,
131 135 :committer => rev.author,
132 136 :committed_on => rev.time,
133 137 :comments => rev.message
134 138 )
135 139 if changeset.save
136 140 rev.paths.each do |file|
137 141 Change.create(
138 142 :changeset => changeset,
139 143 :action => file[:action],
140 144 :path => file[:path])
141 145 end
142 146 end
143 147 end
144 148 private :save_revision
145 149
146 150 def latest_changesets(path,rev,limit=10)
147 151 revisions = scm.revisions(path, nil, rev, :limit => limit, :all => false)
148 152 return [] if revisions.nil? || revisions.empty?
149 153
150 154 changesets.find(
151 155 :all,
152 156 :conditions => [
153 157 "scmid IN (?)",
154 158 revisions.map!{|c| c.scmid}
155 159 ],
156 160 :order => 'committed_on DESC'
157 161 )
158 162 end
159 163 end
General Comments 0
You need to be logged in to leave comments. Login now