Repository: libgit2/git2go
Pull request #639 (2020-08-18 13:36:12)

Revert "More diff functionality (#629) (#636)"
This reverts commit 4d690277874bce93e81a1f1a12c9ec9ba3daca0f.

v0.27 does not support this API.


Patch:
diff --git a/diff.go b/diff.go
index cd8793b..7f824fa 100644
--- a/diff.go
+++ b/diff.go
@@ -3,7 +3,6 @@ package git
 /*
 #include <git2.h>
 
-extern void _go_git_populate_apply_cb(git_apply_options *options);
 extern int _go_git_diff_foreach(git_diff *diff, int eachFile, int eachHunk, int eachLine, void *payload);
 extern void _go_git_setup_diff_notify_callbacks(git_diff_options* opts);
 extern int _go_git_diff_blobs(git_blob *old, const char *old_path, git_blob *new, const char *new_path, git_diff_options *opts, int eachFile, int eachHunk, int eachLine, void *payload);
@@ -551,7 +550,7 @@ const (
 	DiffFindRemoveUnmodified            DiffFindOptionsFlag = C.GIT_DIFF_FIND_REMOVE_UNMODIFIED
 )
 
-// TODO implement git_diff_similarity_metric
+//TODO implement git_diff_similarity_metric
 type DiffFindOptions struct {
 	Flags                      DiffFindOptionsFlag
 	RenameThreshold            uint16
@@ -848,174 +847,3 @@ func DiffBlobs(oldBlob *Blob, oldAsPath string, newBlob *Blob, newAsPath string,
 
 	return nil
 }
-
-// ApplyHunkCallback is a callback that will be made per delta (file) when applying a patch.
-type ApplyHunkCallback func(*DiffHunk) (apply bool, err error)
-
-// ApplyDeltaCallback is a callback that will be made per hunk when applying a patch.
-type ApplyDeltaCallback func(*DiffDelta) (apply bool, err error)
-
-// ApplyOptions has 2 callbacks that are called for hunks or deltas
-// If these functions return an error, abort the apply process immediately.
-// If the first return value is true, the delta/hunk will be applied. If it is false, the  delta/hunk will not be applied. In either case, the rest of the apply process will continue.
-type ApplyOptions struct {
-	ApplyHunkCallback  ApplyHunkCallback
-	ApplyDeltaCallback ApplyDeltaCallback
-	Flags              uint
-}
-
-//export hunkApplyCallback
-func hunkApplyCallback(_hunk *C.git_diff_hunk, _payload unsafe.Pointer) C.int {
-	opts, ok := pointerHandles.Get(_payload).(*ApplyOptions)
-	if !ok {
-		panic("invalid apply options payload")
-	}
-
-	if opts.ApplyHunkCallback == nil {
-		return 0
-	}
-
-	hunk := diffHunkFromC(_hunk)
-
-	apply, err := opts.ApplyHunkCallback(&hunk)
-	if err != nil {
-		if gitError, ok := err.(*GitError); ok {
-			return C.int(gitError.Code)
-		}
-		return -1
-	} else if apply {
-		return 0
-	} else {
-		return 1
-	}
-}
-
-//export deltaApplyCallback
-func deltaApplyCallback(_delta *C.git_diff_delta, _payload unsafe.Pointer) C.int {
-	opts, ok := pointerHandles.Get(_payload).(*ApplyOptions)
-	if !ok {
-		panic("invalid apply options payload")
-	}
-
-	if opts.ApplyDeltaCallback == nil {
-		return 0
-	}
-
-	delta := diffDeltaFromC(_delta)
-
-	apply, err := opts.ApplyDeltaCallback(&delta)
-	if err != nil {
-		if gitError, ok := err.(*GitError); ok {
-			return C.int(gitError.Code)
-		}
-		return -1
-	} else if apply {
-		return 0
-	} else {
-		return 1
-	}
-}
-
-// DefaultApplyOptions returns default options for applying diffs or patches.
-func DefaultApplyOptions() (*ApplyOptions, error) {
-	opts := C.git_apply_options{}
-
-	runtime.LockOSThread()
-	defer runtime.UnlockOSThread()
-
-	ecode := C.git_apply_options_init(&opts, C.GIT_APPLY_OPTIONS_VERSION)
-	if int(ecode) != 0 {
-
-		return nil, MakeGitError(ecode)
-	}
-
-	return applyOptionsFromC(&opts), nil
-}
-
-func (a *ApplyOptions) toC() *C.git_apply_options {
-	if a == nil {
-		return nil
-	}
-
-	opts := &C.git_apply_options{
-		version: C.GIT_APPLY_OPTIONS_VERSION,
-		flags:   C.uint(a.Flags),
-	}
-
-	if a.ApplyDeltaCallback != nil || a.ApplyHunkCallback != nil {
-		C._go_git_populate_apply_cb(opts)
-		opts.payload = pointerHandles.Track(a)
-	}
-
-	return opts
-}
-
-func applyOptionsFromC(opts *C.git_apply_options) *ApplyOptions {
-	return &ApplyOptions{
-		Flags: uint(opts.flags),
-	}
-}
-
-// ApplyLocation represents the possible application locations for applying
-// diffs.
-type ApplyLocation int
-
-const (
-	// ApplyLocationWorkdir applies the patch to the workdir, leaving the
-	// index untouched. This is the equivalent of `git apply` with no location
-	// argument.
-	ApplyLocationWorkdir ApplyLocation = C.GIT_APPLY_LOCATION_WORKDIR
-	// ApplyLocationIndex applies the patch to the index, leaving the working
-	// directory untouched. This is the equivalent of `git apply --cached`.
-	ApplyLocationIndex ApplyLocation = C.GIT_APPLY_LOCATION_INDEX
-	// ApplyLocationBoth applies the patch to both the working directory and
-	// the index. This is the equivalent of `git apply --index`.
-	ApplyLocationBoth ApplyLocation = C.GIT_APPLY_LOCATION_BOTH
-)
-
-// ApplyDiff appllies a Diff to the given repository, making changes directly
-// in the working directory, the index, or both.
-func (v *Repository) ApplyDiff(diff *Diff, location ApplyLocation, opts *ApplyOptions) error {
-	runtime.LockOSThread()
-	defer runtime.UnlockOSThread()
-
-	cOpts := opts.toC()
-	ecode := C.git_apply(v.ptr, diff.ptr, C.git_apply_location_t(location), cOpts)
-	runtime.KeepAlive(v)
-	runtime.KeepAlive(diff)
-	runtime.KeepAlive(cOpts)
-	if ecode < 0 {
-		return MakeGitError(ecode)
-	}
-
-	return nil
-}
-
-// DiffFromBuffer reads the contents of a git patch file into a Diff object.
-//
-// The diff object produced is similar to the one that would be produced if you
-// actually produced it computationally by comparing two trees, however there
-// may be subtle differences. For example, a patch file likely contains
-// abbreviated object IDs, so the object IDs in a git_diff_delta produced by
-// this function will also be abbreviated.
-//
-// This function will only read patch files created by a git implementation, it
-// will not read unified diffs produced by the diff program, nor any other
-// types of patch files.
-func DiffFromBuffer(buffer []byte, repo *Repository) (*Diff, error) {
-	var diff *C.git_diff
-
-	cBuffer := C.CBytes(buffer)
-	defer C.free(unsafe.Pointer(cBuffer))
-
-	runtime.LockOSThread()
-	defer runtime.UnlockOSThread()
-
-	ecode := C.git_diff_from_buffer(&diff, (*C.char)(cBuffer), C.size_t(len(buffer)))
-	if ecode < 0 {
-		return nil, MakeGitError(ecode)
-	}
-	runtime.KeepAlive(diff)
-
-	return newDiffFromC(diff, repo), nil
-}
diff --git a/wrapper.c b/wrapper.c
index 1093cf4..df767fb 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -5,12 +5,6 @@
 
 typedef int (*gogit_submodule_cbk)(git_submodule *sm, const char *name, void *payload);
 
-void _go_git_populate_apply_cb(git_apply_options *options)
-{
-	options->delta_cb = (git_apply_delta_cb)deltaApplyCallback;
-	options->hunk_cb = (git_apply_hunk_cb)hunkApplyCallback;
-}
-
 void _go_git_populate_remote_cb(git_clone_options *opts)
 {
 	opts->remote_cb = (git_remote_create_cb)remoteCreateCallback;


Test patch:
diff --git a/diff_test.go b/diff_test.go
index 394a4c1..6fbad51 100644
--- a/diff_test.go
+++ b/diff_test.go
@@ -2,9 +2,6 @@ package git
 
 import (
 	"errors"
-	"fmt"
-	"io/ioutil"
-	"path"
 	"strings"
 	"testing"
 )
@@ -239,307 +236,3 @@ func TestDiffBlobs(t *testing.T) {
 		t.Fatalf("Bad number of lines iterated")
 	}
 }
-
-func TestApplyDiffAddfile(t *testing.T) {
-	repo := createTestRepo(t)
-	defer cleanupTestRepo(t, repo)
-
-	seedTestRepo(t, repo)
-
-	addFirstFileCommit, addFileTree := addAndGetTree(t, repo, "file1", `hello`)
-	addSecondFileCommit, addSecondFileTree := addAndGetTree(t, repo, "file2", `hello2`)
-
-	diff, err := repo.DiffTreeToTree(addFileTree, addSecondFileTree, nil)
-	checkFatal(t, err)
-
-	t.Run("check does not apply to current tree because file exists", func(t *testing.T) {
-		err = repo.ResetToCommit(addSecondFileCommit, ResetHard, &CheckoutOpts{})
-		checkFatal(t, err)
-
-		err = repo.ApplyDiff(diff, ApplyLocationBoth, nil)
-		if err == nil {
-			t.Error("expecting applying patch to current repo to fail")
-		}
-	})
-
-	t.Run("check apply to correct commit", func(t *testing.T) {
-		err = repo.ResetToCommit(addFirstFileCommit, ResetHard, &CheckoutOpts{})
-		checkFatal(t, err)
-
-		err = repo.ApplyDiff(diff, ApplyLocationBoth, nil)
-		checkFatal(t, err)
-
-		t.Run("Check that diff only changed one file", func(t *testing.T) {
-			checkSecondFileStaged(t, repo)
-
-			index, err := repo.Index()
-			checkFatal(t, err)
-			defer index.Free()
-
-			newTreeOID, err := index.WriteTreeTo(repo)
-			checkFatal(t, err)
-
-			newTree, err := repo.LookupTree(newTreeOID)
-			checkFatal(t, err)
-			defer newTree.Free()
-
-			_, err = repo.CreateCommit("HEAD", signature(), signature(), fmt.Sprintf("patch apply"), newTree, addFirstFileCommit)
-			checkFatal(t, err)
-		})
-
-		t.Run("test applying patch produced the same diff", func(t *testing.T) {
-			head, err := repo.Head()
-			checkFatal(t, err)
-
-			commit, err := repo.LookupCommit(head.Target())
-			checkFatal(t, err)
-
-			tree, err := commit.Tree()
-			checkFatal(t, err)
-
-			newDiff, err := repo.DiffTreeToTree(addFileTree, tree, nil)
-			checkFatal(t, err)
-
-			raw1b, err := diff.ToBuf(DiffFormatPatch)
-			checkFatal(t, err)
-			raw2b, err := newDiff.ToBuf(DiffFormatPatch)
-			checkFatal(t, err)
-
-			raw1 := string(raw1b)
-			raw2 := string(raw2b)
-
-			if raw1 != raw2 {
-				t.Error("diffs should be the same")
-			}
-		})
-	})
-
-	t.Run("check convert to raw buffer and apply", func(t *testing.T) {
-		err = repo.ResetToCommit(addFirstFileCommit, ResetHard, &CheckoutOpts{})
-		checkFatal(t, err)
-
-		raw, err := diff.ToBuf(DiffFormatPatch)
-		checkFatal(t, err)
-
-		if len(raw) == 0 {
-			t.Error("empty diff created")
-		}
-
-		diff2, err := DiffFromBuffer(raw, repo)
-		checkFatal(t, err)
-
-		err = repo.ApplyDiff(diff2, ApplyLocationBoth, nil)
-		checkFatal(t, err)
-	})
-
-	t.Run("check apply callbacks work", func(t *testing.T) {
-		// reset the state and get new default options for test
-		resetAndGetOpts := func(t *testing.T) *ApplyOptions {
-			err = repo.ResetToCommit(addFirstFileCommit, ResetHard, &CheckoutOpts{})
-			checkFatal(t, err)
-
-			opts, err := DefaultApplyOptions()
-			checkFatal(t, err)
-
-			return opts
-		}
-
-		t.Run("Check hunk callback working applies patch", func(t *testing.T) {
-			opts := resetAndGetOpts(t)
-
-			called := false
-			opts.ApplyHunkCallback = func(hunk *DiffHunk) (apply bool, err error) {
-				called = true
-				return true, nil
-			}
-
-			err = repo.ApplyDiff(diff, ApplyLocationBoth, opts)
-			checkFatal(t, err)
-
-			if called == false {
-				t.Error("apply hunk callback was not called")
-			}
-
-			checkSecondFileStaged(t, repo)
-		})
-
-		t.Run("Check delta callback working applies patch", func(t *testing.T) {
-			opts := resetAndGetOpts(t)
-
-			called := false
-			opts.ApplyDeltaCallback = func(hunk *DiffDelta) (apply bool, err error) {
-				if hunk.NewFile.Path != "file2" {
-					t.Error("Unexpected delta in diff application")
-				}
-				called = true
-				return true, nil
-			}
-
-			err = repo.ApplyDiff(diff, ApplyLocationBoth, opts)
-			checkFatal(t, err)
-
-			if called == false {
-				t.Error("apply hunk callback was not called")
-			}
-
-			checkSecondFileStaged(t, repo)
-		})
-
-		t.Run("Check delta callback returning false does not apply patch", func(t *testing.T) {
-			opts := resetAndGetOpts(t)
-
-			called := false
-			opts.ApplyDeltaCallback = func(hunk *DiffDelta) (apply bool, err error) {
-				if hunk.NewFile.Path != "file2" {
-					t.Error("Unexpected hunk in diff application")
-				}
-				called = true
-				return false, nil
-			}
-
-			err = repo.ApplyDiff(diff, ApplyLocationBoth, opts)
-			checkFatal(t, err)
-
-			if called == false {
-				t.Error("apply hunk callback was not called")
-			}
-
-			checkNoFilesStaged(t, repo)
-		})
-
-		t.Run("Check hunk callback returning causes application to fail", func(t *testing.T) {
-			opts := resetAndGetOpts(t)
-
-			called := false
-			opts.ApplyHunkCallback = func(hunk *DiffHunk) (apply bool, err error) {
-				called = true
-				return false, errors.New("something happened")
-			}
-
-			err = repo.ApplyDiff(diff, ApplyLocationBoth, opts)
-			if err == nil {
-				t.Error("expected an error after trying to apply")
-			}
-
-			if called == false {
-				t.Error("apply hunk callback was not called")
-			}
-
-			checkNoFilesStaged(t, repo)
-		})
-
-		t.Run("Check delta callback returning causes application to fail", func(t *testing.T) {
-			opts := resetAndGetOpts(t)
-
-			called := false
-			opts.ApplyDeltaCallback = func(hunk *DiffDelta) (apply bool, err error) {
-				if hunk.NewFile.Path != "file2" {
-					t.Error("Unexpected delta in diff application")
-				}
-				called = true
-				return false, errors.New("something happened")
-			}
-
-			err = repo.ApplyDiff(diff, ApplyLocationBoth, opts)
-			if err == nil {
-				t.Error("expected an error after trying to apply")
-			}
-
-			if called == false {
-				t.Error("apply hunk callback was not called")
-			}
-
-			checkNoFilesStaged(t, repo)
-		})
-	})
-}
-
-// checkSecondFileStaged checks that there is a single file called "file2" uncommitted in the repo
-func checkSecondFileStaged(t *testing.T, repo *Repository) {
-	opts := StatusOptions{
-		Show:  StatusShowIndexAndWorkdir,
-		Flags: StatusOptIncludeUntracked,
-	}
-
-	statuses, err := repo.StatusList(&opts)
-	checkFatal(t, err)
-
-	count, err := statuses.EntryCount()
-	checkFatal(t, err)
-
-	if count != 1 {
-		t.Error("diff should affect exactly one file")
-	}
-	if count == 0 {
-		t.Fatal("no statuses, cannot continue test")
-	}
-
-	entry, err := statuses.ByIndex(0)
-	checkFatal(t, err)
-
-	if entry.Status != StatusIndexNew {
-		t.Error("status should be 'new' as file has been added between commits")
-	}
-
-	if entry.HeadToIndex.NewFile.Path != "file2" {
-		t.Error("new file should be 'file2")
-	}
-	return
-}
-
-// checkNoFilesStaged checks that there is a single file called "file2" uncommitted in the repo
-func checkNoFilesStaged(t *testing.T, repo *Repository) {
-	opts := StatusOptions{
-		Show:  StatusShowIndexAndWorkdir,
-		Flags: StatusOptIncludeUntracked,
-	}
-
-	statuses, err := repo.StatusList(&opts)
-	checkFatal(t, err)
-
-	count, err := statuses.EntryCount()
-	checkFatal(t, err)
-
-	if count != 0 {
-		t.Error("files changed unexpectedly")
-	}
-}
-
-// addAndGetTree creates a file and commits it, returning the commit and tree
-func addAndGetTree(t *testing.T, repo *Repository, filename string, content string) (*Commit, *Tree) {
-	headCommit, err := headCommit(repo)
-	checkFatal(t, err)
-	defer headCommit.Free()
-
-	p := repo.Path()
-	p = strings.TrimSuffix(p, ".git")
-	p = strings.TrimSuffix(p, ".git/")
-
-	err = ioutil.WriteFile(path.Join(p, filename), []byte((content)), 0777)
-	checkFatal(t, err)
-
-	index, err := repo.Index()
-	checkFatal(t, err)
-	defer index.Free()
-
-	err = index.AddByPath(filename)
-	checkFatal(t, err)
-
-	newTreeOID, err := index.WriteTreeTo(repo)
-	checkFatal(t, err)
-
-	newTree, err := repo.LookupTree(newTreeOID)
-	checkFatal(t, err)
-	defer newTree.Free()
-
-	commitId, err := repo.CreateCommit("HEAD", signature(), signature(), fmt.Sprintf("add %s", filename), newTree, headCommit)
-	checkFatal(t, err)
-
-	commit, err := repo.LookupCommit(commitId)
-	checkFatal(t, err)
-
-	tree, err := commit.Tree()
-	checkFatal(t, err)
-
-	return commit, tree
-}