##// END OF EJS Templates
Fixed magic link in the note added when closing an issue by a commit from a subproject (#10284)....
Jean-Philippe Lang -
r8797:77287d1f0bd1
parent child
Show More
@@ -1,271 +1,275
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 #
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 'iconv'
18 require 'iconv'
19
19
20 class Changeset < ActiveRecord::Base
20 class Changeset < ActiveRecord::Base
21 belongs_to :repository
21 belongs_to :repository
22 belongs_to :user
22 belongs_to :user
23 has_many :changes, :dependent => :delete_all
23 has_many :changes, :dependent => :delete_all
24 has_and_belongs_to_many :issues
24 has_and_belongs_to_many :issues
25 has_and_belongs_to_many :parents,
25 has_and_belongs_to_many :parents,
26 :class_name => "Changeset",
26 :class_name => "Changeset",
27 :join_table => "#{table_name_prefix}changeset_parents#{table_name_suffix}",
27 :join_table => "#{table_name_prefix}changeset_parents#{table_name_suffix}",
28 :association_foreign_key => 'parent_id', :foreign_key => 'changeset_id'
28 :association_foreign_key => 'parent_id', :foreign_key => 'changeset_id'
29 has_and_belongs_to_many :children,
29 has_and_belongs_to_many :children,
30 :class_name => "Changeset",
30 :class_name => "Changeset",
31 :join_table => "#{table_name_prefix}changeset_parents#{table_name_suffix}",
31 :join_table => "#{table_name_prefix}changeset_parents#{table_name_suffix}",
32 :association_foreign_key => 'changeset_id', :foreign_key => 'parent_id'
32 :association_foreign_key => 'changeset_id', :foreign_key => 'parent_id'
33
33
34 acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.format_identifier}" + (o.short_comments.blank? ? '' : (': ' + o.short_comments))},
34 acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.format_identifier}" + (o.short_comments.blank? ? '' : (': ' + o.short_comments))},
35 :description => :long_comments,
35 :description => :long_comments,
36 :datetime => :committed_on,
36 :datetime => :committed_on,
37 :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :repository_id => o.repository.identifier_param, :rev => o.identifier}}
37 :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :repository_id => o.repository.identifier_param, :rev => o.identifier}}
38
38
39 acts_as_searchable :columns => 'comments',
39 acts_as_searchable :columns => 'comments',
40 :include => {:repository => :project},
40 :include => {:repository => :project},
41 :project_key => "#{Repository.table_name}.project_id",
41 :project_key => "#{Repository.table_name}.project_id",
42 :date_column => 'committed_on'
42 :date_column => 'committed_on'
43
43
44 acts_as_activity_provider :timestamp => "#{table_name}.committed_on",
44 acts_as_activity_provider :timestamp => "#{table_name}.committed_on",
45 :author_key => :user_id,
45 :author_key => :user_id,
46 :find_options => {:include => [:user, {:repository => :project}]}
46 :find_options => {:include => [:user, {:repository => :project}]}
47
47
48 validates_presence_of :repository_id, :revision, :committed_on, :commit_date
48 validates_presence_of :repository_id, :revision, :committed_on, :commit_date
49 validates_uniqueness_of :revision, :scope => :repository_id
49 validates_uniqueness_of :revision, :scope => :repository_id
50 validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
50 validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true
51
51
52 named_scope :visible, lambda {|*args| { :include => {:repository => :project},
52 named_scope :visible, lambda {|*args| { :include => {:repository => :project},
53 :conditions => Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args) } }
53 :conditions => Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args) } }
54
54
55 after_create :scan_for_issues
55 after_create :scan_for_issues
56 before_create :before_create_cs
56 before_create :before_create_cs
57
57
58 def revision=(r)
58 def revision=(r)
59 write_attribute :revision, (r.nil? ? nil : r.to_s)
59 write_attribute :revision, (r.nil? ? nil : r.to_s)
60 end
60 end
61
61
62 # Returns the identifier of this changeset; depending on repository backends
62 # Returns the identifier of this changeset; depending on repository backends
63 def identifier
63 def identifier
64 if repository.class.respond_to? :changeset_identifier
64 if repository.class.respond_to? :changeset_identifier
65 repository.class.changeset_identifier self
65 repository.class.changeset_identifier self
66 else
66 else
67 revision.to_s
67 revision.to_s
68 end
68 end
69 end
69 end
70
70
71 def committed_on=(date)
71 def committed_on=(date)
72 self.commit_date = date
72 self.commit_date = date
73 super
73 super
74 end
74 end
75
75
76 # Returns the readable identifier
76 # Returns the readable identifier
77 def format_identifier
77 def format_identifier
78 if repository.class.respond_to? :format_changeset_identifier
78 if repository.class.respond_to? :format_changeset_identifier
79 repository.class.format_changeset_identifier self
79 repository.class.format_changeset_identifier self
80 else
80 else
81 identifier
81 identifier
82 end
82 end
83 end
83 end
84
84
85 def project
85 def project
86 repository.project
86 repository.project
87 end
87 end
88
88
89 def author
89 def author
90 user || committer.to_s.split('<').first
90 user || committer.to_s.split('<').first
91 end
91 end
92
92
93 def before_create_cs
93 def before_create_cs
94 self.committer = self.class.to_utf8(self.committer, repository.repo_log_encoding)
94 self.committer = self.class.to_utf8(self.committer, repository.repo_log_encoding)
95 self.comments = self.class.normalize_comments(
95 self.comments = self.class.normalize_comments(
96 self.comments, repository.repo_log_encoding)
96 self.comments, repository.repo_log_encoding)
97 self.user = repository.find_committer_user(self.committer)
97 self.user = repository.find_committer_user(self.committer)
98 end
98 end
99
99
100 def scan_for_issues
100 def scan_for_issues
101 scan_comment_for_issue_ids
101 scan_comment_for_issue_ids
102 end
102 end
103
103
104 TIMELOG_RE = /
104 TIMELOG_RE = /
105 (
105 (
106 ((\d+)(h|hours?))((\d+)(m|min)?)?
106 ((\d+)(h|hours?))((\d+)(m|min)?)?
107 |
107 |
108 ((\d+)(h|hours?|m|min))
108 ((\d+)(h|hours?|m|min))
109 |
109 |
110 (\d+):(\d+)
110 (\d+):(\d+)
111 |
111 |
112 (\d+([\.,]\d+)?)h?
112 (\d+([\.,]\d+)?)h?
113 )
113 )
114 /x
114 /x
115
115
116 def scan_comment_for_issue_ids
116 def scan_comment_for_issue_ids
117 return if comments.blank?
117 return if comments.blank?
118 # keywords used to reference issues
118 # keywords used to reference issues
119 ref_keywords = Setting.commit_ref_keywords.downcase.split(",").collect(&:strip)
119 ref_keywords = Setting.commit_ref_keywords.downcase.split(",").collect(&:strip)
120 ref_keywords_any = ref_keywords.delete('*')
120 ref_keywords_any = ref_keywords.delete('*')
121 # keywords used to fix issues
121 # keywords used to fix issues
122 fix_keywords = Setting.commit_fix_keywords.downcase.split(",").collect(&:strip)
122 fix_keywords = Setting.commit_fix_keywords.downcase.split(",").collect(&:strip)
123
123
124 kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|")
124 kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|")
125
125
126 referenced_issues = []
126 referenced_issues = []
127
127
128 comments.scan(/([\s\(\[,-]|^)((#{kw_regexp})[\s:]+)?(#\d+(\s+@#{TIMELOG_RE})?([\s,;&]+#\d+(\s+@#{TIMELOG_RE})?)*)(?=[[:punct:]]|\s|<|$)/i) do |match|
128 comments.scan(/([\s\(\[,-]|^)((#{kw_regexp})[\s:]+)?(#\d+(\s+@#{TIMELOG_RE})?([\s,;&]+#\d+(\s+@#{TIMELOG_RE})?)*)(?=[[:punct:]]|\s|<|$)/i) do |match|
129 action, refs = match[2], match[3]
129 action, refs = match[2], match[3]
130 next unless action.present? || ref_keywords_any
130 next unless action.present? || ref_keywords_any
131
131
132 refs.scan(/#(\d+)(\s+@#{TIMELOG_RE})?/).each do |m|
132 refs.scan(/#(\d+)(\s+@#{TIMELOG_RE})?/).each do |m|
133 issue, hours = find_referenced_issue_by_id(m[0].to_i), m[2]
133 issue, hours = find_referenced_issue_by_id(m[0].to_i), m[2]
134 if issue
134 if issue
135 referenced_issues << issue
135 referenced_issues << issue
136 fix_issue(issue) if fix_keywords.include?(action.to_s.downcase)
136 fix_issue(issue) if fix_keywords.include?(action.to_s.downcase)
137 log_time(issue, hours) if hours && Setting.commit_logtime_enabled?
137 log_time(issue, hours) if hours && Setting.commit_logtime_enabled?
138 end
138 end
139 end
139 end
140 end
140 end
141
141
142 referenced_issues.uniq!
142 referenced_issues.uniq!
143 self.issues = referenced_issues unless referenced_issues.empty?
143 self.issues = referenced_issues unless referenced_issues.empty?
144 end
144 end
145
145
146 def short_comments
146 def short_comments
147 @short_comments || split_comments.first
147 @short_comments || split_comments.first
148 end
148 end
149
149
150 def long_comments
150 def long_comments
151 @long_comments || split_comments.last
151 @long_comments || split_comments.last
152 end
152 end
153
153
154 def text_tag
154 def text_tag(ref_project=nil)
155 if scmid?
155 tag = if scmid?
156 "commit:#{scmid}"
156 "commit:#{scmid}"
157 else
157 else
158 "r#{revision}"
158 "r#{revision}"
159 end
159 end
160 if ref_project && project && ref_project != project
161 tag = "#{project.identifier}:#{tag}"
162 end
163 tag
160 end
164 end
161
165
162 # Returns the previous changeset
166 # Returns the previous changeset
163 def previous
167 def previous
164 @previous ||= Changeset.find(:first,
168 @previous ||= Changeset.find(:first,
165 :conditions => ['id < ? AND repository_id = ?',
169 :conditions => ['id < ? AND repository_id = ?',
166 self.id, self.repository_id],
170 self.id, self.repository_id],
167 :order => 'id DESC')
171 :order => 'id DESC')
168 end
172 end
169
173
170 # Returns the next changeset
174 # Returns the next changeset
171 def next
175 def next
172 @next ||= Changeset.find(:first,
176 @next ||= Changeset.find(:first,
173 :conditions => ['id > ? AND repository_id = ?',
177 :conditions => ['id > ? AND repository_id = ?',
174 self.id, self.repository_id],
178 self.id, self.repository_id],
175 :order => 'id ASC')
179 :order => 'id ASC')
176 end
180 end
177
181
178 # Creates a new Change from it's common parameters
182 # Creates a new Change from it's common parameters
179 def create_change(change)
183 def create_change(change)
180 Change.create(:changeset => self,
184 Change.create(:changeset => self,
181 :action => change[:action],
185 :action => change[:action],
182 :path => change[:path],
186 :path => change[:path],
183 :from_path => change[:from_path],
187 :from_path => change[:from_path],
184 :from_revision => change[:from_revision])
188 :from_revision => change[:from_revision])
185 end
189 end
186
190
187 # Finds an issue that can be referenced by the commit message
191 # Finds an issue that can be referenced by the commit message
188 def find_referenced_issue_by_id(id)
192 def find_referenced_issue_by_id(id)
189 return nil if id.blank?
193 return nil if id.blank?
190 issue = Issue.find_by_id(id.to_i, :include => :project)
194 issue = Issue.find_by_id(id.to_i, :include => :project)
191 if Setting.commit_cross_project_ref?
195 if Setting.commit_cross_project_ref?
192 # all issues can be referenced/fixed
196 # all issues can be referenced/fixed
193 elsif issue
197 elsif issue
194 # issue that belong to the repository project, a subproject or a parent project only
198 # issue that belong to the repository project, a subproject or a parent project only
195 unless issue.project &&
199 unless issue.project &&
196 (project == issue.project || project.is_ancestor_of?(issue.project) ||
200 (project == issue.project || project.is_ancestor_of?(issue.project) ||
197 project.is_descendant_of?(issue.project))
201 project.is_descendant_of?(issue.project))
198 issue = nil
202 issue = nil
199 end
203 end
200 end
204 end
201 issue
205 issue
202 end
206 end
203
207
204 private
208 private
205
209
206 def fix_issue(issue)
210 def fix_issue(issue)
207 status = IssueStatus.find_by_id(Setting.commit_fix_status_id.to_i)
211 status = IssueStatus.find_by_id(Setting.commit_fix_status_id.to_i)
208 if status.nil?
212 if status.nil?
209 logger.warn("No status matches commit_fix_status_id setting (#{Setting.commit_fix_status_id})") if logger
213 logger.warn("No status matches commit_fix_status_id setting (#{Setting.commit_fix_status_id})") if logger
210 return issue
214 return issue
211 end
215 end
212
216
213 # the issue may have been updated by the closure of another one (eg. duplicate)
217 # the issue may have been updated by the closure of another one (eg. duplicate)
214 issue.reload
218 issue.reload
215 # don't change the status is the issue is closed
219 # don't change the status is the issue is closed
216 return if issue.status && issue.status.is_closed?
220 return if issue.status && issue.status.is_closed?
217
221
218 journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, text_tag))
222 journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, text_tag(issue.project)))
219 issue.status = status
223 issue.status = status
220 unless Setting.commit_fix_done_ratio.blank?
224 unless Setting.commit_fix_done_ratio.blank?
221 issue.done_ratio = Setting.commit_fix_done_ratio.to_i
225 issue.done_ratio = Setting.commit_fix_done_ratio.to_i
222 end
226 end
223 Redmine::Hook.call_hook(:model_changeset_scan_commit_for_issue_ids_pre_issue_update,
227 Redmine::Hook.call_hook(:model_changeset_scan_commit_for_issue_ids_pre_issue_update,
224 { :changeset => self, :issue => issue })
228 { :changeset => self, :issue => issue })
225 unless issue.save
229 unless issue.save
226 logger.warn("Issue ##{issue.id} could not be saved by changeset #{id}: #{issue.errors.full_messages}") if logger
230 logger.warn("Issue ##{issue.id} could not be saved by changeset #{id}: #{issue.errors.full_messages}") if logger
227 end
231 end
228 issue
232 issue
229 end
233 end
230
234
231 def log_time(issue, hours)
235 def log_time(issue, hours)
232 time_entry = TimeEntry.new(
236 time_entry = TimeEntry.new(
233 :user => user,
237 :user => user,
234 :hours => hours,
238 :hours => hours,
235 :issue => issue,
239 :issue => issue,
236 :spent_on => commit_date,
240 :spent_on => commit_date,
237 :comments => l(:text_time_logged_by_changeset, :value => text_tag,
241 :comments => l(:text_time_logged_by_changeset, :value => text_tag(issue.project),
238 :locale => Setting.default_language)
242 :locale => Setting.default_language)
239 )
243 )
240 time_entry.activity = log_time_activity unless log_time_activity.nil?
244 time_entry.activity = log_time_activity unless log_time_activity.nil?
241
245
242 unless time_entry.save
246 unless time_entry.save
243 logger.warn("TimeEntry could not be created by changeset #{id}: #{time_entry.errors.full_messages}") if logger
247 logger.warn("TimeEntry could not be created by changeset #{id}: #{time_entry.errors.full_messages}") if logger
244 end
248 end
245 time_entry
249 time_entry
246 end
250 end
247
251
248 def log_time_activity
252 def log_time_activity
249 if Setting.commit_logtime_activity_id.to_i > 0
253 if Setting.commit_logtime_activity_id.to_i > 0
250 TimeEntryActivity.find_by_id(Setting.commit_logtime_activity_id.to_i)
254 TimeEntryActivity.find_by_id(Setting.commit_logtime_activity_id.to_i)
251 end
255 end
252 end
256 end
253
257
254 def split_comments
258 def split_comments
255 comments =~ /\A(.+?)\r?\n(.*)$/m
259 comments =~ /\A(.+?)\r?\n(.*)$/m
256 @short_comments = $1 || comments
260 @short_comments = $1 || comments
257 @long_comments = $2.to_s.strip
261 @long_comments = $2.to_s.strip
258 return @short_comments, @long_comments
262 return @short_comments, @long_comments
259 end
263 end
260
264
261 public
265 public
262
266
263 # Strips and reencodes a commit log before insertion into the database
267 # Strips and reencodes a commit log before insertion into the database
264 def self.normalize_comments(str, encoding)
268 def self.normalize_comments(str, encoding)
265 Changeset.to_utf8(str.to_s.strip, encoding)
269 Changeset.to_utf8(str.to_s.strip, encoding)
266 end
270 end
267
271
268 def self.to_utf8(str, encoding)
272 def self.to_utf8(str, encoding)
269 Redmine::CodesetUtil.to_utf8(str, encoding)
273 Redmine::CodesetUtil.to_utf8(str, encoding)
270 end
274 end
271 end
275 end
@@ -1,429 +1,467
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # Redmine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2011 Jean-Philippe Lang
4 # Copyright (C) 2006-2011 Jean-Philippe Lang
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
20 require File.expand_path('../../test_helper', __FILE__)
20 require File.expand_path('../../test_helper', __FILE__)
21
21
22 class ChangesetTest < ActiveSupport::TestCase
22 class ChangesetTest < ActiveSupport::TestCase
23 fixtures :projects, :repositories,
23 fixtures :projects, :repositories,
24 :issues, :issue_statuses, :issue_categories,
24 :issues, :issue_statuses, :issue_categories,
25 :changesets, :changes,
25 :changesets, :changes,
26 :enumerations,
26 :enumerations,
27 :custom_fields, :custom_values,
27 :custom_fields, :custom_values,
28 :users, :members, :member_roles, :trackers,
28 :users, :members, :member_roles, :trackers,
29 :enabled_modules, :roles
29 :enabled_modules, :roles
30
30
31 def setup
31 def setup
32 end
32 end
33
33
34 def test_ref_keywords_any
34 def test_ref_keywords_any
35 ActionMailer::Base.deliveries.clear
35 ActionMailer::Base.deliveries.clear
36 Setting.commit_fix_status_id = IssueStatus.find(
36 Setting.commit_fix_status_id = IssueStatus.find(
37 :first, :conditions => ["is_closed = ?", true]).id
37 :first, :conditions => ["is_closed = ?", true]).id
38 Setting.commit_fix_done_ratio = '90'
38 Setting.commit_fix_done_ratio = '90'
39 Setting.commit_ref_keywords = '*'
39 Setting.commit_ref_keywords = '*'
40 Setting.commit_fix_keywords = 'fixes , closes'
40 Setting.commit_fix_keywords = 'fixes , closes'
41
41
42 c = Changeset.new(:repository => Project.find(1).repository,
42 c = Changeset.new(:repository => Project.find(1).repository,
43 :committed_on => Time.now,
43 :committed_on => Time.now,
44 :comments => 'New commit (#2). Fixes #1',
44 :comments => 'New commit (#2). Fixes #1',
45 :revision => '12345')
45 :revision => '12345')
46 assert c.save
46 assert c.save
47 assert_equal [1, 2], c.issue_ids.sort
47 assert_equal [1, 2], c.issue_ids.sort
48 fixed = Issue.find(1)
48 fixed = Issue.find(1)
49 assert fixed.closed?
49 assert fixed.closed?
50 assert_equal 90, fixed.done_ratio
50 assert_equal 90, fixed.done_ratio
51 assert_equal 1, ActionMailer::Base.deliveries.size
51 assert_equal 1, ActionMailer::Base.deliveries.size
52 end
52 end
53
53
54 def test_ref_keywords
54 def test_ref_keywords
55 Setting.commit_ref_keywords = 'refs'
55 Setting.commit_ref_keywords = 'refs'
56 Setting.commit_fix_keywords = ''
56 Setting.commit_fix_keywords = ''
57 c = Changeset.new(:repository => Project.find(1).repository,
57 c = Changeset.new(:repository => Project.find(1).repository,
58 :committed_on => Time.now,
58 :committed_on => Time.now,
59 :comments => 'Ignores #2. Refs #1',
59 :comments => 'Ignores #2. Refs #1',
60 :revision => '12345')
60 :revision => '12345')
61 assert c.save
61 assert c.save
62 assert_equal [1], c.issue_ids.sort
62 assert_equal [1], c.issue_ids.sort
63 end
63 end
64
64
65 def test_ref_keywords_any_only
65 def test_ref_keywords_any_only
66 Setting.commit_ref_keywords = '*'
66 Setting.commit_ref_keywords = '*'
67 Setting.commit_fix_keywords = ''
67 Setting.commit_fix_keywords = ''
68 c = Changeset.new(:repository => Project.find(1).repository,
68 c = Changeset.new(:repository => Project.find(1).repository,
69 :committed_on => Time.now,
69 :committed_on => Time.now,
70 :comments => 'Ignores #2. Refs #1',
70 :comments => 'Ignores #2. Refs #1',
71 :revision => '12345')
71 :revision => '12345')
72 assert c.save
72 assert c.save
73 assert_equal [1, 2], c.issue_ids.sort
73 assert_equal [1, 2], c.issue_ids.sort
74 end
74 end
75
75
76 def test_ref_keywords_any_with_timelog
76 def test_ref_keywords_any_with_timelog
77 Setting.commit_ref_keywords = '*'
77 Setting.commit_ref_keywords = '*'
78 Setting.commit_logtime_enabled = '1'
78 Setting.commit_logtime_enabled = '1'
79
79
80 {
80 {
81 '2' => 2.0,
81 '2' => 2.0,
82 '2h' => 2.0,
82 '2h' => 2.0,
83 '2hours' => 2.0,
83 '2hours' => 2.0,
84 '15m' => 0.25,
84 '15m' => 0.25,
85 '15min' => 0.25,
85 '15min' => 0.25,
86 '3h15' => 3.25,
86 '3h15' => 3.25,
87 '3h15m' => 3.25,
87 '3h15m' => 3.25,
88 '3h15min' => 3.25,
88 '3h15min' => 3.25,
89 '3:15' => 3.25,
89 '3:15' => 3.25,
90 '3.25' => 3.25,
90 '3.25' => 3.25,
91 '3.25h' => 3.25,
91 '3.25h' => 3.25,
92 '3,25' => 3.25,
92 '3,25' => 3.25,
93 '3,25h' => 3.25,
93 '3,25h' => 3.25,
94 }.each do |syntax, expected_hours|
94 }.each do |syntax, expected_hours|
95 c = Changeset.new(:repository => Project.find(1).repository,
95 c = Changeset.new(:repository => Project.find(1).repository,
96 :committed_on => 24.hours.ago,
96 :committed_on => 24.hours.ago,
97 :comments => "Worked on this issue #1 @#{syntax}",
97 :comments => "Worked on this issue #1 @#{syntax}",
98 :revision => '520',
98 :revision => '520',
99 :user => User.find(2))
99 :user => User.find(2))
100 assert_difference 'TimeEntry.count' do
100 assert_difference 'TimeEntry.count' do
101 c.scan_comment_for_issue_ids
101 c.scan_comment_for_issue_ids
102 end
102 end
103 assert_equal [1], c.issue_ids.sort
103 assert_equal [1], c.issue_ids.sort
104
104
105 time = TimeEntry.first(:order => 'id desc')
105 time = TimeEntry.first(:order => 'id desc')
106 assert_equal 1, time.issue_id
106 assert_equal 1, time.issue_id
107 assert_equal 1, time.project_id
107 assert_equal 1, time.project_id
108 assert_equal 2, time.user_id
108 assert_equal 2, time.user_id
109 assert_equal expected_hours, time.hours,
109 assert_equal expected_hours, time.hours,
110 "@#{syntax} should be logged as #{expected_hours} hours but was #{time.hours}"
110 "@#{syntax} should be logged as #{expected_hours} hours but was #{time.hours}"
111 assert_equal Date.yesterday, time.spent_on
111 assert_equal Date.yesterday, time.spent_on
112 assert time.activity.is_default?
112 assert time.activity.is_default?
113 assert time.comments.include?('r520'),
113 assert time.comments.include?('r520'),
114 "r520 was expected in time_entry comments: #{time.comments}"
114 "r520 was expected in time_entry comments: #{time.comments}"
115 end
115 end
116 end
116 end
117
117
118 def test_ref_keywords_closing_with_timelog
118 def test_ref_keywords_closing_with_timelog
119 Setting.commit_fix_status_id = IssueStatus.find(
119 Setting.commit_fix_status_id = IssueStatus.find(
120 :first, :conditions => ["is_closed = ?", true]).id
120 :first, :conditions => ["is_closed = ?", true]).id
121 Setting.commit_ref_keywords = '*'
121 Setting.commit_ref_keywords = '*'
122 Setting.commit_fix_keywords = 'fixes , closes'
122 Setting.commit_fix_keywords = 'fixes , closes'
123 Setting.commit_logtime_enabled = '1'
123 Setting.commit_logtime_enabled = '1'
124
124
125 c = Changeset.new(:repository => Project.find(1).repository,
125 c = Changeset.new(:repository => Project.find(1).repository,
126 :committed_on => Time.now,
126 :committed_on => Time.now,
127 :comments => 'This is a comment. Fixes #1 @4.5, #2 @1',
127 :comments => 'This is a comment. Fixes #1 @4.5, #2 @1',
128 :user => User.find(2))
128 :user => User.find(2))
129 assert_difference 'TimeEntry.count', 2 do
129 assert_difference 'TimeEntry.count', 2 do
130 c.scan_comment_for_issue_ids
130 c.scan_comment_for_issue_ids
131 end
131 end
132
132
133 assert_equal [1, 2], c.issue_ids.sort
133 assert_equal [1, 2], c.issue_ids.sort
134 assert Issue.find(1).closed?
134 assert Issue.find(1).closed?
135 assert Issue.find(2).closed?
135 assert Issue.find(2).closed?
136
136
137 times = TimeEntry.all(:order => 'id desc', :limit => 2)
137 times = TimeEntry.all(:order => 'id desc', :limit => 2)
138 assert_equal [1, 2], times.collect(&:issue_id).sort
138 assert_equal [1, 2], times.collect(&:issue_id).sort
139 end
139 end
140
140
141 def test_ref_keywords_any_line_start
141 def test_ref_keywords_any_line_start
142 Setting.commit_ref_keywords = '*'
142 Setting.commit_ref_keywords = '*'
143 c = Changeset.new(:repository => Project.find(1).repository,
143 c = Changeset.new(:repository => Project.find(1).repository,
144 :committed_on => Time.now,
144 :committed_on => Time.now,
145 :comments => '#1 is the reason of this commit',
145 :comments => '#1 is the reason of this commit',
146 :revision => '12345')
146 :revision => '12345')
147 assert c.save
147 assert c.save
148 assert_equal [1], c.issue_ids.sort
148 assert_equal [1], c.issue_ids.sort
149 end
149 end
150
150
151 def test_ref_keywords_allow_brackets_around_a_issue_number
151 def test_ref_keywords_allow_brackets_around_a_issue_number
152 Setting.commit_ref_keywords = '*'
152 Setting.commit_ref_keywords = '*'
153 c = Changeset.new(:repository => Project.find(1).repository,
153 c = Changeset.new(:repository => Project.find(1).repository,
154 :committed_on => Time.now,
154 :committed_on => Time.now,
155 :comments => '[#1] Worked on this issue',
155 :comments => '[#1] Worked on this issue',
156 :revision => '12345')
156 :revision => '12345')
157 assert c.save
157 assert c.save
158 assert_equal [1], c.issue_ids.sort
158 assert_equal [1], c.issue_ids.sort
159 end
159 end
160
160
161 def test_ref_keywords_allow_brackets_around_multiple_issue_numbers
161 def test_ref_keywords_allow_brackets_around_multiple_issue_numbers
162 Setting.commit_ref_keywords = '*'
162 Setting.commit_ref_keywords = '*'
163 c = Changeset.new(:repository => Project.find(1).repository,
163 c = Changeset.new(:repository => Project.find(1).repository,
164 :committed_on => Time.now,
164 :committed_on => Time.now,
165 :comments => '[#1 #2, #3] Worked on these',
165 :comments => '[#1 #2, #3] Worked on these',
166 :revision => '12345')
166 :revision => '12345')
167 assert c.save
167 assert c.save
168 assert_equal [1,2,3], c.issue_ids.sort
168 assert_equal [1,2,3], c.issue_ids.sort
169 end
169 end
170
170
171 def test_commit_referencing_a_subproject_issue
171 def test_commit_referencing_a_subproject_issue
172 c = Changeset.new(:repository => Project.find(1).repository,
172 c = Changeset.new(:repository => Project.find(1).repository,
173 :committed_on => Time.now,
173 :committed_on => Time.now,
174 :comments => 'refs #5, a subproject issue',
174 :comments => 'refs #5, a subproject issue',
175 :revision => '12345')
175 :revision => '12345')
176 assert c.save
176 assert c.save
177 assert_equal [5], c.issue_ids.sort
177 assert_equal [5], c.issue_ids.sort
178 assert c.issues.first.project != c.project
178 assert c.issues.first.project != c.project
179 end
179 end
180
180
181 def test_commit_closing_a_subproject_issue
182 with_settings :commit_fix_status_id => 5, :commit_fix_keywords => 'closes' do
183 issue = Issue.find(5)
184 assert !issue.closed?
185 assert_difference 'Journal.count' do
186 c = Changeset.new(:repository => Project.find(1).repository,
187 :committed_on => Time.now,
188 :comments => 'closes #5, a subproject issue',
189 :revision => '12345')
190 assert c.save
191 end
192 assert issue.reload.closed?
193 journal = Journal.first(:order => 'id DESC')
194 assert_equal issue, journal.issue
195 assert_include "Applied in changeset ecookbook:r12345.", journal.notes
196 end
197 end
198
181 def test_commit_referencing_a_parent_project_issue
199 def test_commit_referencing_a_parent_project_issue
182 # repository of child project
200 # repository of child project
183 r = Repository::Subversion.create!(
201 r = Repository::Subversion.create!(
184 :project => Project.find(3),
202 :project => Project.find(3),
185 :url => 'svn://localhost/test')
203 :url => 'svn://localhost/test')
186 c = Changeset.new(:repository => r,
204 c = Changeset.new(:repository => r,
187 :committed_on => Time.now,
205 :committed_on => Time.now,
188 :comments => 'refs #2, an issue of a parent project',
206 :comments => 'refs #2, an issue of a parent project',
189 :revision => '12345')
207 :revision => '12345')
190 assert c.save
208 assert c.save
191 assert_equal [2], c.issue_ids.sort
209 assert_equal [2], c.issue_ids.sort
192 assert c.issues.first.project != c.project
210 assert c.issues.first.project != c.project
193 end
211 end
194
212
195 def test_commit_referencing_a_project_with_commit_cross_project_ref_disabled
213 def test_commit_referencing_a_project_with_commit_cross_project_ref_disabled
196 r = Repository::Subversion.create!(
214 r = Repository::Subversion.create!(
197 :project => Project.find(3),
215 :project => Project.find(3),
198 :url => 'svn://localhost/test')
216 :url => 'svn://localhost/test')
199
217
200 with_settings :commit_cross_project_ref => '0' do
218 with_settings :commit_cross_project_ref => '0' do
201 c = Changeset.new(:repository => r,
219 c = Changeset.new(:repository => r,
202 :committed_on => Time.now,
220 :committed_on => Time.now,
203 :comments => 'refs #4, an issue of a different project',
221 :comments => 'refs #4, an issue of a different project',
204 :revision => '12345')
222 :revision => '12345')
205 assert c.save
223 assert c.save
206 assert_equal [], c.issue_ids
224 assert_equal [], c.issue_ids
207 end
225 end
208 end
226 end
209
227
210 def test_commit_referencing_a_project_with_commit_cross_project_ref_enabled
228 def test_commit_referencing_a_project_with_commit_cross_project_ref_enabled
211 r = Repository::Subversion.create!(
229 r = Repository::Subversion.create!(
212 :project => Project.find(3),
230 :project => Project.find(3),
213 :url => 'svn://localhost/test')
231 :url => 'svn://localhost/test')
214
232
215 with_settings :commit_cross_project_ref => '1' do
233 with_settings :commit_cross_project_ref => '1' do
216 c = Changeset.new(:repository => r,
234 c = Changeset.new(:repository => r,
217 :committed_on => Time.now,
235 :committed_on => Time.now,
218 :comments => 'refs #4, an issue of a different project',
236 :comments => 'refs #4, an issue of a different project',
219 :revision => '12345')
237 :revision => '12345')
220 assert c.save
238 assert c.save
221 assert_equal [4], c.issue_ids
239 assert_equal [4], c.issue_ids
222 end
240 end
223 end
241 end
224
242
225 def test_text_tag_revision
243 def test_text_tag_revision
226 c = Changeset.new(:revision => '520')
244 c = Changeset.new(:revision => '520')
227 assert_equal 'r520', c.text_tag
245 assert_equal 'r520', c.text_tag
228 end
246 end
229
247
248 def test_text_tag_revision_with_same_project
249 c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
250 assert_equal 'r520', c.text_tag(Project.find(1))
251 end
252
253 def test_text_tag_revision_with_different_project
254 c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
255 assert_equal 'ecookbook:r520', c.text_tag(Project.find(2))
256 end
257
230 def test_text_tag_hash
258 def test_text_tag_hash
231 c = Changeset.new(
259 c = Changeset.new(
232 :scmid => '7234cb2750b63f47bff735edc50a1c0a433c2518',
260 :scmid => '7234cb2750b63f47bff735edc50a1c0a433c2518',
233 :revision => '7234cb2750b63f47bff735edc50a1c0a433c2518')
261 :revision => '7234cb2750b63f47bff735edc50a1c0a433c2518')
234 assert_equal 'commit:7234cb2750b63f47bff735edc50a1c0a433c2518', c.text_tag
262 assert_equal 'commit:7234cb2750b63f47bff735edc50a1c0a433c2518', c.text_tag
235 end
263 end
236
264
265 def test_text_tag_hash_with_same_project
266 c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
267 assert_equal 'commit:7234cb27', c.text_tag(Project.find(1))
268 end
269
270 def test_text_tag_hash_with_different_project
271 c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
272 assert_equal 'ecookbook:commit:7234cb27', c.text_tag(Project.find(2))
273 end
274
237 def test_text_tag_hash_all_number
275 def test_text_tag_hash_all_number
238 c = Changeset.new(:scmid => '0123456789', :revision => '0123456789')
276 c = Changeset.new(:scmid => '0123456789', :revision => '0123456789')
239 assert_equal 'commit:0123456789', c.text_tag
277 assert_equal 'commit:0123456789', c.text_tag
240 end
278 end
241
279
242 def test_previous
280 def test_previous
243 changeset = Changeset.find_by_revision('3')
281 changeset = Changeset.find_by_revision('3')
244 assert_equal Changeset.find_by_revision('2'), changeset.previous
282 assert_equal Changeset.find_by_revision('2'), changeset.previous
245 end
283 end
246
284
247 def test_previous_nil
285 def test_previous_nil
248 changeset = Changeset.find_by_revision('1')
286 changeset = Changeset.find_by_revision('1')
249 assert_nil changeset.previous
287 assert_nil changeset.previous
250 end
288 end
251
289
252 def test_next
290 def test_next
253 changeset = Changeset.find_by_revision('2')
291 changeset = Changeset.find_by_revision('2')
254 assert_equal Changeset.find_by_revision('3'), changeset.next
292 assert_equal Changeset.find_by_revision('3'), changeset.next
255 end
293 end
256
294
257 def test_next_nil
295 def test_next_nil
258 changeset = Changeset.find_by_revision('10')
296 changeset = Changeset.find_by_revision('10')
259 assert_nil changeset.next
297 assert_nil changeset.next
260 end
298 end
261
299
262 def test_comments_should_be_converted_to_utf8
300 def test_comments_should_be_converted_to_utf8
263 proj = Project.find(3)
301 proj = Project.find(3)
264 # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
302 # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
265 str = "Texte encod\xe9 en ISO-8859-1."
303 str = "Texte encod\xe9 en ISO-8859-1."
266 str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
304 str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
267 r = Repository::Bazaar.create!(
305 r = Repository::Bazaar.create!(
268 :project => proj,
306 :project => proj,
269 :url => '/tmp/test/bazaar',
307 :url => '/tmp/test/bazaar',
270 :log_encoding => 'ISO-8859-1' )
308 :log_encoding => 'ISO-8859-1' )
271 assert r
309 assert r
272 c = Changeset.new(:repository => r,
310 c = Changeset.new(:repository => r,
273 :committed_on => Time.now,
311 :committed_on => Time.now,
274 :revision => '123',
312 :revision => '123',
275 :scmid => '12345',
313 :scmid => '12345',
276 :comments => str)
314 :comments => str)
277 assert( c.save )
315 assert( c.save )
278 str_utf8 = "Texte encod\xc3\xa9 en ISO-8859-1."
316 str_utf8 = "Texte encod\xc3\xa9 en ISO-8859-1."
279 str_utf8.force_encoding("UTF-8") if str_utf8.respond_to?(:force_encoding)
317 str_utf8.force_encoding("UTF-8") if str_utf8.respond_to?(:force_encoding)
280 assert_equal str_utf8, c.comments
318 assert_equal str_utf8, c.comments
281 end
319 end
282
320
283 def test_invalid_utf8_sequences_in_comments_should_be_replaced_latin1
321 def test_invalid_utf8_sequences_in_comments_should_be_replaced_latin1
284 proj = Project.find(3)
322 proj = Project.find(3)
285 # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
323 # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
286 str1 = "Texte encod\xe9 en ISO-8859-1."
324 str1 = "Texte encod\xe9 en ISO-8859-1."
287 str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
325 str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
288 str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
326 str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
289 str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
327 str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
290 r = Repository::Bazaar.create!(
328 r = Repository::Bazaar.create!(
291 :project => proj,
329 :project => proj,
292 :url => '/tmp/test/bazaar',
330 :url => '/tmp/test/bazaar',
293 :log_encoding => 'UTF-8' )
331 :log_encoding => 'UTF-8' )
294 assert r
332 assert r
295 c = Changeset.new(:repository => r,
333 c = Changeset.new(:repository => r,
296 :committed_on => Time.now,
334 :committed_on => Time.now,
297 :revision => '123',
335 :revision => '123',
298 :scmid => '12345',
336 :scmid => '12345',
299 :comments => str1,
337 :comments => str1,
300 :committer => str2)
338 :committer => str2)
301 assert( c.save )
339 assert( c.save )
302 assert_equal "Texte encod? en ISO-8859-1.", c.comments
340 assert_equal "Texte encod? en ISO-8859-1.", c.comments
303 assert_equal "?a?b?c?d?e test", c.committer
341 assert_equal "?a?b?c?d?e test", c.committer
304 end
342 end
305
343
306 def test_invalid_utf8_sequences_in_comments_should_be_replaced_ja_jis
344 def test_invalid_utf8_sequences_in_comments_should_be_replaced_ja_jis
307 proj = Project.find(3)
345 proj = Project.find(3)
308 str = "test\xb5\xfetest\xb5\xfe"
346 str = "test\xb5\xfetest\xb5\xfe"
309 if str.respond_to?(:force_encoding)
347 if str.respond_to?(:force_encoding)
310 str.force_encoding('ASCII-8BIT')
348 str.force_encoding('ASCII-8BIT')
311 end
349 end
312 r = Repository::Bazaar.create!(
350 r = Repository::Bazaar.create!(
313 :project => proj,
351 :project => proj,
314 :url => '/tmp/test/bazaar',
352 :url => '/tmp/test/bazaar',
315 :log_encoding => 'ISO-2022-JP' )
353 :log_encoding => 'ISO-2022-JP' )
316 assert r
354 assert r
317 c = Changeset.new(:repository => r,
355 c = Changeset.new(:repository => r,
318 :committed_on => Time.now,
356 :committed_on => Time.now,
319 :revision => '123',
357 :revision => '123',
320 :scmid => '12345',
358 :scmid => '12345',
321 :comments => str)
359 :comments => str)
322 assert( c.save )
360 assert( c.save )
323 assert_equal "test??test??", c.comments
361 assert_equal "test??test??", c.comments
324 end
362 end
325
363
326 def test_comments_should_be_converted_all_latin1_to_utf8
364 def test_comments_should_be_converted_all_latin1_to_utf8
327 s1 = "\xC2\x80"
365 s1 = "\xC2\x80"
328 s2 = "\xc3\x82\xc2\x80"
366 s2 = "\xc3\x82\xc2\x80"
329 s4 = s2.dup
367 s4 = s2.dup
330 if s1.respond_to?(:force_encoding)
368 if s1.respond_to?(:force_encoding)
331 s3 = s1.dup
369 s3 = s1.dup
332 s1.force_encoding('ASCII-8BIT')
370 s1.force_encoding('ASCII-8BIT')
333 s2.force_encoding('ASCII-8BIT')
371 s2.force_encoding('ASCII-8BIT')
334 s3.force_encoding('ISO-8859-1')
372 s3.force_encoding('ISO-8859-1')
335 s4.force_encoding('UTF-8')
373 s4.force_encoding('UTF-8')
336 assert_equal s3.encode('UTF-8'), s4
374 assert_equal s3.encode('UTF-8'), s4
337 end
375 end
338 proj = Project.find(3)
376 proj = Project.find(3)
339 r = Repository::Bazaar.create!(
377 r = Repository::Bazaar.create!(
340 :project => proj,
378 :project => proj,
341 :url => '/tmp/test/bazaar',
379 :url => '/tmp/test/bazaar',
342 :log_encoding => 'ISO-8859-1' )
380 :log_encoding => 'ISO-8859-1' )
343 assert r
381 assert r
344 c = Changeset.new(:repository => r,
382 c = Changeset.new(:repository => r,
345 :committed_on => Time.now,
383 :committed_on => Time.now,
346 :revision => '123',
384 :revision => '123',
347 :scmid => '12345',
385 :scmid => '12345',
348 :comments => s1)
386 :comments => s1)
349 assert( c.save )
387 assert( c.save )
350 assert_equal s4, c.comments
388 assert_equal s4, c.comments
351 end
389 end
352
390
353 def test_invalid_utf8_sequences_in_paths_should_be_replaced
391 def test_invalid_utf8_sequences_in_paths_should_be_replaced
354 proj = Project.find(3)
392 proj = Project.find(3)
355 str1 = "Texte encod\xe9 en ISO-8859-1"
393 str1 = "Texte encod\xe9 en ISO-8859-1"
356 str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
394 str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
357 str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
395 str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
358 str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
396 str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
359 r = Repository::Bazaar.create!(
397 r = Repository::Bazaar.create!(
360 :project => proj,
398 :project => proj,
361 :url => '/tmp/test/bazaar',
399 :url => '/tmp/test/bazaar',
362 :log_encoding => 'UTF-8' )
400 :log_encoding => 'UTF-8' )
363 assert r
401 assert r
364 cs = Changeset.new(
402 cs = Changeset.new(
365 :repository => r,
403 :repository => r,
366 :committed_on => Time.now,
404 :committed_on => Time.now,
367 :revision => '123',
405 :revision => '123',
368 :scmid => '12345',
406 :scmid => '12345',
369 :comments => "test")
407 :comments => "test")
370 assert(cs.save)
408 assert(cs.save)
371 ch = Change.new(
409 ch = Change.new(
372 :changeset => cs,
410 :changeset => cs,
373 :action => "A",
411 :action => "A",
374 :path => str1,
412 :path => str1,
375 :from_path => str2,
413 :from_path => str2,
376 :from_revision => "345")
414 :from_revision => "345")
377 assert(ch.save)
415 assert(ch.save)
378 assert_equal "Texte encod? en ISO-8859-1", ch.path
416 assert_equal "Texte encod? en ISO-8859-1", ch.path
379 assert_equal "?a?b?c?d?e test", ch.from_path
417 assert_equal "?a?b?c?d?e test", ch.from_path
380 end
418 end
381
419
382 def test_comments_nil
420 def test_comments_nil
383 proj = Project.find(3)
421 proj = Project.find(3)
384 r = Repository::Bazaar.create!(
422 r = Repository::Bazaar.create!(
385 :project => proj,
423 :project => proj,
386 :url => '/tmp/test/bazaar',
424 :url => '/tmp/test/bazaar',
387 :log_encoding => 'ISO-8859-1' )
425 :log_encoding => 'ISO-8859-1' )
388 assert r
426 assert r
389 c = Changeset.new(:repository => r,
427 c = Changeset.new(:repository => r,
390 :committed_on => Time.now,
428 :committed_on => Time.now,
391 :revision => '123',
429 :revision => '123',
392 :scmid => '12345',
430 :scmid => '12345',
393 :comments => nil,
431 :comments => nil,
394 :committer => nil)
432 :committer => nil)
395 assert( c.save )
433 assert( c.save )
396 assert_equal "", c.comments
434 assert_equal "", c.comments
397 assert_equal nil, c.committer
435 assert_equal nil, c.committer
398 if c.comments.respond_to?(:force_encoding)
436 if c.comments.respond_to?(:force_encoding)
399 assert_equal "UTF-8", c.comments.encoding.to_s
437 assert_equal "UTF-8", c.comments.encoding.to_s
400 end
438 end
401 end
439 end
402
440
403 def test_comments_empty
441 def test_comments_empty
404 proj = Project.find(3)
442 proj = Project.find(3)
405 r = Repository::Bazaar.create!(
443 r = Repository::Bazaar.create!(
406 :project => proj,
444 :project => proj,
407 :url => '/tmp/test/bazaar',
445 :url => '/tmp/test/bazaar',
408 :log_encoding => 'ISO-8859-1' )
446 :log_encoding => 'ISO-8859-1' )
409 assert r
447 assert r
410 c = Changeset.new(:repository => r,
448 c = Changeset.new(:repository => r,
411 :committed_on => Time.now,
449 :committed_on => Time.now,
412 :revision => '123',
450 :revision => '123',
413 :scmid => '12345',
451 :scmid => '12345',
414 :comments => "",
452 :comments => "",
415 :committer => "")
453 :committer => "")
416 assert( c.save )
454 assert( c.save )
417 assert_equal "", c.comments
455 assert_equal "", c.comments
418 assert_equal "", c.committer
456 assert_equal "", c.committer
419 if c.comments.respond_to?(:force_encoding)
457 if c.comments.respond_to?(:force_encoding)
420 assert_equal "UTF-8", c.comments.encoding.to_s
458 assert_equal "UTF-8", c.comments.encoding.to_s
421 assert_equal "UTF-8", c.committer.encoding.to_s
459 assert_equal "UTF-8", c.committer.encoding.to_s
422 end
460 end
423 end
461 end
424
462
425 def test_identifier
463 def test_identifier
426 c = Changeset.find_by_revision('1')
464 c = Changeset.find_by_revision('1')
427 assert_equal c.revision, c.identifier
465 assert_equal c.revision, c.identifier
428 end
466 end
429 end
467 end
General Comments 0
You need to be logged in to leave comments. Login now