summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJochen Hilgers <[email protected]>2014-11-26 17:22:15 +0100
committerJochen Hilgers <[email protected]>2014-11-26 17:22:15 +0100
commita4ae68783d92a46b8d8bbd7e2aab3700bde10597 (patch)
tree36aa17bc98911687b5c50b6abaea41a6a381cb06
parent17963043741d7057cae1782032d022af0cd053fb (diff)
Integrated git_diff_find_similar
-rw-r--r--diff.go71
-rw-r--r--diff_test.go73
2 files changed, 139 insertions, 5 deletions
diff --git a/diff.go b/diff.go
index f762a56..661a9a7 100644
--- a/diff.go
+++ b/diff.go
@@ -164,6 +164,29 @@ func (diff *Diff) Free() error {
return nil
}
+func (diff *Diff) FindSimilar(opts *DiffFindOptions) error {
+
+ var copts *C.git_diff_find_options
+ if opts != nil {
+ copts = &C.git_diff_find_options{
+ version: C.GIT_DIFF_FIND_OPTIONS_VERSION,
+ flags: C.uint32_t(opts.Flags),
+ rename_threshold: C.uint16_t(opts.RenameThreshold),
+ copy_threshold: C.uint16_t(opts.CopyThreshold),
+ rename_from_rewrite_threshold: C.uint16_t(opts.RenameFromRewriteThreshold),
+ break_rewrite_threshold: C.uint16_t(opts.BreakRewriteThreshold),
+ rename_limit: C.size_t(opts.RenameLimit),
+ }
+ }
+
+ ecode := C.git_diff_find_similar(diff.ptr, copts)
+ if ecode < 0 {
+ return MakeGitError(ecode)
+ }
+
+ return nil
+}
+
type diffForEachData struct {
FileCallback DiffForEachFileCallback
HunkCallback DiffForEachHunkCallback
@@ -341,6 +364,54 @@ func DefaultDiffOptions() (DiffOptions, error) {
}, nil
}
+type DiffFindOptionsFlag int
+
+const (
+ DiffFindByConfig DiffFindOptionsFlag = C.GIT_DIFF_FIND_BY_CONFIG
+ DiffFindRenames DiffFindOptionsFlag = C.GIT_DIFF_FIND_RENAMES
+ DiffFindRenamesFromRewrites DiffFindOptionsFlag = C.GIT_DIFF_FIND_RENAMES_FROM_REWRITES
+ DiffFindCopies DiffFindOptionsFlag = C.GIT_DIFF_FIND_COPIES
+ DiffFindCopiesFromUnmodified DiffFindOptionsFlag = C.GIT_DIFF_FIND_COPIES_FROM_UNMODIFIED
+ DiffFindRewrites DiffFindOptionsFlag = C.GIT_DIFF_FIND_REWRITES
+ DiffFindBreakRewrites DiffFindOptionsFlag = C.GIT_DIFF_BREAK_REWRITES
+ DiffFindAndBreakRewrites DiffFindOptionsFlag = C.GIT_DIFF_FIND_AND_BREAK_REWRITES
+ DiffFindForUntracked DiffFindOptionsFlag = C.GIT_DIFF_FIND_FOR_UNTRACKED
+ DiffFindAll DiffFindOptionsFlag = C.GIT_DIFF_FIND_ALL
+ DiffFindIgnoreLeadingWhitespace DiffFindOptionsFlag = C.GIT_DIFF_FIND_IGNORE_LEADING_WHITESPACE
+ DiffFindIgnoreWhitespace DiffFindOptionsFlag = C.GIT_DIFF_FIND_IGNORE_WHITESPACE
+ DiffFindDontIgnoreWhitespace DiffFindOptionsFlag = C.GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE
+ DiffFindExactMatchOnly DiffFindOptionsFlag = C.GIT_DIFF_FIND_EXACT_MATCH_ONLY
+ DiffFindBreakRewritesForRenamesOnly DiffFindOptionsFlag = C.GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY
+ DiffFindRemoveUnmodified DiffFindOptionsFlag = C.GIT_DIFF_FIND_REMOVE_UNMODIFIED
+)
+
+//TODO implement git_diff_similarity_metric
+type DiffFindOptions struct {
+ Flags DiffFindOptionsFlag
+ RenameThreshold uint16
+ CopyThreshold uint16
+ RenameFromRewriteThreshold uint16
+ BreakRewriteThreshold uint16
+ RenameLimit uint
+}
+
+func DefaultDiffFindOptions() (DiffFindOptions, error) {
+ opts := C.git_diff_find_options{}
+ ecode := C.git_diff_find_init_options(&opts, C.GIT_DIFF_FIND_OPTIONS_VERSION)
+ if ecode < 0 {
+ return DiffFindOptions{}, MakeGitError(ecode)
+ }
+
+ return DiffFindOptions{
+ Flags: DiffFindOptionsFlag(opts.flags),
+ RenameThreshold: uint16(opts.rename_threshold),
+ CopyThreshold: uint16(opts.copy_threshold),
+ RenameFromRewriteThreshold: uint16(opts.rename_from_rewrite_threshold),
+ BreakRewriteThreshold: uint16(opts.break_rewrite_threshold),
+ RenameLimit: uint(opts.rename_limit),
+ }, nil
+}
+
var (
ErrDeltaSkip = errors.New("Skip delta")
)
diff --git a/diff_test.go b/diff_test.go
index b688294..84d72db 100644
--- a/diff_test.go
+++ b/diff_test.go
@@ -6,21 +6,69 @@ import (
"testing"
)
-func TestDiffTreeToTree(t *testing.T) {
+func TestFindSimilar(t *testing.T) {
repo := createTestRepo(t)
defer repo.Free()
defer os.RemoveAll(repo.Workdir())
- _, originalTreeId := seedTestRepo(t, repo)
- originalTree, err := repo.LookupTree(originalTreeId)
+ originalTree, newTree := createTestTrees(t, repo)
+
+ diffOpt, _ := DefaultDiffOptions()
+ diff, err := repo.DiffTreeToTree(originalTree, newTree, &diffOpt)
checkFatal(t, err)
+ if diff == nil {
+ t.Fatal("no diff returned")
+ }
- _, newTreeId := updateReadme(t, repo, "file changed\n")
+ findOpts, err := DefaultDiffFindOptions()
+ checkFatal(t, err)
+ findOpts.Flags = DiffFindBreakRewrites
- newTree, err := repo.LookupTree(newTreeId)
+ err = diff.FindSimilar(&findOpts)
checkFatal(t, err)
+ numDiffs := 0
+ numAdded := 0
+ numDeleted := 0
+
+ err = diff.ForEach(func(file DiffDelta, progress float64) (DiffForEachHunkCallback, error) {
+ numDiffs++
+
+ switch file.Status {
+ case DeltaAdded:
+ numAdded++
+ case DeltaDeleted:
+ numDeleted++
+ }
+
+ return func(hunk DiffHunk) (DiffForEachLineCallback, error) {
+ return func(line DiffLine) error {
+ return nil
+ }, nil
+ }, nil
+ }, DiffDetailLines)
+
+ if numDiffs != 2 {
+ t.Fatal("Incorrect number of files in diff")
+ }
+ if numAdded != 1 {
+ t.Fatal("Incorrect number of new files in diff")
+ }
+ if numDeleted != 1 {
+ t.Fatal("Incorrect number of deleted files in diff")
+ }
+
+}
+
+func TestDiffTreeToTree(t *testing.T) {
+
+ repo := createTestRepo(t)
+ defer repo.Free()
+ defer os.RemoveAll(repo.Workdir())
+
+ originalTree, newTree := createTestTrees(t, repo)
+
callbackInvoked := false
opts := DiffOptions{
NotifyCallback: func(diffSoFar *Diff, delta DiffDelta, matchedPathSpec string) error {
@@ -94,3 +142,18 @@ func TestDiffTreeToTree(t *testing.T) {
}
}
+
+func createTestTrees(t *testing.T, repo *Repository) (originalTree *Tree, newTree *Tree) {
+ var err error
+ _, originalTreeId := seedTestRepo(t, repo)
+ originalTree, err = repo.LookupTree(originalTreeId)
+
+ checkFatal(t, err)
+
+ _, newTreeId := updateReadme(t, repo, "file changed\n")
+
+ newTree, err = repo.LookupTree(newTreeId)
+ checkFatal(t, err)
+
+ return originalTree, newTree
+}