| 
									
										
										
										
											2008-11-10 18:59:06 +00:00
										 |  |  | # Redmine - project management software | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | # Copyright (C) 2006-2011  Jean-Philippe Lang | 
					
						
							| 
									
										
										
										
											2007-03-25 12:12:15 +00:00
										 |  |  | # | 
					
						
							|  |  |  | # This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  | # modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  | # as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  | # of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2007-03-25 12:12:15 +00:00
										 |  |  | # This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | # GNU General Public License for more details. | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2007-03-25 12:12:15 +00:00
										 |  |  | # You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | # along with this program; if not, write to the Free Software | 
					
						
							|  |  |  | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-26 12:13:15 +00:00
										 |  |  | require 'iconv' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-25 12:12:15 +00:00
										 |  |  | class Changeset < ActiveRecord::Base | 
					
						
							|  |  |  |   belongs_to :repository | 
					
						
							| 
									
										
										
										
											2008-11-10 18:59:06 +00:00
										 |  |  |   belongs_to :user | 
					
						
							| 
									
										
										
										
											2007-03-25 12:12:15 +00:00
										 |  |  |   has_many :changes, :dependent => :delete_all | 
					
						
							| 
									
										
										
										
											2007-04-24 13:57:27 +00:00
										 |  |  |   has_and_belongs_to_many :issues | 
					
						
							| 
									
										
										
										
											2007-08-29 16:52:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-02 09:45:05 +00:00
										 |  |  |   acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.format_identifier}" + (o.short_comments.blank? ? '' : (': ' + o.short_comments))}, | 
					
						
							| 
									
										
										
										
											2009-02-01 15:48:56 +00:00
										 |  |  |                 :description => :long_comments, | 
					
						
							| 
									
										
										
										
											2007-08-29 16:52:35 +00:00
										 |  |  |                 :datetime => :committed_on, | 
					
						
							| 
									
										
										
										
											2011-01-02 09:45:05 +00:00
										 |  |  |                 :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project, :rev => o.identifier}} | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-27 17:28:22 +00:00
										 |  |  |   acts_as_searchable :columns => 'comments', | 
					
						
							| 
									
										
										
										
											2008-05-18 16:15:22 +00:00
										 |  |  |                      :include => {:repository => :project}, | 
					
						
							| 
									
										
										
										
											2007-09-27 17:28:22 +00:00
										 |  |  |                      :project_key => "#{Repository.table_name}.project_id", | 
					
						
							|  |  |  |                      :date_column => 'committed_on' | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-27 17:54:09 +00:00
										 |  |  |   acts_as_activity_provider :timestamp => "#{table_name}.committed_on", | 
					
						
							| 
									
										
										
										
											2008-11-30 11:18:22 +00:00
										 |  |  |                             :author_key => :user_id, | 
					
						
							| 
									
										
										
										
											2009-04-07 17:30:56 +00:00
										 |  |  |                             :find_options => {:include => [:user, {:repository => :project}]} | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-25 17:11:46 +00:00
										 |  |  |   validates_presence_of :repository_id, :revision, :committed_on, :commit_date | 
					
						
							| 
									
										
										
										
											2007-03-25 12:12:15 +00:00
										 |  |  |   validates_uniqueness_of :revision, :scope => :repository_id | 
					
						
							| 
									
										
										
										
											2007-06-24 19:30:38 +00:00
										 |  |  |   validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-31 16:25:06 +00:00
										 |  |  |   named_scope :visible, lambda {|*args| { :include => {:repository => :project}, | 
					
						
							| 
									
										
										
										
											2011-04-05 12:50:19 +00:00
										 |  |  |                                           :conditions => Project.allowed_to_condition(args.shift || User.current, :view_changesets, *args) } } | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-26 17:56:26 +00:00
										 |  |  |   def revision=(r) | 
					
						
							|  |  |  |     write_attribute :revision, (r.nil? ? nil : r.to_s) | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-01-02 09:45:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   # Returns the identifier of this changeset; depending on repository backends | 
					
						
							|  |  |  |   def identifier | 
					
						
							|  |  |  |     if repository.class.respond_to? :changeset_identifier | 
					
						
							|  |  |  |       repository.class.changeset_identifier self | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       revision.to_s | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2007-08-25 14:41:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-25 17:11:46 +00:00
										 |  |  |   def committed_on=(date) | 
					
						
							|  |  |  |     self.commit_date = date | 
					
						
							|  |  |  |     super | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-01-02 09:45:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   # Returns the readable identifier | 
					
						
							|  |  |  |   def format_identifier | 
					
						
							|  |  |  |     if repository.class.respond_to? :format_changeset_identifier | 
					
						
							|  |  |  |       repository.class.format_changeset_identifier self | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       identifier | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-11 19:33:38 +00:00
										 |  |  |   def project | 
					
						
							|  |  |  |     repository.project | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-04-09 09:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-10 18:59:06 +00:00
										 |  |  |   def author | 
					
						
							|  |  |  |     user || committer.to_s.split('<').first | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-04-09 09:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-10 18:59:06 +00:00
										 |  |  |   def before_create | 
					
						
							| 
									
										
										
										
											2011-02-28 12:09:32 +00:00
										 |  |  |     self.committer = self.class.to_utf8(self.committer, repository.repo_log_encoding) | 
					
						
							| 
									
										
										
										
											2011-04-09 09:30:50 +00:00
										 |  |  |     self.comments  = self.class.normalize_comments( | 
					
						
							|  |  |  |                        self.comments, repository.repo_log_encoding) | 
					
						
							| 
									
										
										
										
											2011-02-28 12:09:32 +00:00
										 |  |  |     self.user = repository.find_committer_user(self.committer) | 
					
						
							| 
									
										
										
										
											2008-11-10 18:59:06 +00:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-02-28 12:09:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-24 13:57:27 +00:00
										 |  |  |   def after_create | 
					
						
							|  |  |  |     scan_comment_for_issue_ids | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-04-09 09:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |   TIMELOG_RE = /
 | 
					
						
							|  |  |  |     ( | 
					
						
							| 
									
										
										
										
											2011-02-26 14:46:19 +00:00
										 |  |  |     ((\d+)(h|hours?))((\d+)(m|min)?)? | 
					
						
							|  |  |  |     | | 
					
						
							|  |  |  |     ((\d+)(h|hours?|m|min)) | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |     | | 
					
						
							|  |  |  |     (\d+):(\d+) | 
					
						
							|  |  |  |     | | 
					
						
							| 
									
										
										
										
											2011-02-26 14:46:19 +00:00
										 |  |  |     (\d+([\.,]\d+)?)h? | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  |     /x
 | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-04-24 13:57:27 +00:00
										 |  |  |   def scan_comment_for_issue_ids | 
					
						
							| 
									
										
										
										
											2007-04-25 15:06:20 +00:00
										 |  |  |     return if comments.blank? | 
					
						
							| 
									
										
										
										
											2007-04-24 13:57:27 +00:00
										 |  |  |     # keywords used to reference issues | 
					
						
							| 
									
										
										
										
											2007-10-22 16:52:36 +00:00
										 |  |  |     ref_keywords = Setting.commit_ref_keywords.downcase.split(",").collect(&:strip) | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |     ref_keywords_any = ref_keywords.delete('*') | 
					
						
							| 
									
										
										
										
											2007-04-24 13:57:27 +00:00
										 |  |  |     # keywords used to fix issues | 
					
						
							| 
									
										
										
										
											2007-10-22 16:52:36 +00:00
										 |  |  |     fix_keywords = Setting.commit_fix_keywords.downcase.split(",").collect(&:strip) | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-22 16:52:36 +00:00
										 |  |  |     kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|") | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-22 16:52:36 +00:00
										 |  |  |     referenced_issues = [] | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |     comments.scan(/([\s\(\[,-]|^)((#{kw_regexp})[\s:]+)?(#\d+(\s+@#{TIMELOG_RE})?([\s,;&]+#\d+(\s+@#{TIMELOG_RE})?)*)(?=[[:punct:]]|\s|<|$)/i) do |match| | 
					
						
							|  |  |  |       action, refs = match[2], match[3] | 
					
						
							|  |  |  |       next unless action.present? || ref_keywords_any | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |       refs.scan(/#(\d+)(\s+@#{TIMELOG_RE})?/).each do |m| | 
					
						
							|  |  |  |         issue, hours = find_referenced_issue_by_id(m[0].to_i), m[2] | 
					
						
							|  |  |  |         if issue | 
					
						
							|  |  |  |           referenced_issues << issue | 
					
						
							|  |  |  |           fix_issue(issue) if fix_keywords.include?(action.to_s.downcase) | 
					
						
							|  |  |  |           log_time(issue, hours) if hours && Setting.commit_logtime_enabled? | 
					
						
							| 
									
										
										
										
											2007-04-24 13:57:27 +00:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-21 14:43:45 +00:00
										 |  |  |     referenced_issues.uniq! | 
					
						
							|  |  |  |     self.issues = referenced_issues unless referenced_issues.empty? | 
					
						
							| 
									
										
										
										
											2007-04-24 13:57:27 +00:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 15:48:56 +00:00
										 |  |  |   def short_comments | 
					
						
							|  |  |  |     @short_comments || split_comments.first | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 15:48:56 +00:00
										 |  |  |   def long_comments | 
					
						
							|  |  |  |     @long_comments || split_comments.last | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def text_tag | 
					
						
							| 
									
										
										
										
											2010-12-11 14:20:04 +00:00
										 |  |  |     if scmid? | 
					
						
							|  |  |  |       "commit:#{scmid}" | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2010-12-11 14:20:04 +00:00
										 |  |  |       "r#{revision}" | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-04-09 23:21:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-01 17:15:42 +00:00
										 |  |  |   # Returns the previous changeset | 
					
						
							|  |  |  |   def previous | 
					
						
							| 
									
										
										
										
											2011-04-09 23:21:04 +00:00
										 |  |  |     @previous ||= Changeset.find(:first, | 
					
						
							|  |  |  |                     :conditions => ['id < ? AND repository_id = ?', | 
					
						
							|  |  |  |                                     self.id, self.repository_id], | 
					
						
							|  |  |  |                     :order => 'id DESC') | 
					
						
							| 
									
										
										
										
											2007-12-01 17:15:42 +00:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Returns the next changeset | 
					
						
							|  |  |  |   def next | 
					
						
							| 
									
										
										
										
											2011-04-09 23:21:04 +00:00
										 |  |  |     @next ||= Changeset.find(:first, | 
					
						
							|  |  |  |                     :conditions => ['id > ? AND repository_id = ?', | 
					
						
							|  |  |  |                                     self.id, self.repository_id], | 
					
						
							|  |  |  |                     :order => 'id ASC') | 
					
						
							| 
									
										
										
										
											2007-12-01 17:15:42 +00:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-04-09 23:21:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 17:02:32 +00:00
										 |  |  |   # Creates a new Change from it's common parameters | 
					
						
							|  |  |  |   def create_change(change) | 
					
						
							| 
									
										
										
										
											2011-04-09 23:21:04 +00:00
										 |  |  |     Change.create(:changeset     => self, | 
					
						
							|  |  |  |                   :action        => change[:action], | 
					
						
							|  |  |  |                   :path          => change[:path], | 
					
						
							|  |  |  |                   :from_path     => change[:from_path], | 
					
						
							| 
									
										
										
										
											2010-02-02 17:02:32 +00:00
										 |  |  |                   :from_revision => change[:from_revision]) | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-02-28 12:09:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-26 12:13:15 +00:00
										 |  |  |   private | 
					
						
							| 
									
										
										
										
											2008-11-10 18:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |   # Finds an issue that can be referenced by the commit message | 
					
						
							|  |  |  |   # i.e. an issue that belong to the repository project, a subproject or a parent project | 
					
						
							|  |  |  |   def find_referenced_issue_by_id(id) | 
					
						
							|  |  |  |     return nil if id.blank? | 
					
						
							|  |  |  |     issue = Issue.find_by_id(id.to_i, :include => :project) | 
					
						
							|  |  |  |     if issue | 
					
						
							| 
									
										
										
										
											2011-04-09 09:30:50 +00:00
										 |  |  |       unless issue.project && | 
					
						
							|  |  |  |                 (project == issue.project || project.is_ancestor_of?(issue.project) || | 
					
						
							|  |  |  |                  project.is_descendant_of?(issue.project)) | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |         issue = nil | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     issue | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |   def fix_issue(issue) | 
					
						
							|  |  |  |     status = IssueStatus.find_by_id(Setting.commit_fix_status_id.to_i) | 
					
						
							|  |  |  |     if status.nil? | 
					
						
							|  |  |  |       logger.warn("No status macthes commit_fix_status_id setting (#{Setting.commit_fix_status_id})") if logger | 
					
						
							|  |  |  |       return issue | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |     # the issue may have been updated by the closure of another one (eg. duplicate) | 
					
						
							|  |  |  |     issue.reload | 
					
						
							|  |  |  |     # don't change the status is the issue is closed | 
					
						
							|  |  |  |     return if issue.status && issue.status.is_closed? | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |     journal = issue.init_journal(user || User.anonymous, ll(Setting.default_language, :text_status_changed_by_changeset, text_tag)) | 
					
						
							|  |  |  |     issue.status = status | 
					
						
							|  |  |  |     unless Setting.commit_fix_done_ratio.blank? | 
					
						
							|  |  |  |       issue.done_ratio = Setting.commit_fix_done_ratio.to_i | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     Redmine::Hook.call_hook(:model_changeset_scan_commit_for_issue_ids_pre_issue_update, | 
					
						
							|  |  |  |                             { :changeset => self, :issue => issue }) | 
					
						
							|  |  |  |     unless issue.save | 
					
						
							|  |  |  |       logger.warn("Issue ##{issue.id} could not be saved by changeset #{id}: #{issue.errors.full_messages}") if logger | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     issue | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-04-09 09:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |   def log_time(issue, hours) | 
					
						
							|  |  |  |     time_entry = TimeEntry.new( | 
					
						
							|  |  |  |       :user => user, | 
					
						
							|  |  |  |       :hours => hours, | 
					
						
							|  |  |  |       :issue => issue, | 
					
						
							|  |  |  |       :spent_on => commit_date, | 
					
						
							| 
									
										
										
										
											2011-04-09 09:30:50 +00:00
										 |  |  |       :comments => l(:text_time_logged_by_changeset, :value => text_tag, | 
					
						
							|  |  |  |                      :locale => Setting.default_language) | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |       ) | 
					
						
							|  |  |  |     time_entry.activity = log_time_activity unless log_time_activity.nil? | 
					
						
							| 
									
										
										
										
											2011-05-15 23:01:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |     unless time_entry.save | 
					
						
							|  |  |  |       logger.warn("TimeEntry could not be created by changeset #{id}: #{time_entry.errors.full_messages}") if logger | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     time_entry | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-04-09 09:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 11:45:09 +00:00
										 |  |  |   def log_time_activity | 
					
						
							|  |  |  |     if Setting.commit_logtime_activity_id.to_i > 0
 | 
					
						
							|  |  |  |       TimeEntryActivity.find_by_id(Setting.commit_logtime_activity_id.to_i) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2010-01-31 16:25:06 +00:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2011-04-09 09:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 15:48:56 +00:00
										 |  |  |   def split_comments | 
					
						
							|  |  |  |     comments =~ /\A(.+?)\r?\n(.*)$/m | 
					
						
							|  |  |  |     @short_comments = $1 || comments | 
					
						
							|  |  |  |     @long_comments = $2.to_s.strip | 
					
						
							|  |  |  |     return @short_comments, @long_comments | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2008-11-10 18:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-28 12:09:32 +00:00
										 |  |  |   public | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Strips and reencodes a commit log before insertion into the database | 
					
						
							|  |  |  |   def self.normalize_comments(str, encoding) | 
					
						
							|  |  |  |     Changeset.to_utf8(str.to_s.strip, encoding) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def self.to_utf8(str, encoding) | 
					
						
							| 
									
										
										
										
											2011-04-09 05:41:12 +00:00
										 |  |  |     return str if str.nil? | 
					
						
							|  |  |  |     str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding) | 
					
						
							| 
									
										
										
										
											2011-04-09 06:34:33 +00:00
										 |  |  |     if str.empty? | 
					
						
							|  |  |  |       str.force_encoding("UTF-8") if str.respond_to?(:force_encoding) | 
					
						
							|  |  |  |       return str | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-04-09 09:31:14 +00:00
										 |  |  |     enc = encoding.blank? ? "UTF-8" : encoding | 
					
						
							| 
									
										
										
										
											2011-02-22 13:39:37 +00:00
										 |  |  |     if str.respond_to?(:force_encoding) | 
					
						
							| 
									
										
										
										
											2011-04-09 23:21:41 +00:00
										 |  |  |       if enc.upcase != "UTF-8" | 
					
						
							| 
									
										
										
										
											2011-04-09 05:41:12 +00:00
										 |  |  |         str.force_encoding(enc) | 
					
						
							| 
									
										
										
										
											2011-04-09 08:07:22 +00:00
										 |  |  |         str = str.encode("UTF-8", :invalid => :replace, | 
					
						
							|  |  |  |               :undef => :replace, :replace => '?') | 
					
						
							| 
									
										
										
										
											2011-04-09 08:19:55 +00:00
										 |  |  |       else | 
					
						
							|  |  |  |         str.force_encoding("UTF-8") | 
					
						
							|  |  |  |         if ! str.valid_encoding? | 
					
						
							|  |  |  |           str = str.encode("US-ASCII", :invalid => :replace, | 
					
						
							|  |  |  |                 :undef => :replace, :replace => '?').encode("UTF-8") | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2011-02-22 13:39:37 +00:00
										 |  |  |       end | 
					
						
							|  |  |  |     else | 
					
						
							| 
									
										
										
										
											2011-04-09 09:31:14 +00:00
										 |  |  |       ic = Iconv.new('UTF-8', enc) | 
					
						
							|  |  |  |       txtar = "" | 
					
						
							| 
									
										
										
										
											2011-02-22 13:39:37 +00:00
										 |  |  |       begin | 
					
						
							| 
									
										
										
										
											2011-04-09 09:31:14 +00:00
										 |  |  |         txtar += ic.iconv(str) | 
					
						
							|  |  |  |       rescue Iconv::IllegalSequence | 
					
						
							|  |  |  |         txtar += $!.success | 
					
						
							|  |  |  |         str = '?' + $!.failed[1,$!.failed.length] | 
					
						
							|  |  |  |         retry | 
					
						
							|  |  |  |       rescue | 
					
						
							|  |  |  |         txtar += $!.success | 
					
						
							| 
									
										
										
										
											2011-02-22 13:39:37 +00:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2011-04-09 09:31:14 +00:00
										 |  |  |       str = txtar | 
					
						
							| 
									
										
										
										
											2010-04-11 13:55:30 +00:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-02-22 13:39:37 +00:00
										 |  |  |     str | 
					
						
							| 
									
										
										
										
											2008-08-26 12:13:15 +00:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2007-03-25 12:12:15 +00:00
										 |  |  | end |