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