class GitCommitMailer::CommitInfo

Attributes

added_files[R]
author_email[R]
author_name[R]
copied_files[R]
date[R]
deleted_files[R]
diffs[R]
mailer[R]
merge_commits[R]
merge_messages[RW]
reference[RW]
renamed_files[R]
revision[R]
subject[R]
summary[R]
type_changed_files[R]
updated_files[R]

Public Class Methods

new(mailer, reference, revision) click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 49
def initialize(mailer, reference, revision)
  @mailer = mailer
  @reference = reference
  @revision = revision

  @files = []
  @added_files = []
  @copied_files = []
  @deleted_files = []
  @updated_files = []
  @renamed_files = []
  @type_changed_files = []

  set_records
  parse_file_status
  parse_diff

  @merge_messages = []
  @merge_commits = []
end
unescape_file_path(file_path) click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 21
def unescape_file_path(file_path)
  if file_path =~ /\A"(.*)"\z/
    escaped_file_path = $1
    if escaped_file_path.respond_to?(:encoding)
      encoding = escaped_file_path.encoding
    else
      encoding = nil
    end
    unescaped_file_path = escaped_file_path.gsub(/\\\\/, '\\').
                                            gsub(/\\\"/, '"').
                                            gsub(/\\([0-9]{1,3})/) do
      $1.to_i(8).chr
    end
    unescaped_file_path.force_encoding(encoding) if encoding
    unescaped_file_path
  else
    file_path
  end
end

Public Instance Methods

file_index(name) click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 140
def file_index(name)
  @files.index(name)
end
first_parent() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 70
def first_parent
  return nil if @parent_revisions.length.zero?

  @parent_revisions[0]
end
format_mail_body_html() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 132
def format_mail_body_html
  HTMLMailBodyFormatter.new(self).format
end
format_mail_body_text() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 128
def format_mail_body_text
  TextMailBodyFormatter.new(self).format
end
format_mail_subject() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 116
def format_mail_subject
  affected_path_info = ""
  if @mailer.show_path?
    _affected_paths = affected_paths
    unless _affected_paths.empty?
      affected_path_info = " (#{_affected_paths.join(',')})"
    end
  end

  "[#{short_reference}#{affected_path_info}] " + subject
end
headers() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 94
def headers
  [
    "X-Git-Author: #{@author_name}",
    "X-Git-Revision: #{@revision}",
    # "X-Git-Repository: #{path}",
    "X-Git-Repository: XXX",
    "X-Git-Commit-Id: #{@revision}",
    "Message-ID: #{message_id}",
    *related_mail_headers
  ]
end
merge?() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 82
def merge?
  @parent_revisions.length >= 2
end
message_id() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 86
def message_id
  if merge?
    "<merge.#{@parent_revisions.first}.#{@revision}@#{self.class.host_name}>"
  else
    "<#{@revision}@#{self.class.host_name}>"
  end
end
other_parents() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 76
def other_parents
  return [] if @parent_revisions.length.zero?

  @parent_revisions[1..-1]
end
rss_content() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 148
def rss_content
  "<pre>#{ERB::Util.h(format_mail_body_text)}</pre>"
end
rss_title() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 144
def rss_title
  format_mail_subject
end
short_revision() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 136
def short_revision
  GitCommitMailer.short_revision(@revision)
end

Private Instance Methods

affected_paths() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 165
def affected_paths
  paths = []
  sub_paths = sub_paths('')
  paths.concat(sub_paths)
  paths.uniq
end
create_file_diff(lines) click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 218
def create_file_diff(lines)
  diff = FileDiff.new(@mailer, lines, @revision)
  diff.index = @files.index(diff.file_path)
  diff
end
force_utf8(string) click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 269
def force_utf8(string)
  string.force_encoding("UTF-8")
  return string if string.valid_encoding?

  guess_encodings = [
    "Windows-31J",
    "EUC-JP",
  ]
  guess_encodings.each do |guess_encoding|
    string.force_encoding(guess_encoding)
    next unless string.valid_encoding?
    begin
      return string.encode("UTF-8")
    rescue EncodingError
    end
  end

  nil
end
parse_diff() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 183
def parse_diff
  @diffs = []
  output = []
  n_bytes = 0
  git("log -n 1 --pretty=format:'' -C --cc -p #{@revision}") do |io|
    io.each_line do |line|
      n_bytes += line.bytesize
      break if n_bytes > mailer.max_diff_size
      utf8_line = force_utf8(line) || "(binary line)\n"
      output << utf8_line
    end
  end
  return if output.empty?

  output.shift if output.first.strip.empty?

  lines = []

  line = output.shift
  lines << line.chomp if line # take out the very first 'diff --git' header
  while line = output.shift
    line.chomp!
    case line
    when /\Adiff --git/
      @diffs << create_file_diff(lines)
      lines = [line]
    else
      lines << line
    end
  end

  # create the last diff terminated by the EOF
  @diffs << create_file_diff(lines) if lines.length > 0
end
parse_file_status() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 224
def parse_file_status
  git("log -n 1 --pretty=format:'' -C --name-status #{@revision}").
  lines.each do |line|
    line.rstrip!
    next if line.empty?
    case line
    when /\A([^\t]*?)\t([^\t]*?)\z/
      status = $1
      file = CommitInfo.unescape_file_path($2)

      case status
      when /^A/ # Added
        @added_files << file
      when /^M/ # Modified
        @updated_files << file
      when /^D/ # Deleted
        @deleted_files << file
      when /^T/ # File Type Changed
        @type_changed_files << file
      else
        raise "unsupported status type: #{line.inspect}"
      end

      @files << file
    when /\A([^\t]*?)\t([^\t]*?)\t([^\t]*?)\z/
      status = $1
      from_file = CommitInfo.unescape_file_path($2)
      to_file = CommitInfo.unescape_file_path($3)

      case status
      when /^R/ # Renamed
        @renamed_files << [from_file, to_file]
      when /^C/ # Copied
        @copied_files << [from_file, to_file]
      else
        raise "unsupported status type: #{line.inspect}"
      end

      @files << to_file
    else
      raise "unsupported status type: #{line.inspect}"
    end
  end
end
set_records() click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 172
def set_records
  author_name, author_email, date, subject, parent_revisions =
    get_records(["%an", "%ae", "%at", "%s", "%P"])
  @author_name = author_name
  @author_email = author_email
  @date = Time.at(date.to_i)
  @subject = subject
  @parent_revisions = parent_revisions.split
  @summary = git("log -n 1 --pretty=format:%B #{@revision}").rstrip
end
sub_paths(prefix) click to toggle source
# File lib/git-commit-mailer/commit-info.rb, line 153
def sub_paths(prefix)
  prefixes = prefix.split(/\/+/)
  results = []
  @diffs.each do |diff|
    paths = diff.file_path.split(/\/+/)
    if prefixes.size < paths.size and prefixes == paths[0, prefixes.size]
      results << paths[prefixes.size]
    end
  end
  results
end