class Xlint

Constants

VERSION

Attributes

comments[RW]
diff_file[RW]
draft[RW]

Public Class Methods

build_draft() click to toggle source
# File lib/xlint.rb, line 30
def build_draft
  @comments = []
  # GitDiffParser::Patches.parse(cp932 text) raises ArgumentError: invalid byte sequence in UTF-8
  # https://github.com/packsaddle/ruby-git_diff_parser/issues/91
  diff_data = File.read(diff_file)
  diff_data.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
  diff = Xlint.parse_git(diff_data)
  diff.files.each do |file|
    patch = diff.find_patch_by_file(file)
    changes = Xlint.patch_body_changes(patch.body, file)
    @comments.concat(Xlint.find_offenses(changes))
  end
end
build_label() click to toggle source
# File lib/xlint.rb, line 51
def build_label
  return unless ENV['GERGICH_REVIEW_LABEL']
  score = comments.empty? ? 1 : -1
  message = comments.empty? ? 'Xlint didn\'t find anything to complain about' : 'Xlint is worried about your commit'
  draft.add_message(message)
  draft.add_label(ENV['GERGICH_REVIEW_LABEL'], score)
end
check_args() click to toggle source
# File lib/xlint.rb, line 18
def check_args
  # reads git diff from file, file name in ARGV[0]
  raise ArgumentError, 'usage: xlint path/to/some.diff' unless ARGV.size == 1
  @diff_file = ARGV.first
  raise "File does not exist: #{diff_file}" unless File.exist?(diff_file)
end
check_deployment_target(change) click to toggle source
# File lib/xlint.rb, line 109
def check_deployment_target(change)
  offenses = []
  if change[:file] =~ /(.pbxproj)/ && change[:line] =~ /(DEPLOYMENT_TARGET =)/
    offense = {
      path: change[:file],
      position: change[:line_number],
      message: 'Deployment target changes should be approved by the team lead.',
      severity: 'error'
    }
    offenses.push(offense)
  end
  offenses
end
check_env() click to toggle source
# File lib/xlint.rb, line 25
def check_env
  raise 'ENV[GERGICH_KEY] not defined' unless ENV['GERGICH_KEY']
  raise 'ENV[GERRIT_PROJECT] not defined' unless ENV['GERRIT_PROJECT']
end
clear() click to toggle source
# File lib/xlint.rb, line 12
def clear
  @diff_file = nil
  @draft.reset! if draft
  @comments = []
end
find_offenses(changes) click to toggle source

only checks for deployment target changes, we can add more rules in the future here

# File lib/xlint.rb, line 100
def find_offenses(changes)
  offenses = []
  changes.each do |change|
    warnings = check_deployment_target(change)
    offenses.concat(warnings) unless warnings.empty?
  end
  offenses
end
parse_git(diff) click to toggle source
# File lib/xlint.rb, line 72
def parse_git(diff)
  GitDiffParser::Patches.parse(diff)
end
patch_body_changes(body, file) click to toggle source
# File lib/xlint.rb, line 76
def patch_body_changes(body, file)
  result = []
  line_number = 0
  body.split("\n").each do |line|
    if valid_git_header?(line)
      line_number = starting_line_number(line)
      next
    end
    next if line.start_with?('-')
    result.push(file: file, line: line, line_number: line_number) if line.start_with?('+')
    line_number += 1
  end
  result
end
publish() click to toggle source
# File lib/xlint.rb, line 63
def publish
  check_args
  check_env
  build_draft
  save_draft
  build_label
  publish_draft
end
publish_draft() click to toggle source
# File lib/xlint.rb, line 59
def publish_draft
  Gergich::Review.new.publish!
end
save_draft() click to toggle source
# File lib/xlint.rb, line 44
def save_draft
  @draft = Gergich::Draft.new
  comments.each do |comment|
    draft.add_comment(comment[:path], comment[:position], comment[:message], comment[:severity])
  end
end
starting_line_number(header) click to toggle source

expects git header in the form of: @@ -215,13 +215,7 @@

# File lib/xlint.rb, line 92
def starting_line_number(header)
  str = header.split(' ')[2].split(',')[0]
  str.slice!('-')
  str.to_i
end
valid_git_header?(line) click to toggle source
# File lib/xlint.rb, line 123
def valid_git_header?(line)
  line =~ /^(@{2})\s([-]{1}[0-9]*(,[0-9]*)?)\s([+][0-9]*(,[0-9]*)?)\s(@{2})$/
end