Created
March 18, 2010 08:26
-
-
Save kolo/336157 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From fad23f414a762d74bdcd77290ef206110327bb46 Mon Sep 17 00:00:00 2001 | |
From: Dmitry Maksimov <[email protected]> | |
Date: Tue, 16 Mar 2010 08:47:04 +0300 | |
Subject: [PATCH] Basic implementation of git-bisect | |
--- | |
lib/grit.rb | 1 + | |
lib/grit/bisect.rb | 37 +++++++++++++++++++++++++++++++++ | |
lib/grit/git.rb | 4 +++ | |
lib/grit/repo.rb | 20 ++++++++++++++++++ | |
test/test_bisect.rb | 31 +++++++++++++++++++++++++++ | |
test/test_bisect_object.rb | 49 ++++++++++++++++++++++++++++++++++++++++++++ | |
test/test_git.rb | 5 ++++ | |
7 files changed, 147 insertions(+), 0 deletions(-) | |
create mode 100644 lib/grit/bisect.rb | |
create mode 100644 test/test_bisect.rb | |
create mode 100644 test/test_bisect_object.rb | |
diff --git a/lib/grit.rb b/lib/grit.rb | |
index d6f6148..426a2d9 100644 | |
--- a/lib/grit.rb | |
+++ b/lib/grit.rb | |
@@ -50,6 +50,7 @@ require 'grit/status' | |
require 'grit/submodule' | |
require 'grit/blame' | |
require 'grit/merge' | |
+require 'grit/bisect' | |
module Grit | |
diff --git a/lib/grit/bisect.rb b/lib/grit/bisect.rb | |
new file mode 100644 | |
index 0000000..092150e | |
--- /dev/null | |
+++ b/lib/grit/bisect.rb | |
@@ -0,0 +1,37 @@ | |
+module Grit | |
+ | |
+ class BisectObject | |
+ def initialize(git) | |
+ @git = git | |
+ end | |
+ | |
+ def good(ref = nil) | |
+ response = @git.bisect(:good, ref) | |
+ parse_response(response) | |
+ end | |
+ | |
+ def bad(ref = nil) | |
+ response = @git.bisect(:bad, ref) | |
+ parse_response(response) | |
+ end | |
+ | |
+ def start | |
+ @git.bisect(:start) | |
+ end | |
+ | |
+ def reset | |
+ @git.bisect(:reset) | |
+ end | |
+ | |
+ private | |
+ def parse_response(response) | |
+ first_line = response.first | |
+ return nil if first_line.match(/^Bisecting:/) | |
+ return first_line.split.first if first_line.match(/is\sthe\sfirst\sbad\scommit$/) # broken commit sha | |
+ | |
+ raise Exception, "Grit::BisectObject#parse_response is outdated" | |
+ end | |
+ | |
+ end # BisectObject | |
+ | |
+end # Grit | |
diff --git a/lib/grit/git.rb b/lib/grit/git.rb | |
index 1831fe2..5d83a46 100644 | |
--- a/lib/grit/git.rb | |
+++ b/lib/grit/git.rb | |
@@ -183,6 +183,10 @@ module Grit | |
false | |
end | |
+ def bisect(subcommand, *args) | |
+ run("", "bisect #{subcommand.to_s}", "", {}, args.compact) | |
+ end | |
+ | |
# RAW CALLS WITH ENV SETTINGS | |
def raw_git_call(command, index) | |
tmp = ENV['GIT_INDEX_FILE'] | |
diff --git a/lib/grit/repo.rb b/lib/grit/repo.rb | |
index 9eb3354..8a72a89 100644 | |
--- a/lib/grit/repo.rb | |
+++ b/lib/grit/repo.rb | |
@@ -477,6 +477,26 @@ module Grit | |
def inspect | |
%Q{#<Grit::Repo "#{@path}">} | |
end | |
+ | |
+ # Find a broken commit using git bisect | |
+ # +good_commit_ref+ is the reference to the last good commit | |
+ # +bad_commit_ref+ is the reference to the bad commit, by default points to HEAD | |
+ # | |
+ # Returns nothing | |
+ def bisect(good_commit_ref, bad_commit_ref = nil, &block) | |
+ if block | |
+ bisect_obj = BisectObject.new(self.git) | |
+ bisect_obj.start | |
+ bisect_obj.bad(bad_commit_ref) | |
+ bisect_obj.good(good_commit_ref) | |
+ | |
+ yield bisect_obj | |
+ | |
+ bisect_obj.reset | |
+ else | |
+ raise ArgumentError, "A code block should be passed to Repo#bisect" | |
+ end | |
+ end | |
end # Repo | |
end # Grit | |
diff --git a/test/test_bisect.rb b/test/test_bisect.rb | |
new file mode 100644 | |
index 0000000..68d1948 | |
--- /dev/null | |
+++ b/test/test_bisect.rb | |
@@ -0,0 +1,31 @@ | |
+require File.dirname(__FILE__) + '/helper' | |
+ | |
+class TestBisect < Test::Unit::TestCase | |
+ | |
+ def setup | |
+ @r = Repo.new(File.join(File.dirname(__FILE__), %w[dot_git]), :is_bare => true) | |
+ | |
+ @good_commit = "d6016bc9fa3950ad18e3028f9d2d26f831061a62" | |
+ @bad_commit = "ca8a30f5a7f0f163bbe3b6f0abf18a6c83b0687a" | |
+ end | |
+ | |
+ def test_bisect_with_empty_block | |
+ assert_raise ArgumentError do | |
+ @r.bisect(@good_commit) | |
+ end | |
+ end | |
+ | |
+ def test_bisect_calls | |
+ bisect_obj = mock("BisectObject instance") | |
+ bisect_obj.expects(:start) | |
+ bisect_obj.expects(:bad).with(@bad_commit) | |
+ bisect_obj.expects(:good).with(@good_commit) | |
+ bisect_obj.expects(:reset) | |
+ | |
+ BisectObject.expects(:new).returns(bisect_obj) | |
+ | |
+ @r.bisect(@good_commit, @bad_commit) do |b| | |
+ end | |
+ end | |
+ | |
+end | |
diff --git a/test/test_bisect_object.rb b/test/test_bisect_object.rb | |
new file mode 100644 | |
index 0000000..abc02e3 | |
--- /dev/null | |
+++ b/test/test_bisect_object.rb | |
@@ -0,0 +1,49 @@ | |
+require File.dirname(__FILE__) + '/helper' | |
+ | |
+class TestBisectObject < Test::Unit::TestCase | |
+ | |
+ def setup | |
+ @git_mock = mock("git") | |
+ @bisect_obj = BisectObject.new(@git_mock) | |
+ end | |
+ | |
+ def test_start | |
+ @git_mock.expects(:bisect).with(:start) | |
+ @bisect_obj.start | |
+ end | |
+ | |
+ def test_reset | |
+ @git_mock.expects(:bisect).with(:reset) | |
+ @bisect_obj.reset | |
+ end | |
+ | |
+ def test_bad | |
+ @git_mock.expects(:bisect).with(:bad, nil).returns("Bisecting: ...") | |
+ @bisect_obj.bad | |
+ end | |
+ | |
+ def test_good | |
+ @git_mock.expects(:bisect).with(:good, nil).returns("Bisecting: ...") | |
+ @bisect_obj.good | |
+ end | |
+ | |
+ def test_parse_response_returns_nil | |
+ @git_mock.stubs(:bisect).with(:bad, nil).returns("Bisecting: ...") | |
+ assert_equal nil, @bisect_obj.bad | |
+ end | |
+ | |
+ def test_parse_response_returns_commit_sha | |
+ sha = "d6016bc9fa3950ad18e3028f9d2d26f831061a62" | |
+ | |
+ @git_mock.stubs(:bisect).with(:good, nil).returns("#{sha} is the first bad commit\n") | |
+ assert sha, @bisect_obj.good | |
+ end | |
+ | |
+ def test_parse_response_raises_error | |
+ @git_mock.stubs(:bisect).with(:bad, nil).returns("Someting changed in git bisect messages\n") | |
+ assert_raise Exception do | |
+ @bisect_obj.bad | |
+ end | |
+ end | |
+ | |
+end | |
diff --git a/test/test_git.rb b/test/test_git.rb | |
index 1d9d9e0..1a95363 100644 | |
--- a/test/test_git.rb | |
+++ b/test/test_git.rb | |
@@ -101,4 +101,9 @@ class TestGit < Test::Unit::TestCase | |
FileUtils.expects(:rm_rf).with(File.join(@git.git_dir, 'foo')) | |
@git.fs_delete('foo') | |
end | |
+ | |
+ def test_bisect | |
+ @git.expects(:run).with("", "bisect start", "", {}, []) | |
+ @git.bisect(:start) | |
+ end | |
end | |
-- | |
1.6.3.3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment