##// END OF EJS Templates
Adds the repository identifier to Changeset#text_tag (#779)....
Jean-Philippe Lang -
r9135:bb36fa5d1208
parent child
Show More
@@ -1,275 +1,278
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 154 def text_tag(ref_project=nil)
155 155 tag = if scmid?
156 156 "commit:#{scmid}"
157 157 else
158 158 "r#{revision}"
159 159 end
160 if repository && repository.identifier.present?
161 tag = "#{repository.identifier}|#{tag}"
162 end
160 163 if ref_project && project && ref_project != project
161 164 tag = "#{project.identifier}:#{tag}"
162 165 end
163 166 tag
164 167 end
165 168
166 169 # Returns the previous changeset
167 170 def previous
168 171 @previous ||= Changeset.find(:first,
169 172 :conditions => ['id < ? AND repository_id = ?',
170 173 self.id, self.repository_id],
171 174 :order => 'id DESC')
172 175 end
173 176
174 177 # Returns the next changeset
175 178 def next
176 179 @next ||= Changeset.find(:first,
177 180 :conditions => ['id > ? AND repository_id = ?',
178 181 self.id, self.repository_id],
179 182 :order => 'id ASC')
180 183 end
181 184
182 185 # Creates a new Change from it's common parameters
183 186 def create_change(change)
184 187 Change.create(:changeset => self,
185 188 :action => change[:action],
186 189 :path => change[:path],
187 190 :from_path => change[:from_path],
188 191 :from_revision => change[:from_revision])
189 192 end
190 193
191 194 # Finds an issue that can be referenced by the commit message
192 195 def find_referenced_issue_by_id(id)
193 196 return nil if id.blank?
194 197 issue = Issue.find_by_id(id.to_i, :include => :project)
195 198 if Setting.commit_cross_project_ref?
196 199 # all issues can be referenced/fixed
197 200 elsif issue
198 201 # issue that belong to the repository project, a subproject or a parent project only
199 202 unless issue.project &&
200 203 (project == issue.project || project.is_ancestor_of?(issue.project) ||
201 204 project.is_descendant_of?(issue.project))
202 205 issue = nil
203 206 end
204 207 end
205 208 issue
206 209 end
207 210
208 211 private
209 212
210 213 def fix_issue(issue)
211 214 status = IssueStatus.find_by_id(Setting.commit_fix_status_id.to_i)
212 215 if status.nil?
213 216 logger.warn("No status matches commit_fix_status_id setting (#{Setting.commit_fix_status_id})") if logger
214 217 return issue
215 218 end
216 219
217 220 # the issue may have been updated by the closure of another one (eg. duplicate)
218 221 issue.reload
219 222 # don't change the status is the issue is closed
220 223 return if issue.status && issue.status.is_closed?
221 224
222 225 journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, text_tag(issue.project)))
223 226 issue.status = status
224 227 unless Setting.commit_fix_done_ratio.blank?
225 228 issue.done_ratio = Setting.commit_fix_done_ratio.to_i
226 229 end
227 230 Redmine::Hook.call_hook(:model_changeset_scan_commit_for_issue_ids_pre_issue_update,
228 231 { :changeset => self, :issue => issue })
229 232 unless issue.save
230 233 logger.warn("Issue ##{issue.id} could not be saved by changeset #{id}: #{issue.errors.full_messages}") if logger
231 234 end
232 235 issue
233 236 end
234 237
235 238 def log_time(issue, hours)
236 239 time_entry = TimeEntry.new(
237 240 :user => user,
238 241 :hours => hours,
239 242 :issue => issue,
240 243 :spent_on => commit_date,
241 244 :comments => l(:text_time_logged_by_changeset, :value => text_tag(issue.project),
242 245 :locale => Setting.default_language)
243 246 )
244 247 time_entry.activity = log_time_activity unless log_time_activity.nil?
245 248
246 249 unless time_entry.save
247 250 logger.warn("TimeEntry could not be created by changeset #{id}: #{time_entry.errors.full_messages}") if logger
248 251 end
249 252 time_entry
250 253 end
251 254
252 255 def log_time_activity
253 256 if Setting.commit_logtime_activity_id.to_i > 0
254 257 TimeEntryActivity.find_by_id(Setting.commit_logtime_activity_id.to_i)
255 258 end
256 259 end
257 260
258 261 def split_comments
259 262 comments =~ /\A(.+?)\r?\n(.*)$/m
260 263 @short_comments = $1 || comments
261 264 @long_comments = $2.to_s.strip
262 265 return @short_comments, @long_comments
263 266 end
264 267
265 268 public
266 269
267 270 # Strips and reencodes a commit log before insertion into the database
268 271 def self.normalize_comments(str, encoding)
269 272 Changeset.to_utf8(str.to_s.strip, encoding)
270 273 end
271 274
272 275 def self.to_utf8(str, encoding)
273 276 Redmine::CodesetUtil.to_utf8(str, encoding)
274 277 end
275 278 end
@@ -1,467 +1,478
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 181 def test_commit_closing_a_subproject_issue
182 182 with_settings :commit_fix_status_id => 5, :commit_fix_keywords => 'closes' do
183 183 issue = Issue.find(5)
184 184 assert !issue.closed?
185 185 assert_difference 'Journal.count' do
186 186 c = Changeset.new(:repository => Project.find(1).repository,
187 187 :committed_on => Time.now,
188 188 :comments => 'closes #5, a subproject issue',
189 189 :revision => '12345')
190 190 assert c.save
191 191 end
192 192 assert issue.reload.closed?
193 193 journal = Journal.first(:order => 'id DESC')
194 194 assert_equal issue, journal.issue
195 195 assert_include "Applied in changeset ecookbook:r12345.", journal.notes
196 196 end
197 197 end
198 198
199 199 def test_commit_referencing_a_parent_project_issue
200 200 # repository of child project
201 201 r = Repository::Subversion.create!(
202 202 :project => Project.find(3),
203 203 :url => 'svn://localhost/test')
204 204 c = Changeset.new(:repository => r,
205 205 :committed_on => Time.now,
206 206 :comments => 'refs #2, an issue of a parent project',
207 207 :revision => '12345')
208 208 assert c.save
209 209 assert_equal [2], c.issue_ids.sort
210 210 assert c.issues.first.project != c.project
211 211 end
212 212
213 213 def test_commit_referencing_a_project_with_commit_cross_project_ref_disabled
214 214 r = Repository::Subversion.create!(
215 215 :project => Project.find(3),
216 216 :url => 'svn://localhost/test')
217 217
218 218 with_settings :commit_cross_project_ref => '0' do
219 219 c = Changeset.new(:repository => r,
220 220 :committed_on => Time.now,
221 221 :comments => 'refs #4, an issue of a different project',
222 222 :revision => '12345')
223 223 assert c.save
224 224 assert_equal [], c.issue_ids
225 225 end
226 226 end
227 227
228 228 def test_commit_referencing_a_project_with_commit_cross_project_ref_enabled
229 229 r = Repository::Subversion.create!(
230 230 :project => Project.find(3),
231 231 :url => 'svn://localhost/test')
232 232
233 233 with_settings :commit_cross_project_ref => '1' do
234 234 c = Changeset.new(:repository => r,
235 235 :committed_on => Time.now,
236 236 :comments => 'refs #4, an issue of a different project',
237 237 :revision => '12345')
238 238 assert c.save
239 239 assert_equal [4], c.issue_ids
240 240 end
241 241 end
242 242
243 243 def test_text_tag_revision
244 244 c = Changeset.new(:revision => '520')
245 245 assert_equal 'r520', c.text_tag
246 246 end
247 247
248 248 def test_text_tag_revision_with_same_project
249 249 c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
250 250 assert_equal 'r520', c.text_tag(Project.find(1))
251 251 end
252 252
253 253 def test_text_tag_revision_with_different_project
254 254 c = Changeset.new(:revision => '520', :repository => Project.find(1).repository)
255 255 assert_equal 'ecookbook:r520', c.text_tag(Project.find(2))
256 256 end
257 257
258 def test_text_tag_revision_with_repository_identifier
259 r = Repository::Subversion.create!(
260 :project_id => 1,
261 :url => 'svn://localhost/test',
262 :identifier => 'documents')
263
264 c = Changeset.new(:revision => '520', :repository => r)
265 assert_equal 'documents|r520', c.text_tag
266 assert_equal 'ecookbook:documents|r520', c.text_tag(Project.find(2))
267 end
268
258 269 def test_text_tag_hash
259 270 c = Changeset.new(
260 271 :scmid => '7234cb2750b63f47bff735edc50a1c0a433c2518',
261 272 :revision => '7234cb2750b63f47bff735edc50a1c0a433c2518')
262 273 assert_equal 'commit:7234cb2750b63f47bff735edc50a1c0a433c2518', c.text_tag
263 274 end
264 275
265 276 def test_text_tag_hash_with_same_project
266 277 c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
267 278 assert_equal 'commit:7234cb27', c.text_tag(Project.find(1))
268 279 end
269 280
270 281 def test_text_tag_hash_with_different_project
271 282 c = Changeset.new(:revision => '7234cb27', :scmid => '7234cb27', :repository => Project.find(1).repository)
272 283 assert_equal 'ecookbook:commit:7234cb27', c.text_tag(Project.find(2))
273 284 end
274 285
275 286 def test_text_tag_hash_all_number
276 287 c = Changeset.new(:scmid => '0123456789', :revision => '0123456789')
277 288 assert_equal 'commit:0123456789', c.text_tag
278 289 end
279 290
280 291 def test_previous
281 292 changeset = Changeset.find_by_revision('3')
282 293 assert_equal Changeset.find_by_revision('2'), changeset.previous
283 294 end
284 295
285 296 def test_previous_nil
286 297 changeset = Changeset.find_by_revision('1')
287 298 assert_nil changeset.previous
288 299 end
289 300
290 301 def test_next
291 302 changeset = Changeset.find_by_revision('2')
292 303 assert_equal Changeset.find_by_revision('3'), changeset.next
293 304 end
294 305
295 306 def test_next_nil
296 307 changeset = Changeset.find_by_revision('10')
297 308 assert_nil changeset.next
298 309 end
299 310
300 311 def test_comments_should_be_converted_to_utf8
301 312 proj = Project.find(3)
302 313 # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
303 314 str = "Texte encod\xe9 en ISO-8859-1."
304 315 str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
305 316 r = Repository::Bazaar.create!(
306 317 :project => proj,
307 318 :url => '/tmp/test/bazaar',
308 319 :log_encoding => 'ISO-8859-1' )
309 320 assert r
310 321 c = Changeset.new(:repository => r,
311 322 :committed_on => Time.now,
312 323 :revision => '123',
313 324 :scmid => '12345',
314 325 :comments => str)
315 326 assert( c.save )
316 327 str_utf8 = "Texte encod\xc3\xa9 en ISO-8859-1."
317 328 str_utf8.force_encoding("UTF-8") if str_utf8.respond_to?(:force_encoding)
318 329 assert_equal str_utf8, c.comments
319 330 end
320 331
321 332 def test_invalid_utf8_sequences_in_comments_should_be_replaced_latin1
322 333 proj = Project.find(3)
323 334 # str = File.read("#{RAILS_ROOT}/test/fixtures/encoding/iso-8859-1.txt")
324 335 str1 = "Texte encod\xe9 en ISO-8859-1."
325 336 str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
326 337 str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
327 338 str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
328 339 r = Repository::Bazaar.create!(
329 340 :project => proj,
330 341 :url => '/tmp/test/bazaar',
331 342 :log_encoding => 'UTF-8' )
332 343 assert r
333 344 c = Changeset.new(:repository => r,
334 345 :committed_on => Time.now,
335 346 :revision => '123',
336 347 :scmid => '12345',
337 348 :comments => str1,
338 349 :committer => str2)
339 350 assert( c.save )
340 351 assert_equal "Texte encod? en ISO-8859-1.", c.comments
341 352 assert_equal "?a?b?c?d?e test", c.committer
342 353 end
343 354
344 355 def test_invalid_utf8_sequences_in_comments_should_be_replaced_ja_jis
345 356 proj = Project.find(3)
346 357 str = "test\xb5\xfetest\xb5\xfe"
347 358 if str.respond_to?(:force_encoding)
348 359 str.force_encoding('ASCII-8BIT')
349 360 end
350 361 r = Repository::Bazaar.create!(
351 362 :project => proj,
352 363 :url => '/tmp/test/bazaar',
353 364 :log_encoding => 'ISO-2022-JP' )
354 365 assert r
355 366 c = Changeset.new(:repository => r,
356 367 :committed_on => Time.now,
357 368 :revision => '123',
358 369 :scmid => '12345',
359 370 :comments => str)
360 371 assert( c.save )
361 372 assert_equal "test??test??", c.comments
362 373 end
363 374
364 375 def test_comments_should_be_converted_all_latin1_to_utf8
365 376 s1 = "\xC2\x80"
366 377 s2 = "\xc3\x82\xc2\x80"
367 378 s4 = s2.dup
368 379 if s1.respond_to?(:force_encoding)
369 380 s3 = s1.dup
370 381 s1.force_encoding('ASCII-8BIT')
371 382 s2.force_encoding('ASCII-8BIT')
372 383 s3.force_encoding('ISO-8859-1')
373 384 s4.force_encoding('UTF-8')
374 385 assert_equal s3.encode('UTF-8'), s4
375 386 end
376 387 proj = Project.find(3)
377 388 r = Repository::Bazaar.create!(
378 389 :project => proj,
379 390 :url => '/tmp/test/bazaar',
380 391 :log_encoding => 'ISO-8859-1' )
381 392 assert r
382 393 c = Changeset.new(:repository => r,
383 394 :committed_on => Time.now,
384 395 :revision => '123',
385 396 :scmid => '12345',
386 397 :comments => s1)
387 398 assert( c.save )
388 399 assert_equal s4, c.comments
389 400 end
390 401
391 402 def test_invalid_utf8_sequences_in_paths_should_be_replaced
392 403 proj = Project.find(3)
393 404 str1 = "Texte encod\xe9 en ISO-8859-1"
394 405 str2 = "\xe9a\xe9b\xe9c\xe9d\xe9e test"
395 406 str1.force_encoding("UTF-8") if str1.respond_to?(:force_encoding)
396 407 str2.force_encoding("ASCII-8BIT") if str2.respond_to?(:force_encoding)
397 408 r = Repository::Bazaar.create!(
398 409 :project => proj,
399 410 :url => '/tmp/test/bazaar',
400 411 :log_encoding => 'UTF-8' )
401 412 assert r
402 413 cs = Changeset.new(
403 414 :repository => r,
404 415 :committed_on => Time.now,
405 416 :revision => '123',
406 417 :scmid => '12345',
407 418 :comments => "test")
408 419 assert(cs.save)
409 420 ch = Change.new(
410 421 :changeset => cs,
411 422 :action => "A",
412 423 :path => str1,
413 424 :from_path => str2,
414 425 :from_revision => "345")
415 426 assert(ch.save)
416 427 assert_equal "Texte encod? en ISO-8859-1", ch.path
417 428 assert_equal "?a?b?c?d?e test", ch.from_path
418 429 end
419 430
420 431 def test_comments_nil
421 432 proj = Project.find(3)
422 433 r = Repository::Bazaar.create!(
423 434 :project => proj,
424 435 :url => '/tmp/test/bazaar',
425 436 :log_encoding => 'ISO-8859-1' )
426 437 assert r
427 438 c = Changeset.new(:repository => r,
428 439 :committed_on => Time.now,
429 440 :revision => '123',
430 441 :scmid => '12345',
431 442 :comments => nil,
432 443 :committer => nil)
433 444 assert( c.save )
434 445 assert_equal "", c.comments
435 446 assert_equal nil, c.committer
436 447 if c.comments.respond_to?(:force_encoding)
437 448 assert_equal "UTF-8", c.comments.encoding.to_s
438 449 end
439 450 end
440 451
441 452 def test_comments_empty
442 453 proj = Project.find(3)
443 454 r = Repository::Bazaar.create!(
444 455 :project => proj,
445 456 :url => '/tmp/test/bazaar',
446 457 :log_encoding => 'ISO-8859-1' )
447 458 assert r
448 459 c = Changeset.new(:repository => r,
449 460 :committed_on => Time.now,
450 461 :revision => '123',
451 462 :scmid => '12345',
452 463 :comments => "",
453 464 :committer => "")
454 465 assert( c.save )
455 466 assert_equal "", c.comments
456 467 assert_equal "", c.committer
457 468 if c.comments.respond_to?(:force_encoding)
458 469 assert_equal "UTF-8", c.comments.encoding.to_s
459 470 assert_equal "UTF-8", c.committer.encoding.to_s
460 471 end
461 472 end
462 473
463 474 def test_identifier
464 475 c = Changeset.find_by_revision('1')
465 476 assert_equal c.revision, c.identifier
466 477 end
467 478 end
General Comments 0
You need to be logged in to leave comments. Login now