##// END OF EJS Templates
Clear changesets and changes with raw sql when deleting a repository (#1627)....
Jean-Philippe Lang -
r1651:fc07ba2a99fd
parent child
Show More
@@ -1,130 +1,139
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 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.
17 17
18 18 class Repository < ActiveRecord::Base
19 19 belongs_to :project
20 has_many :changesets, :dependent => :destroy, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
20 has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
21 21 has_many :changes, :through => :changesets
22 22
23 # Raw SQL to delete changesets and changes in the database
24 # has_many :changesets, :dependent => :destroy is too slow for big repositories
25 before_destroy :clear_changesets
26
23 27 # Checks if the SCM is enabled when creating a repository
24 28 validate_on_create { |r| r.errors.add(:type, :activerecord_error_invalid) unless Setting.enabled_scm.include?(r.class.name.demodulize) }
25 29
26 30 # Removes leading and trailing whitespace
27 31 def url=(arg)
28 32 write_attribute(:url, arg ? arg.to_s.strip : nil)
29 33 end
30 34
31 35 # Removes leading and trailing whitespace
32 36 def root_url=(arg)
33 37 write_attribute(:root_url, arg ? arg.to_s.strip : nil)
34 38 end
35 39
36 40 def scm
37 41 @scm ||= self.scm_adapter.new url, root_url, login, password
38 42 update_attribute(:root_url, @scm.root_url) if root_url.blank?
39 43 @scm
40 44 end
41 45
42 46 def scm_name
43 47 self.class.scm_name
44 48 end
45 49
46 50 def supports_cat?
47 51 scm.supports_cat?
48 52 end
49 53
50 54 def supports_annotate?
51 55 scm.supports_annotate?
52 56 end
53 57
54 58 def entry(path=nil, identifier=nil)
55 59 scm.entry(path, identifier)
56 60 end
57 61
58 62 def entries(path=nil, identifier=nil)
59 63 scm.entries(path, identifier)
60 64 end
61 65
62 66 def properties(path, identifier=nil)
63 67 scm.properties(path, identifier)
64 68 end
65 69
66 70 def cat(path, identifier=nil)
67 71 scm.cat(path, identifier)
68 72 end
69 73
70 74 def diff(path, rev, rev_to)
71 75 scm.diff(path, rev, rev_to)
72 76 end
73 77
74 78 # Default behaviour: we search in cached changesets
75 79 def changesets_for_path(path)
76 80 path = "/#{path}" unless path.starts_with?('/')
77 81 Change.find(:all, :include => :changeset,
78 82 :conditions => ["repository_id = ? AND path = ?", id, path],
79 83 :order => "committed_on DESC, #{Changeset.table_name}.id DESC").collect(&:changeset)
80 84 end
81 85
82 86 # Returns a path relative to the url of the repository
83 87 def relative_path(path)
84 88 path
85 89 end
86 90
87 91 def latest_changeset
88 92 @latest_changeset ||= changesets.find(:first)
89 93 end
90 94
91 95 def scan_changesets_for_issue_ids
92 96 self.changesets.each(&:scan_comment_for_issue_ids)
93 97 end
94 98
95 99 # fetch new changesets for all repositories
96 100 # can be called periodically by an external script
97 101 # eg. ruby script/runner "Repository.fetch_changesets"
98 102 def self.fetch_changesets
99 103 find(:all).each(&:fetch_changesets)
100 104 end
101 105
102 106 # scan changeset comments to find related and fixed issues for all repositories
103 107 def self.scan_changesets_for_issue_ids
104 108 find(:all).each(&:scan_changesets_for_issue_ids)
105 109 end
106 110
107 111 def self.scm_name
108 112 'Abstract'
109 113 end
110 114
111 115 def self.available_scm
112 116 subclasses.collect {|klass| [klass.scm_name, klass.name]}
113 117 end
114 118
115 119 def self.factory(klass_name, *args)
116 120 klass = "Repository::#{klass_name}".constantize
117 121 klass.new(*args)
118 122 rescue
119 123 nil
120 124 end
121 125
122 126 private
123 127
124 128 def before_save
125 129 # Strips url and root_url
126 130 url.strip!
127 131 root_url.strip!
128 132 true
129 133 end
134
135 def clear_changesets
136 connection.delete("DELETE FROM changes WHERE changes.changeset_id IN (SELECT changesets.id FROM changesets WHERE changesets.repository_id = #{id})")
137 connection.delete("DELETE FROM changesets WHERE changesets.repository_id = #{id}")
138 end
130 139 end
@@ -1,120 +1,130
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 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.
17 17
18 18 require File.dirname(__FILE__) + '/../test_helper'
19 19
20 20 class RepositoryTest < Test::Unit::TestCase
21 21 fixtures :projects,
22 22 :trackers,
23 23 :projects_trackers,
24 24 :repositories,
25 25 :issues,
26 26 :issue_statuses,
27 27 :changesets,
28 28 :changes,
29 29 :users,
30 30 :enumerations
31 31
32 32 def setup
33 33 @repository = Project.find(1).repository
34 34 end
35 35
36 36 def test_create
37 37 repository = Repository::Subversion.new(:project => Project.find(3))
38 38 assert !repository.save
39 39
40 40 repository.url = "svn://localhost"
41 41 assert repository.save
42 42 repository.reload
43 43
44 44 project = Project.find(3)
45 45 assert_equal repository, project.repository
46 46 end
47 47
48 def test_destroy
49 changesets = Changeset.count(:all, :conditions => "repository_id = 10")
50 changes = Change.count(:all, :conditions => "repository_id = 10", :include => :changeset)
51 assert_difference 'Changeset.count', -changesets do
52 assert_difference 'Change.count', -changes do
53 Repository.find(10).destroy
54 end
55 end
56 end
57
48 58 def test_should_not_create_with_disabled_scm
49 59 # disable Subversion
50 60 Setting.enabled_scm = ['Darcs', 'Git']
51 61 repository = Repository::Subversion.new(:project => Project.find(3), :url => "svn://localhost")
52 62 assert !repository.save
53 63 assert_equal :activerecord_error_invalid, repository.errors.on(:type)
54 64 # re-enable Subversion for following tests
55 65 Setting.delete_all
56 66 end
57 67
58 68 def test_scan_changesets_for_issue_ids
59 69 # choosing a status to apply to fix issues
60 70 Setting.commit_fix_status_id = IssueStatus.find(:first, :conditions => ["is_closed = ?", true]).id
61 71 Setting.commit_fix_done_ratio = "90"
62 72 Setting.commit_ref_keywords = 'refs , references, IssueID'
63 73 Setting.commit_fix_keywords = 'fixes , closes'
64 74 Setting.default_language = 'en'
65 75 ActionMailer::Base.deliveries.clear
66 76
67 77 # make sure issue 1 is not already closed
68 78 fixed_issue = Issue.find(1)
69 79 assert !fixed_issue.status.is_closed?
70 80 old_status = fixed_issue.status
71 81
72 82 Repository.scan_changesets_for_issue_ids
73 83 assert_equal [101, 102], Issue.find(3).changeset_ids
74 84
75 85 # fixed issues
76 86 fixed_issue.reload
77 87 assert fixed_issue.status.is_closed?
78 88 assert_equal 90, fixed_issue.done_ratio
79 89 assert_equal [101], fixed_issue.changeset_ids
80 90
81 91 # issue change
82 92 journal = fixed_issue.journals.find(:first, :order => 'created_on desc')
83 93 assert_equal User.find_by_login('dlopper'), journal.user
84 94 assert_equal 'Applied in changeset r2.', journal.notes
85 95
86 96 # 2 email notifications
87 97 assert_equal 2, ActionMailer::Base.deliveries.size
88 98 mail = ActionMailer::Base.deliveries.first
89 99 assert_kind_of TMail::Mail, mail
90 100 assert mail.subject.starts_with?("[#{fixed_issue.project.name} - #{fixed_issue.tracker.name} ##{fixed_issue.id}]")
91 101 assert mail.body.include?("Status changed from #{old_status} to #{fixed_issue.status}")
92 102
93 103 # ignoring commits referencing an issue of another project
94 104 assert_equal [], Issue.find(4).changesets
95 105 end
96 106
97 107 def test_for_changeset_comments_strip
98 108 repository = Repository::Mercurial.create( :project => Project.find( 4 ), :url => '/foo/bar/baz' )
99 109 comment = <<-COMMENT
100 110 This is a loooooooooooooooooooooooooooong comment
101 111
102 112
103 113 COMMENT
104 114 changeset = Changeset.new(
105 115 :comments => comment, :commit_date => Time.now, :revision => 0, :scmid => 'f39b7922fb3c',
106 116 :committer => 'foo <foo@example.com>', :committed_on => Time.now, :repository => repository )
107 117 assert( changeset.save )
108 118 assert_not_equal( comment, changeset.comments )
109 119 assert_equal( 'This is a loooooooooooooooooooooooooooong comment', changeset.comments )
110 120 end
111 121
112 122 def test_for_urls_strip
113 123 repository = Repository::Cvs.create(:project => Project.find(4), :url => ' :pserver:login:password@host:/path/to/the/repository',
114 124 :root_url => 'foo ')
115 125 assert repository.save
116 126 repository.reload
117 127 assert_equal ':pserver:login:password@host:/path/to/the/repository', repository.url
118 128 assert_equal 'foo', repository.root_url
119 129 end
120 130 end
General Comments 0
You need to be logged in to leave comments. Login now