comparison app/models/changeset.rb @ 245:051f544170fe

* Update to SVN trunk revision 4993
author Chris Cannam
date Thu, 03 Mar 2011 11:42:28 +0000
parents 8661b858af72
children eeebe205a056 cbce1fd3b1b7
comparison
equal deleted inserted replaced
244:8972b600f4fb 245:051f544170fe
54 repository.class.changeset_identifier self 54 repository.class.changeset_identifier self
55 else 55 else
56 revision.to_s 56 revision.to_s
57 end 57 end
58 end 58 end
59
60 def comments=(comment)
61 write_attribute(:comments, Changeset.normalize_comments(comment))
62 end
63 59
64 def committed_on=(date) 60 def committed_on=(date)
65 self.commit_date = date 61 self.commit_date = date
66 super 62 super
67 end 63 end
73 else 69 else
74 identifier 70 identifier
75 end 71 end
76 end 72 end
77 73
78 def committer=(arg)
79 write_attribute(:committer, self.class.to_utf8(arg.to_s))
80 end
81
82 def project 74 def project
83 repository.project 75 repository.project
84 end 76 end
85 77
86 def author 78 def author
87 user || committer.to_s.split('<').first 79 user || committer.to_s.split('<').first
88 end 80 end
89 81
90 def before_create 82 def before_create
91 self.user = repository.find_committer_user(committer) 83 self.committer = self.class.to_utf8(self.committer, repository.repo_log_encoding)
92 end 84 self.comments = self.class.normalize_comments(self.comments, repository.repo_log_encoding)
93 85 self.user = repository.find_committer_user(self.committer)
86 end
87
94 def after_create 88 def after_create
95 scan_comment_for_issue_ids 89 scan_comment_for_issue_ids
96 end 90 end
97 91
98 TIMELOG_RE = / 92 TIMELOG_RE = /
99 ( 93 (
100 (\d+([.,]\d+)?)h? 94 ((\d+)(h|hours?))((\d+)(m|min)?)?
95 |
96 ((\d+)(h|hours?|m|min))
101 | 97 |
102 (\d+):(\d+) 98 (\d+):(\d+)
103 | 99 |
104 ((\d+)(h|hours?))?((\d+)(m|min)?)? 100 (\d+([\.,]\d+)?)h?
105 ) 101 )
106 /x 102 /x
107 103
108 def scan_comment_for_issue_ids 104 def scan_comment_for_issue_ids
109 return if comments.blank? 105 return if comments.blank?
159 # Returns the next changeset 155 # Returns the next changeset
160 def next 156 def next
161 @next ||= Changeset.find(:first, :conditions => ['id > ? AND repository_id = ?', self.id, self.repository_id], :order => 'id ASC') 157 @next ||= Changeset.find(:first, :conditions => ['id > ? AND repository_id = ?', self.id, self.repository_id], :order => 'id ASC')
162 end 158 end
163 159
164 # Strips and reencodes a commit log before insertion into the database
165 def self.normalize_comments(str)
166 to_utf8(str.to_s.strip)
167 end
168
169 # Creates a new Change from it's common parameters 160 # Creates a new Change from it's common parameters
170 def create_change(change) 161 def create_change(change)
171 Change.create(:changeset => self, 162 Change.create(:changeset => self,
172 :action => change[:action], 163 :action => change[:action],
173 :path => change[:path], 164 :path => change[:path],
174 :from_path => change[:from_path], 165 :from_path => change[:from_path],
175 :from_revision => change[:from_revision]) 166 :from_revision => change[:from_revision])
176 end 167 end
177 168
178 private 169 private
179 170
180 # Finds an issue that can be referenced by the commit message 171 # Finds an issue that can be referenced by the commit message
181 # i.e. an issue that belong to the repository project, a subproject or a parent project 172 # i.e. an issue that belong to the repository project, a subproject or a parent project
182 def find_referenced_issue_by_id(id) 173 def find_referenced_issue_by_id(id)
242 @short_comments = $1 || comments 233 @short_comments = $1 || comments
243 @long_comments = $2.to_s.strip 234 @long_comments = $2.to_s.strip
244 return @short_comments, @long_comments 235 return @short_comments, @long_comments
245 end 236 end
246 237
247 def self.to_utf8(str) 238 public
248 if str.respond_to?(:force_encoding) 239
249 str.force_encoding('UTF-8') 240 # Strips and reencodes a commit log before insertion into the database
250 return str if str.valid_encoding? 241 def self.normalize_comments(str, encoding)
251 else 242 Changeset.to_utf8(str.to_s.strip, encoding)
252 return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii 243 end
253 end 244
254 245 private
255 encoding = Setting.commit_logs_encoding.to_s.strip 246
247 def self.to_utf8(str, encoding)
248 return str if str.blank?
256 unless encoding.blank? || encoding == 'UTF-8' 249 unless encoding.blank? || encoding == 'UTF-8'
257 begin 250 begin
258 str = Iconv.conv('UTF-8', encoding, str) 251 str = Iconv.conv('UTF-8', encoding, str)
259 rescue Iconv::Failure 252 rescue Iconv::Failure
260 # do nothing here 253 # do nothing here
261 end 254 end
262 end 255 end
263 # removes invalid UTF8 sequences 256 if str.respond_to?(:force_encoding)
264 begin 257 str.force_encoding('UTF-8')
265 Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3] 258 if ! str.valid_encoding?
266 rescue Iconv::InvalidEncoding 259 str = str.encode("US-ASCII", :invalid => :replace,
267 # "UTF-8//IGNORE" is not supported on some OS 260 :undef => :replace, :replace => '?').encode("UTF-8")
268 str 261 end
269 end 262 else
263 # removes invalid UTF8 sequences
264 begin
265 str = Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3]
266 rescue Iconv::InvalidEncoding
267 # "UTF-8//IGNORE" is not supported on some OS
268 end
269 end
270 str
270 end 271 end
271 end 272 end