class Coveralls::Gcov::Runner

Attributes

exclude_pattern[RW]
excludes[RW]
extensions[RW]
no_gcov[RW]
parallel[RW]
repo_token[RW]
root_dir[RW]
service_event_type[RW]
service_job_id[RW]
service_job_number[RW]
service_name[RW]
service_number[RW]
service_pull_request[RW]

Public Class Methods

new() click to toggle source
# File lib/coveralls/gcov/runner.rb, line 25
def initialize()
  if ENV['TRAVIS']
    @service_name = 'travis-ci'
    @service_job_id = ENV['TRAVIS_JOB_ID']
  elsif ENV['CIRCLECI']
    @service_name = 'circleci'
    @service_number = ENV['CIRCLE_BUILD_NUM']
    @service_pull_request = (ENV['CI_PULL_REQUEST'] || "")[/(\d+)$/, 1]
    @parallel = ENV['CIRCLE_NODE_TOTAL'].to_i > 1
    @service_job_number = ENV['CIRCLE_NODE_INDEX']
  end

  @extensions = []
  @excludes = []
end

Public Instance Methods

exclude_pattern=(exclude_pattern) click to toggle source
# File lib/coveralls/gcov/runner.rb, line 41
def exclude_pattern=(exclude_pattern)
  if !exclude_pattern.kind_of?(Regexp)
    exclude_pattern = Regexp.new(exclude_pattern)
  end
  @exclude_pattern = exclude_pattern
end
run() click to toggle source
# File lib/coveralls/gcov/runner.rb, line 48
def run()
  root_dir = @root_dir || Dir.pwd
  report = parse(root_dir)
  file = write_report(report)
  upload(file)
end

Private Instance Methods

is_excluded_path(filepath) click to toggle source
# File lib/coveralls/gcov/runner.rb, line 129
def is_excluded_path(filepath)
  if filepath.start_with?('..')
    return true
  end
  @excludes.each do |exclude|
    if filepath.start_with?(exclude)
      return true
    end
  end
  if !@exclude_pattern.nil? && filepath.match(@exclude_pattern)
    return true
  end
  if !@extensions.empty?
    @extensions.each do |extension|
      if File.extname(filepath) == extension
        return false
      end
    end
    return true
  else
    return false
  end
end
parse(base_dir) click to toggle source
# File lib/coveralls/gcov/runner.rb, line 57
def parse(base_dir)
  report = {}
  report['repo_token'] = repo_token if repo_token
  report['service_name'] = service_name if service_name
  report['service_job_id'] = service_job_id if service_job_id
  report['service_number'] = service_number if service_number
  report['service_pull_request'] = service_pull_request if service_pull_request
  report['parallel'] = parallel if parallel
  report['service_job_number'] = service_job_number if service_job_number
  report['service_event_type'] = service_event_type if service_event_type
  report['source_files'] = []

  Dir.glob("#{base_dir}/**/*.gcov").each do |file|
    File.open(file, "r") do |handle|
      source_file = {}
      name = ''
      source_digest = nil
      coverage = []

      handle.each_line do |line|
        match = /^[ ]*([0-9]+|-|#####):[ ]*([0-9]+):(.*)/.match(line)
        next unless match.to_a.count == 4
        count, number, text = match.to_a[1..3]

        if number.to_i == 0
          key, val = /([^:]+):(.*)$/.match(text).to_a[1..2]
          if key == 'Source'
            name = Pathname(val).relative_path_from(Pathname(base_dir)).to_s
            if File.exist?(val)
              source_digest = Digest::MD5.file(val).to_s
            end
          end
        else
          coverage[number.to_i - 1] = case count.strip
            when "-"
              nil
            when "#####"
              if text.strip == '}'
                nil
              else
                0
              end
            else count.to_i
            end
        end
      end

      if !is_excluded_path(name) && !source_digest.nil?
        source_file['name'] = name
        source_file['source_digest'] = source_digest
        source_file['coverage'] = coverage

        report['source_files'] << source_file
      end
    end
  end

  remotes = %x[git remote -v].rstrip.split(/\r?\n/).map {|line| line.chomp }.select { |line| line.include? 'fetch'}.first.split(' ')
  report['git'] = {
    'head' => {
      'id' => %x[git --no-pager log -1 --pretty=format:%H],
      'author_name' => %x[git --no-pager log -1 --pretty=format:%aN],
      'author_email' => %x[git --no-pager log -1 --pretty=format:%ae],
      'committer_name' => %x[git --no-pager log -1 --pretty=format:%cN],
      'committer_email' => %x[git --no-pager log -1 --pretty=format:%ce],
      'message' => %x[git --no-pager log -1 --pretty=format:%s] },
    'branch' => %x[git rev-parse --abbrev-ref HEAD].strip,
    'remotes' => {'name' => remotes[0], 'remote' => remotes[1]} }

  report
end
upload(json_file) click to toggle source
# File lib/coveralls/gcov/runner.rb, line 162
def upload(json_file)
  curl_options = ['curl', '-sSf', '-F', "json_file=@#{json_file}", 'https://coveralls.io/api/v1/jobs']
  puts curl_options.join(' ')
  Open3.popen2e(*curl_options) do |stdin, stdout_err, wait_thr|
    output = ''
    while line = stdout_err.gets
      puts line
      output << line
    end

    status = wait_thr.value
    if !status.success?
      raise "Upload failed (exited with status: #{status.exitstatus})"
    end
  end
end
write_report(report) click to toggle source
# File lib/coveralls/gcov/runner.rb, line 153
def write_report(report)
  tempdir = Pathname.new(Dir.tmpdir).join(SecureRandom.hex)
  FileUtils.mkdir_p(tempdir)
  tempfile = File::open(tempdir.join('coveralls.json'), "w")
  tempfile.puts(report.to_json)
  tempfile.flush
  tempfile.path
end