class FlakeySpecCatcher::GitController

GitController class

Runs a 'git diff' between the local working commit and a base commit that represents what is at the top of the source control manager.

The end goal of the GitController is to specify which tests have changed in a form that can be easily sent to RSpec. Because you can specify a test to run via `rspec <path_to_spec_file>:<file number>` the GitController will summarize changes in that form.

Attributes

base_commit_sha[R]
branch[R]
capsule_manager[R]
git_comparison[R]
remote[R]
working_commit_sha[R]

Public Class Methods

new(test_mode: false, capsule_manager: FlakeySpecCatcher::CapsuleManager.new, user_config: FlakeySpecCatcher::UserConfig.new) click to toggle source
# File lib/flakey_spec_catcher/git_controller.rb, line 22
def initialize(test_mode: false, capsule_manager: FlakeySpecCatcher::CapsuleManager.new,
  user_config: FlakeySpecCatcher::UserConfig.new)

  @user_config = user_config
  @remote = find_git_remote
  @branch = find_remote_branch
  @capsule_manager = capsule_manager
  # we don't need to do any git comparisons if we have manually specified tests to run.
  return unless @user_config.manual_rerun_patterns.nil? || @user_config.manual_rerun_patterns.empty?

  initialize_git_comparison(test_mode)
  parse_changes
  identify_change_contexts
end

Public Instance Methods

changed_examples() click to toggle source
# File lib/flakey_spec_catcher/git_controller.rb, line 37
def changed_examples
  @capsule_manager.change_capsules.map(&:changed_examples).flatten.uniq
end

Private Instance Methods

diff_files() click to toggle source
# File lib/flakey_spec_catcher/git_controller.rb, line 104
def diff_files
  `git diff --name-only #{@git_comparison}`.gsub("\n", ',').split(',')
end
find_git_remote() click to toggle source

Use 'origin' unless otherwise specified

# File lib/flakey_spec_catcher/git_controller.rb, line 44
def find_git_remote
  if @user_config.use_parent
    nil
  elsif ENV.fetch('FSC_GIT_REMOTE', '').empty?
    remotes = `git remote show`.split
    remotes.empty? ? nil : remotes[0]
  else
    ENV['FSC_GIT_REMOTE']
  end
end
find_remote_branch() click to toggle source
# File lib/flakey_spec_catcher/git_controller.rb, line 55
def find_remote_branch
  return nil if @remote.nil?

  working_branch = `git branch | grep '*'`.delete('*').gsub(/\s+/, '')
  branch_remote = `git config branch.#{working_branch}.remote`.strip
  return 'master' unless @remote == branch_remote

  remote_branch = `git config branch.#{branch}.merge`.strip.sub(%r{^refs/heads/}, '')
  remote_branch = nil if remote_branch.empty?
  remote_branch || 'master'
end
identify_change_contexts() click to toggle source

rubocop:enable Metrics/CyclomaticComplexity

# File lib/flakey_spec_catcher/git_controller.rb, line 100
def identify_change_contexts
  @capsule_manager.change_capsules.each(&:fill_contexts)
end
initialize_git_comparison(test_mode) click to toggle source
# File lib/flakey_spec_catcher/git_controller.rb, line 67
def initialize_git_comparison(test_mode)
  if !test_mode && !@remote.nil?
    @working_commit_sha = `git rev-parse @`.gsub(/\s+/, '')
    @base_commit_sha = `git rev-parse #{@remote}/#{@branch}`.gsub(/\s+/, '')
  else
    @working_commit_sha = `git rev-parse HEAD`.gsub(/\s+/, '')
    @base_commit_sha = `git rev-parse HEAD~1`.gsub(/\s+/, '')
  end
  @git_comparison = "#{@base_commit_sha}..#{@working_commit_sha}"
end
parse_changes() click to toggle source

rubocop:disable Metrics/CyclomaticComplexity

# File lib/flakey_spec_catcher/git_controller.rb, line 79
def parse_changes
  # For each file, get the change block
  diff_files.each do |filename|
    next unless filename =~ /_spec.rb/
    next unless File.file?(filename)

    # Get diff pairs [ /path/to/file,  "@@ -19 +19,4 @@" ]
    diff = `git diff --unified=0 #{@git_comparison} -- #{filename}`
    diff_pairs = diff.split("\n").select { |line| line =~ /^@@/ || line =~ /^diff --git/ }

    diff_pairs.each do |line|
      next unless (diff_summary = /-\d+,?(\d+)?\s\+\d+,?(\d+)?/.match(line))

      change_summary = ChangeSummary.new(diff_summary.to_s)
      capsule = ChangeCapsule.new(filename, change_summary)
      @capsule_manager.add_capsule(capsule)
    end
  end
end