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