##// END OF EJS Templates
Fixed: using '*' as keyword for repository referencing keywords doesn't work when issue id is at the beginning of a line (#1253)....
Jean-Philippe Lang -
r1437:e8d092e46ad8
parent child
Show More
@@ -1,131 +1,131
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 Changeset < ActiveRecord::Base
19 19 belongs_to :repository
20 20 has_many :changes, :dependent => :delete_all
21 21 has_and_belongs_to_many :issues
22 22
23 23 acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.revision}" + (o.comments.blank? ? '' : (': ' + o.comments))},
24 24 :description => :comments,
25 25 :datetime => :committed_on,
26 26 :author => :committer,
27 27 :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project_id, :rev => o.revision}}
28 28
29 29 acts_as_searchable :columns => 'comments',
30 30 :include => {:repository => :project},
31 31 :project_key => "#{Repository.table_name}.project_id",
32 32 :date_column => 'committed_on'
33 33
34 34 validates_presence_of :repository_id, :revision, :committed_on, :commit_date
35 35 validates_uniqueness_of :revision, :scope => :repository_id
36 36 validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
37 37
38 38 def revision=(r)
39 39 write_attribute :revision, (r.nil? ? nil : r.to_s)
40 40 end
41 41
42 42 def comments=(comment)
43 43 write_attribute(:comments, comment.strip)
44 44 end
45 45
46 46 def committed_on=(date)
47 47 self.commit_date = date
48 48 super
49 49 end
50 50
51 51 def project
52 52 repository.project
53 53 end
54 54
55 55 def after_create
56 56 scan_comment_for_issue_ids
57 57 end
58 58 require 'pp'
59 59
60 60 def scan_comment_for_issue_ids
61 61 return if comments.blank?
62 62 # keywords used to reference issues
63 63 ref_keywords = Setting.commit_ref_keywords.downcase.split(",").collect(&:strip)
64 64 # keywords used to fix issues
65 65 fix_keywords = Setting.commit_fix_keywords.downcase.split(",").collect(&:strip)
66 66 # status and optional done ratio applied
67 67 fix_status = IssueStatus.find_by_id(Setting.commit_fix_status_id)
68 68 done_ratio = Setting.commit_fix_done_ratio.blank? ? nil : Setting.commit_fix_done_ratio.to_i
69 69
70 70 kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|")
71 71 return if kw_regexp.blank?
72 72
73 73 referenced_issues = []
74 74
75 75 if ref_keywords.delete('*')
76 76 # find any issue ID in the comments
77 77 target_issue_ids = []
78 comments.scan(%r{([\s\(,-^])#(\d+)(?=[[:punct:]]|\s|<|$)}).each { |m| target_issue_ids << m[1] }
78 comments.scan(%r{([\s\(,-]|^)#(\d+)(?=[[:punct:]]|\s|<|$)}).each { |m| target_issue_ids << m[1] }
79 79 referenced_issues += repository.project.issues.find_all_by_id(target_issue_ids)
80 80 end
81 81
82 82 comments.scan(Regexp.new("(#{kw_regexp})[\s:]+(([\s,;&]*#?\\d+)+)", Regexp::IGNORECASE)).each do |match|
83 83 action = match[0]
84 84 target_issue_ids = match[1].scan(/\d+/)
85 85 target_issues = repository.project.issues.find_all_by_id(target_issue_ids)
86 86 if fix_status && fix_keywords.include?(action.downcase)
87 87 # update status of issues
88 88 logger.debug "Issues fixed by changeset #{self.revision}: #{issue_ids.join(', ')}." if logger && logger.debug?
89 89 target_issues.each do |issue|
90 90 # the issue may have been updated by the closure of another one (eg. duplicate)
91 91 issue.reload
92 92 # don't change the status is the issue is closed
93 93 next if issue.status.is_closed?
94 94 user = committer_user || User.anonymous
95 95 csettext = "r#{self.revision}"
96 96 if self.scmid && (! (csettext =~ /^r[0-9]+$/))
97 97 csettext = "commit:\"#{self.scmid}\""
98 98 end
99 99 journal = issue.init_journal(user, l(:text_status_changed_by_changeset, csettext))
100 100 issue.status = fix_status
101 101 issue.done_ratio = done_ratio if done_ratio
102 102 issue.save
103 103 Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
104 104 end
105 105 end
106 106 referenced_issues += target_issues
107 107 end
108 108
109 109 self.issues = referenced_issues.uniq
110 110 end
111 111
112 112 # Returns the Redmine User corresponding to the committer
113 113 def committer_user
114 114 if committer && committer.strip =~ /^([^<]+)(<(.*)>)?$/
115 115 username, email = $1.strip, $3
116 116 u = User.find_by_login(username)
117 117 u ||= User.find_by_mail(email) unless email.blank?
118 118 u
119 119 end
120 120 end
121 121
122 122 # Returns the previous changeset
123 123 def previous
124 124 @previous ||= Changeset.find(:first, :conditions => ['id < ? AND repository_id = ?', self.id, self.repository_id], :order => 'id DESC')
125 125 end
126 126
127 127 # Returns the next changeset
128 128 def next
129 129 @next ||= Changeset.find(:first, :conditions => ['id > ? AND repository_id = ?', self.id, self.repository_id], :order => 'id ASC')
130 130 end
131 131 end
@@ -1,62 +1,73
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 ChangesetTest < Test::Unit::TestCase
21 21 fixtures :projects, :repositories, :issues, :issue_statuses, :changesets, :changes, :issue_categories, :enumerations, :custom_fields, :custom_values, :users, :members, :trackers
22 22
23 23 def setup
24 24 end
25 25
26 26 def test_ref_keywords_any
27 27 Setting.commit_fix_status_id = IssueStatus.find(:first, :conditions => ["is_closed = ?", true]).id
28 28 Setting.commit_fix_done_ratio = '90'
29 29 Setting.commit_ref_keywords = '*'
30 30 Setting.commit_fix_keywords = 'fixes , closes'
31 31
32 32 c = Changeset.new(:repository => Project.find(1).repository,
33 33 :committed_on => Time.now,
34 34 :comments => 'New commit (#2). Fixes #1')
35 35 c.scan_comment_for_issue_ids
36 36
37 37 assert_equal [1, 2], c.issue_ids.sort
38 38 fixed = Issue.find(1)
39 39 assert fixed.closed?
40 40 assert_equal 90, fixed.done_ratio
41 41 end
42 42
43 def test_ref_keywords_any_line_start
44 Setting.commit_ref_keywords = '*'
45
46 c = Changeset.new(:repository => Project.find(1).repository,
47 :committed_on => Time.now,
48 :comments => '#1 is the reason of this commit')
49 c.scan_comment_for_issue_ids
50
51 assert_equal [1], c.issue_ids.sort
52 end
53
43 54 def test_previous
44 55 changeset = Changeset.find_by_revision('3')
45 56 assert_equal Changeset.find_by_revision('2'), changeset.previous
46 57 end
47 58
48 59 def test_previous_nil
49 60 changeset = Changeset.find_by_revision('1')
50 61 assert_nil changeset.previous
51 62 end
52 63
53 64 def test_next
54 65 changeset = Changeset.find_by_revision('2')
55 66 assert_equal Changeset.find_by_revision('3'), changeset.next
56 67 end
57 68
58 69 def test_next_nil
59 70 changeset = Changeset.find_by_revision('4')
60 71 assert_nil changeset.next
61 72 end
62 73 end
General Comments 0
You need to be logged in to leave comments. Login now