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