##// END OF EJS Templates
Changeset comments are now stripped before being stored in the database (patch by Nicholas Wieland)....
Jean-Philippe Lang -
r651:c754e017dcc4
parent child
Show More
@@ -1,69 +1,73
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class Changeset < ActiveRecord::Base
18 class Changeset < ActiveRecord::Base
19 belongs_to :repository
19 belongs_to :repository
20 has_many :changes, :dependent => :delete_all
20 has_many :changes, :dependent => :delete_all
21 has_and_belongs_to_many :issues
21 has_and_belongs_to_many :issues
22
22
23 validates_presence_of :repository_id, :revision, :committed_on, :commit_date
23 validates_presence_of :repository_id, :revision, :committed_on, :commit_date
24 validates_numericality_of :revision, :only_integer => true
24 validates_numericality_of :revision, :only_integer => true
25 validates_uniqueness_of :revision, :scope => :repository_id
25 validates_uniqueness_of :revision, :scope => :repository_id
26 validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
26 validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
27
27
28 def comments=(comment)
29 write_attribute(:comments, comment.strip)
30 end
31
28 def committed_on=(date)
32 def committed_on=(date)
29 self.commit_date = date
33 self.commit_date = date
30 super
34 super
31 end
35 end
32
36
33 def after_create
37 def after_create
34 scan_comment_for_issue_ids
38 scan_comment_for_issue_ids
35 end
39 end
36
40
37 def scan_comment_for_issue_ids
41 def scan_comment_for_issue_ids
38 return if comments.blank?
42 return if comments.blank?
39 # keywords used to reference issues
43 # keywords used to reference issues
40 ref_keywords = Setting.commit_ref_keywords.downcase.split(",")
44 ref_keywords = Setting.commit_ref_keywords.downcase.split(",")
41 # keywords used to fix issues
45 # keywords used to fix issues
42 fix_keywords = Setting.commit_fix_keywords.downcase.split(",")
46 fix_keywords = Setting.commit_fix_keywords.downcase.split(",")
43 # status applied
47 # status applied
44 fix_status = IssueStatus.find_by_id(Setting.commit_fix_status_id)
48 fix_status = IssueStatus.find_by_id(Setting.commit_fix_status_id)
45
49
46 kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw.strip)}.join("|")
50 kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw.strip)}.join("|")
47 return if kw_regexp.blank?
51 return if kw_regexp.blank?
48
52
49 # remove any associated issues
53 # remove any associated issues
50 self.issues.clear
54 self.issues.clear
51
55
52 comments.scan(Regexp.new("(#{kw_regexp})[\s:]+(([\s,;&]*#?\\d+)+)", Regexp::IGNORECASE)).each do |match|
56 comments.scan(Regexp.new("(#{kw_regexp})[\s:]+(([\s,;&]*#?\\d+)+)", Regexp::IGNORECASE)).each do |match|
53 action = match[0]
57 action = match[0]
54 target_issue_ids = match[1].scan(/\d+/)
58 target_issue_ids = match[1].scan(/\d+/)
55 target_issues = repository.project.issues.find_all_by_id(target_issue_ids)
59 target_issues = repository.project.issues.find_all_by_id(target_issue_ids)
56 if fix_status && fix_keywords.include?(action.downcase)
60 if fix_status && fix_keywords.include?(action.downcase)
57 # update status of issues
61 # update status of issues
58 logger.debug "Issues fixed by changeset #{self.revision}: #{issue_ids.join(', ')}." if logger && logger.debug?
62 logger.debug "Issues fixed by changeset #{self.revision}: #{issue_ids.join(', ')}." if logger && logger.debug?
59 target_issues.each do |issue|
63 target_issues.each do |issue|
60 # don't change the status is the issue is already closed
64 # don't change the status is the issue is already closed
61 next if issue.status.is_closed?
65 next if issue.status.is_closed?
62 issue.status = fix_status
66 issue.status = fix_status
63 issue.save
67 issue.save
64 end
68 end
65 end
69 end
66 self.issues << target_issues
70 self.issues << target_issues
67 end
71 end
68 end
72 end
69 end
73 end
@@ -1,56 +1,71
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19
19
20 class RepositoryTest < Test::Unit::TestCase
20 class RepositoryTest < Test::Unit::TestCase
21 fixtures :projects, :repositories, :issues, :issue_statuses, :changesets, :changes
21 fixtures :projects, :repositories, :issues, :issue_statuses, :changesets, :changes
22
22
23 def setup
23 def setup
24 @repository = Project.find(1).repository
24 @repository = Project.find(1).repository
25 end
25 end
26
26
27 def test_create
27 def test_create
28 repository = Repository::Subversion.new(:project => Project.find(2))
28 repository = Repository::Subversion.new(:project => Project.find(2))
29 assert !repository.save
29 assert !repository.save
30
30
31 repository.url = "svn://localhost"
31 repository.url = "svn://localhost"
32 assert repository.save
32 assert repository.save
33 repository.reload
33 repository.reload
34
34
35 project = Project.find(2)
35 project = Project.find(2)
36 assert_equal repository, project.repository
36 assert_equal repository, project.repository
37 end
37 end
38
38
39 def test_scan_changesets_for_issue_ids
39 def test_scan_changesets_for_issue_ids
40 # choosing a status to apply to fix issues
40 # choosing a status to apply to fix issues
41 Setting.commit_fix_status_id = IssueStatus.find(:first, :conditions => ["is_closed = ?", true]).id
41 Setting.commit_fix_status_id = IssueStatus.find(:first, :conditions => ["is_closed = ?", true]).id
42
42
43 # make sure issue 1 is not already closed
43 # make sure issue 1 is not already closed
44 assert !Issue.find(1).status.is_closed?
44 assert !Issue.find(1).status.is_closed?
45
45
46 Repository.scan_changesets_for_issue_ids
46 Repository.scan_changesets_for_issue_ids
47 assert_equal [101, 102], Issue.find(3).changeset_ids
47 assert_equal [101, 102], Issue.find(3).changeset_ids
48
48
49 # fixed issues
49 # fixed issues
50 assert Issue.find(1).status.is_closed?
50 assert Issue.find(1).status.is_closed?
51 assert_equal [101], Issue.find(1).changeset_ids
51 assert_equal [101], Issue.find(1).changeset_ids
52
52
53 # ignoring commits referencing an issue of another project
53 # ignoring commits referencing an issue of another project
54 assert_equal [], Issue.find(4).changesets
54 assert_equal [], Issue.find(4).changesets
55 end
55 end
56
57 def test_for_changeset_comments_strip
58 repository = Repository::Mercurial.create( :project => Project.find( 4 ), :url => '/foo/bar/baz' )
59 comment = <<-COMMENT
60 This is a loooooooooooooooooooooooooooong comment
61
62
63 COMMENT
64 changeset = Changeset.new(
65 :comments => comment, :commit_date => Time.now, :revision => 0, :scmid => 'f39b7922fb3c',
66 :committer => 'foo <foo@example.com>', :committed_on => Time.now, :repository_id => repository )
67 assert( changeset.save )
68 assert_not_equal( comment, changeset.comments )
69 assert_equal( 'This is a loooooooooooooooooooooooooooong comment', changeset.comments )
70 end
56 end
71 end
General Comments 0
You need to be logged in to leave comments. Login now