Integrated git_diff_find_similar #141
71
diff.go
71
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")
|
||||
)
|
||||
|
|
75
diff_test.go
75
diff_test.go
|
@ -6,20 +6,68 @@ 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")
|
||||
}
|
||||
|
||||
findOpts, err := DefaultDiffFindOptions()
|
||||
checkFatal(t, err)
|
||||
findOpts.Flags = DiffFindBreakRewrites
|
||||
|
||||
err = diff.FindSimilar(&findOpts)
|
||||
checkFatal(t, err)
|
||||
|
||||
_, newTreeId := updateReadme(t, repo, "file changed\n")
|
||||
numDiffs := 0
|
||||
numAdded := 0
|
||||
numDeleted := 0
|
||||
|
||||
newTree, err := repo.LookupTree(newTreeId)
|
||||
checkFatal(t, err)
|
||||
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{
|
||||
|
@ -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