Integrated git_diff_find_similar #141
71
diff.go
71
diff.go
|
@ -164,6 +164,29 @@ func (diff *Diff) Free() error {
|
||||||
return nil
|
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 {
|
type diffForEachData struct {
|
||||||
FileCallback DiffForEachFileCallback
|
FileCallback DiffForEachFileCallback
|
||||||
HunkCallback DiffForEachHunkCallback
|
HunkCallback DiffForEachHunkCallback
|
||||||
|
@ -341,6 +364,54 @@ func DefaultDiffOptions() (DiffOptions, error) {
|
||||||
}, nil
|
}, 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 (
|
var (
|
||||||
ErrDeltaSkip = errors.New("Skip delta")
|
ErrDeltaSkip = errors.New("Skip delta")
|
||||||
)
|
)
|
||||||
|
|
75
diff_test.go
75
diff_test.go
|
@ -6,20 +6,68 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDiffTreeToTree(t *testing.T) {
|
func TestFindSimilar(t *testing.T) {
|
||||||
repo := createTestRepo(t)
|
repo := createTestRepo(t)
|
||||||
defer repo.Free()
|
defer repo.Free()
|
||||||
defer os.RemoveAll(repo.Workdir())
|
defer os.RemoveAll(repo.Workdir())
|
||||||
|
|
||||||
_, originalTreeId := seedTestRepo(t, repo)
|
originalTree, newTree := createTestTrees(t, repo)
|
||||||
originalTree, err := repo.LookupTree(originalTreeId)
|
|
||||||
|
|
||||||
|
diffOpt, _ := DefaultDiffOptions()
|
||||||
|
|
||||||
|
diff, err := repo.DiffTreeToTree(originalTree, newTree, &diffOpt)
|
||||||
|
checkFatal(t, err)
|
||||||
|
if diff == nil {
|
||||||
|
t.Fatal("no diff returned")
|
||||||
|
}
|
||||||
|
|
||||||
|
findOpts, err := DefaultDiffFindOptions()
|
||||||
|
checkFatal(t, err)
|
||||||
|
findOpts.Flags = DiffFindBreakRewrites
|
||||||
|
|
||||||
|
err = diff.FindSimilar(&findOpts)
|
||||||
checkFatal(t, err)
|
checkFatal(t, err)
|
||||||
|
|
||||||
_, newTreeId := updateReadme(t, repo, "file changed\n")
|
numDiffs := 0
|
||||||
|
numAdded := 0
|
||||||
|
numDeleted := 0
|
||||||
|
|
||||||
newTree, err := repo.LookupTree(newTreeId)
|
err = diff.ForEach(func(file DiffDelta, progress float64) (DiffForEachHunkCallback, error) {
|
||||||
checkFatal(t, err)
|
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
|
callbackInvoked := false
|
||||||
opts := DiffOptions{
|
opts := DiffOptions{
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue