Class: DerailedBenchmarks::Git::SwitchProject

Inherits:
Object
  • Object
show all
Defined in:
lib/derailed_benchmarks/git/switch_project.rb

Overview

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"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path:, ref_array: [], io: STDOUT, log_dir: "/dev/null") ⇒ SwitchProject

Returns a new instance of SwitchProject.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 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

Instance Attribute Details

#commitsObject (readonly)

Returns the value of attribute commits.



46
47
48
# File 'lib/derailed_benchmarks/git/switch_project.rb', line 46

def commits
  @commits
end

Instance Method Details

#clean?Boolean

Returns:

  • (Boolean)


80
81
82
# 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_shaObject



69
70
71
72
73
# 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?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/derailed_benchmarks/git/switch_project.rb', line 75

def dirty?
  !clean?
end

#restore_branch_on_return(quiet: false) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# 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