aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/git
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/git')
-rw-r--r--pkg/git/git.go62
1 files changed, 62 insertions, 0 deletions
diff --git a/pkg/git/git.go b/pkg/git/git.go
index f7e93825f..59715ed07 100644
--- a/pkg/git/git.go
+++ b/pkg/git/git.go
@@ -30,6 +30,7 @@ const (
// This involves fetching/resetting/cloning as necessary to recover from all possible problems.
// Returns hash of the HEAD commit in the specified branch.
func Poll(dir, repo, branch string) (*Commit, error) {
+ runSandboxed(dir, "git", "bisect", "reset")
runSandboxed(dir, "git", "reset", "--hard")
origin, err := runSandboxed(dir, "git", "remote", "get-url", "origin")
if err != nil || strings.TrimSpace(string(origin)) != repo {
@@ -61,6 +62,7 @@ func Poll(dir, repo, branch string) (*Commit, error) {
// CheckoutBranch checkouts the specified repository/branch in dir.
func CheckoutBranch(dir, repo, branch string) (*Commit, error) {
+ runSandboxed(dir, "git", "bisect", "reset")
if _, err := runSandboxed(dir, "git", "reset", "--hard"); err != nil {
if err := initRepo(dir); err != nil {
return nil, err
@@ -78,6 +80,7 @@ func CheckoutBranch(dir, repo, branch string) (*Commit, error) {
// CheckoutCommit checkouts the specified repository on the specified commit in dir.
func CheckoutCommit(dir, repo, commit string) (*Commit, error) {
+ runSandboxed(dir, "git", "bisect", "reset")
if _, err := runSandboxed(dir, "git", "reset", "--hard"); err != nil {
if err := initRepo(dir); err != nil {
return nil, err
@@ -318,6 +321,65 @@ func Patch(dir string, patch []byte) error {
return nil
}
+type BisectResult int
+
+const (
+ BisectBad BisectResult = iota
+ BisectGood
+ BisectSkip
+)
+
+// Bisect bisects good..bad commit range against the provided predicate (wrapper around git bisect).
+// The predicate should return an error only if there is no way to proceed
+// (it will abort the process), if possible it should prefer to return BisectSkip.
+// Progress of the process is streamed to the provided trace.
+// Returns the first commit on which the predicate returns BisectBad.
+func Bisect(dir, bad, good string, trace io.Writer, pred func() (BisectResult, error)) (*Commit, error) {
+ runSandboxed(dir, "git", "bisect", "reset")
+ runSandboxed(dir, "git", "reset", "--hard")
+ firstBad, err := GetCommit(dir, bad)
+ if err != nil {
+ return nil, err
+ }
+ output, err := runSandboxed(dir, "git", "bisect", "start", bad, good)
+ if err != nil {
+ return nil, err
+ }
+ defer runSandboxed(dir, "git", "bisect", "reset")
+ fmt.Fprintf(trace, "# git bisect start %v %v\n%s", bad, good, output)
+ current, err := HeadCommit(dir)
+ if err != nil {
+ return nil, err
+ }
+ var bisectTerms = [...]string{
+ BisectBad: "bad",
+ BisectGood: "good",
+ BisectSkip: "skip",
+ }
+ for {
+ res, err := pred()
+ if err != nil {
+ return nil, err
+ }
+ if res == BisectBad {
+ firstBad = current
+ }
+ output, err = runSandboxed(dir, "git", "bisect", bisectTerms[res])
+ if err != nil {
+ return nil, err
+ }
+ fmt.Fprintf(trace, "# git bisect %v %v\n%s", bisectTerms[res], current.Hash, output)
+ next, err := HeadCommit(dir)
+ if err != nil {
+ return nil, err
+ }
+ if current.Hash == next.Hash {
+ return firstBad, nil
+ }
+ current = next
+ }
+}
+
// PreviousReleaseTags returns list of preceding release tags that are reachable from the given commit.
// Note: linux-specific.
func PreviousReleaseTags(dir, commit string) ([]string, error) {