class DerailedBenchmarks::Git::SwitchProject

Wraps two or more git commits in a specific location

Returns an array of GitCommit objects that can be used to manipulate and checkout the repo

Example:

`git clone https://sharpstone/default_ruby tmp/default_ruby`

project = GitSwitchProject.new(path: "tmp/default_ruby")

By default it will represent the last two commits:

project.commits.length # => 2

You can pass in explicit REFs in an array:

ref_array = ["da748a59340be8b950e7bbbfb32077eb67d70c3c", "9b19275a592f148e2a53b87ead4ccd8c747539c9"]
project = GitSwitchProject.new(path: "tmp/default_ruby", ref_array: ref_array)

puts project.commits.map(&:ref) == ref_array # => true

It knows the current branch or sha:

`cd tmp/ruby && git checkout -b mybranch`
project.current_branch_or_sha #=> "mybranch"

It can be used for safely wrapping checkouts to ensure the project returns to it’s original branch:

project.restore_branch_on_return do
  project.commits.first.checkout!
  project.current_branch_or_sha # => "da748a593"
end

project.current_branch_or_sha # => "mybranch"

Attributes

commits[R]

Public Class Methods

new(path: , ref_array: [], io: STDOUT, log_dir: "/dev/null") click to toggle source
# File lib/derailed_benchmarks/git/switch_project.rb, line 48
def initialize(path: , ref_array: [], io: STDOUT, log_dir: "/dev/null")
  @path = Pathname.new(path)

  @in_git_path = Git::InPath.new(@path.expand_path)

  raise "Must be a path with a .git directory '#{@path}'" if !@path.join(".git").exist?
  @io = io
  @commits = []
  log_dir = Pathname(log_dir)

  expand_refs(ref_array).each do |ref|
    restore_branch_on_return(quiet: true) do
      @commits << Git::Commit.new(path: @path, ref: ref, log_dir: log_dir)
    end
  end

  if (duplicate = @commits.group_by(&:short_sha).detect {|(k, v)| v.length > 1})
    raise "Duplicate SHA resolved #{duplicate[0].inspect}: #{duplicate[1].map {|c| "'#{c.ref}' => '#{c.short_sha}'"}.join(", ") } at #{@path}"
  end
end

Public Instance Methods

clean?() click to toggle source

stackoverflow.com/a/3879077/147390

# File lib/derailed_benchmarks/git/switch_project.rb, line 80
def clean?
  @in_git_path.run("git diff-index --quiet HEAD --") && $?.success?
end
current_branch_or_sha() click to toggle source
# File lib/derailed_benchmarks/git/switch_project.rb, line 69
def current_branch_or_sha
  branch_or_sha = @in_git_path.branch
  branch_or_sha ||= @in_git_path.short_sha
  branch_or_sha
end
dirty?() click to toggle source
# File lib/derailed_benchmarks/git/switch_project.rb, line 75
def dirty?
  !clean?
end
restore_branch_on_return(quiet: false) { || ... } click to toggle source
# File lib/derailed_benchmarks/git/switch_project.rb, line 88
def restore_branch_on_return(quiet: false)
  if dirty? && status.include?("gemspec")
    dirty_gemspec = true
    unless quiet
      @io.puts "Working tree at #{@path} is dirty, stashing. This will be popped on return"
      @io.puts "Bundler modifies gemspec files on git install, this is normal"
      @io.puts "Original status:\n#{status}"
    end
    @in_git_path.run!("git stash")
  end
  branch_or_sha = self.current_branch_or_sha
  yield
ensure
  return unless branch_or_sha
  @io.puts "Resetting git dir of '#{@path.to_s}' to #{branch_or_sha.inspect}" unless quiet

  @in_git_path.checkout!(branch_or_sha)
  if dirty_gemspec
    out = @in_git_path.run!("git stash apply 2>&1")
    @io.puts "Applying stash of '#{@path.to_s}':\n#{out}" unless quiet
  end
end

Private Instance Methods

expand_refs(ref_array) click to toggle source

case ref_array.length when >= 2

returns original array

when 1

returns the given ref plus the one before it

when 0

returns the most recent 2 refs
# File lib/derailed_benchmarks/git/switch_project.rb, line 118
        def expand_refs(ref_array)
  return ref_array if ref_array.length >= 2

  @in_git_path.checkout!(ref_array.first) if ref_array.first

  branches_string = @in_git_path.run!("git log --format='%H' -n 2")
  ref_array = branches_string.split($/)
  return ref_array
end
status(pattern: "*.gemspec") click to toggle source
# File lib/derailed_benchmarks/git/switch_project.rb, line 84
        def status(pattern: "*.gemspec")
  @in_git_path.run("git status #{pattern}")
end