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