Range-diff rd-51
- title
- feat: range diff
- description
-
Patch changed
- old #1
778bcd8
- new #1
0f86231
1: 778bcd8 ! 1: 0f86231 feat: range diff
range_diff.go
+package git + +import ( + "fmt" + "math" + + "github.com/sergi/go-diff/diffmatchpatch" +) + +var COST_MAX = 65536 +var RANGE_DIFF_CREATION_FACTOR_DEFAULT = 60 + +type PatchRange struct { + *Patch + Matching int + Diff string + DiffSize int + Shown bool +} + +func NewPatchRange(patch *Patch) *PatchRange { + diff := patch.CalcDiff() + return &PatchRange{ + Patch: patch, + Patch: patch, + Matching: -1, + Diff: diff, + DiffSize: len(diff), + Shown: false, + } +} + +func output(a []*PatchRange, b []*PatchRange) string { + out := "" + for _, patchB := range b { + for i, patchA := range a { + if patchA.Matching == -1 { + out += outputPairHeader(patchA, nil, i+1, -1) + } + } + + for j, patchB := range b { + if patchB.Matching == -1 { + out += outputPairHeader(nil, patchB, -1, j+1) + continue + } + patchA := a[patchB.Matching] + if patchB.ContentSha == patchA.ContentSha { + out += outputPairHeader(patchA, patchB, patchB.Matching+1, patchA.Matching+1) + } + } + return out +} + +func outputPairHeader(a *PatchRange, b *PatchRange, aIndex, bIndex int) string { + if a == nil { + return fmt.Sprintf("-: ------- > %d: %s %s\n", bIndex, truncateSha(b.CommitSha), b.Title) + } + if b == nil { + return fmt.Sprintf("%d: %s < -: ------- %s\n", aIndex, truncateSha(a.CommitSha), a.Title) + } + return fmt.Sprintf("%d: %s = %d: %s %s\n", aIndex, truncateSha(a.CommitSha), bIndex, truncateSha(b.CommitSha), a.Title) +} + +func RangeDiff(a []*Patch, b []*Patch) string { + aPatches := []*PatchRange{} + for _, patch := range a { + aPatches = append(aPatches, NewPatchRange(patch)) + } + bPatches := []*PatchRange{} + for _, patch := range b { + bPatches = append(bPatches, NewPatchRange(patch)) + } + findExactMatches(aPatches, bPatches) + getCorrespondences(aPatches, bPatches, RANGE_DIFF_CREATION_FACTOR_DEFAULT) + return output(aPatches, bPatches) +} + +func findExactMatches(a []*PatchRange, b []*PatchRange) { + for i, patchA := range a { + for j, patchB := range b { + if patchA.ContentSha == patchB.ContentSha { + patchA.Matching = j + patchB.Matching = i + } + } + } +} + +func createMatrix(rows, cols int) [][]int { + mat := make([][]int, rows) + for i := range mat { + mat[i] = make([]int, cols) + } + return mat +} + +func diffsize(a *PatchRange, b *PatchRange) int { + dmp := diffmatchpatch.New() + diffs := dmp.DiffMain(a.RawText, b.RawText, false) + diffs := dmp.DiffMain(a.Diff, b.Diff, false) + return len(dmp.DiffPrettyText(diffs)) +} + +func getCorrespondences(a []*PatchRange, b []*PatchRange, creationFactor int) { + // n := len(a) + len(b) + fmt.Println(len(a), len(b)) + cost := createMatrix(len(a), len(b)) + n := len(a) + len(b) + fmt.Println("rows", len(a), "cols", len(b)) + cost := createMatrix(n, n) + + for i, patchA := range a { + var c int + for j, patchB := range b { + if patchA.Matching == j { + c = 0 + } else if patchA.Matching == 0 && patchB.Matching == 0 { + } else if patchA.Matching == -1 && patchB.Matching == -1 { + c = diffsize(patchA, patchB) + } else { + c = COST_MAX + } + cost[i][j] = c + } + } + + assignment := computeAssignment(cost, len(a), len(b)) + for i, j := range assignment { + if j < len(b) { + a[i].Matching = j + b[j].Matching = i + for j, patchB := range b { + creationCost := (patchB.DiffSize * creationFactor) / 100 + if patchB.Matching >= 0 { + creationCost = math.MaxInt32 + } + for i := len(a); i < n; i++ { + cost[i][j] = creationCost + } + } + + fmt.Println(cost, assignment) + fmt.Println("A==") + for _, patch := range a { + fmt.Println("matches", b[patch.Matching].Title) + for i := len(a); i < n; i++ { + for j := len(b); j < n; j++ { + cost[i][j] = 0 + } + } + + fmt.Println("B==") + for _, patch := range b { + fmt.Println("matches", a[patch.Matching].Title) + assignment := computeAssignment(cost, n, n) + for i, j := range assignment { + if i < len(a) && j < len(b) { + a[i].Matching = j + b[j].Matching = i + } + } + + fmt.Println("cost", cost, "assignment", assignment) +} + +// computeAssignment assigns patches using the Hungarian algorithm. +func computeAssignment(costMatrix [][]int, m, n int) []int { + u := make([]int, m+1) // potential for workers + v := make([]int, n+1) // potential for jobs + p := make([]int, n+1) // job assignment + way := make([]int, n+1) + + for i := 1; i <= m; i++ { + links := make([]int, n+1) + minV := make([]int, n+1) + used := make([]bool, n+1) + for j := 0; j <= n; j++ { + minV[j] = math.MaxInt32 + used[j] = false + } + + j0 := 0 + p[0] = i + + for { + used[j0] = true + i0 := p[j0] + delta := math.MaxInt32 + j1 := 0 + + for j := 1; j <= n; j++ { + if !used[j] { + cur := costMatrix[i0-1][j-1] - u[i0] - v[j] + if cur < minV[j] { + minV[j] = cur + links[j] = j0 + } + if minV[j] < delta { + delta = minV[j] + j1 = j + } + } + } + + for j := 0; j <= n; j++ { + if used[j] { + u[p[j]] += delta + v[j] -= delta + } else { + minV[j] -= delta + } + } + + j0 = j1 + if p[j0] == 0 { + break + } + } + + for { + j1 := way[j0] + p[j0] = p[j1] + j0 = j1 + if j0 == 0 { + break + } + } + } + + assignment := make([]int, m) + for j := 1; j <= n; j++ { + if p[j] > 0 { + assignment[p[j]-1] = j - 1 + } + } + return assignment +}
range_diff.go
+package git + +import ( + "fmt" + "math" + + "github.com/sergi/go-diff/diffmatchpatch" +) + +var COST_MAX = 65536 +var RANGE_DIFF_CREATION_FACTOR_DEFAULT = 60 + +type PatchRange struct { + *Patch + Matching int + Diff string + DiffSize int + Shown bool +} + +func NewPatchRange(patch *Patch) *PatchRange { + diff := patch.CalcDiff() + return &PatchRange{ + Patch: patch, + Patch: patch, + Matching: -1, + Diff: diff, + DiffSize: len(diff), + Shown: false, + } +} + +func output(a []*PatchRange, b []*PatchRange) string { + out := "" + for _, patchB := range b { + for i, patchA := range a { + if patchA.Matching == -1 { + out += outputPairHeader(patchA, nil, i+1, -1) + } + } + + for j, patchB := range b { + if patchB.Matching == -1 { + out += outputPairHeader(nil, patchB, -1, j+1) + continue + } + patchA := a[patchB.Matching] + if patchB.ContentSha == patchA.ContentSha { + out += outputPairHeader(patchA, patchB, patchB.Matching+1, patchA.Matching+1) + } + } + return out +} + +func outputPairHeader(a *PatchRange, b *PatchRange, aIndex, bIndex int) string { + if a == nil { + return fmt.Sprintf("-: ------- > %d: %s %s\n", bIndex, truncateSha(b.CommitSha), b.Title) + } + if b == nil { + return fmt.Sprintf("%d: %s < -: ------- %s\n", aIndex, truncateSha(a.CommitSha), a.Title) + } + return fmt.Sprintf("%d: %s = %d: %s %s\n", aIndex, truncateSha(a.CommitSha), bIndex, truncateSha(b.CommitSha), a.Title) +} + +func RangeDiff(a []*Patch, b []*Patch) string { + aPatches := []*PatchRange{} + for _, patch := range a { + aPatches = append(aPatches, NewPatchRange(patch)) + } + bPatches := []*PatchRange{} + for _, patch := range b { + bPatches = append(bPatches, NewPatchRange(patch)) + } + findExactMatches(aPatches, bPatches) + getCorrespondences(aPatches, bPatches, RANGE_DIFF_CREATION_FACTOR_DEFAULT) + return output(aPatches, bPatches) +} + +func findExactMatches(a []*PatchRange, b []*PatchRange) { + for i, patchA := range a { + for j, patchB := range b { + if patchA.ContentSha == patchB.ContentSha { + patchA.Matching = j + patchB.Matching = i + } + } + } +} + +func createMatrix(rows, cols int) [][]int { + mat := make([][]int, rows) + for i := range mat { + mat[i] = make([]int, cols) + } + return mat +} + +func diffsize(a *PatchRange, b *PatchRange) int { + dmp := diffmatchpatch.New() + diffs := dmp.DiffMain(a.RawText, b.RawText, false) + diffs := dmp.DiffMain(a.Diff, b.Diff, false) + return len(dmp.DiffPrettyText(diffs)) +} + +func getCorrespondences(a []*PatchRange, b []*PatchRange, creationFactor int) { + // n := len(a) + len(b) + fmt.Println(len(a), len(b)) + cost := createMatrix(len(a), len(b)) + n := len(a) + len(b) + fmt.Println("rows", len(a), "cols", len(b)) + cost := createMatrix(n, n) + + for i, patchA := range a { + var c int + for j, patchB := range b { + if patchA.Matching == j { + c = 0 + } else if patchA.Matching == 0 && patchB.Matching == 0 { + } else if patchA.Matching == -1 && patchB.Matching == -1 { + c = diffsize(patchA, patchB) + } else { + c = COST_MAX + } + cost[i][j] = c + } + } + + assignment := computeAssignment(cost, len(a), len(b)) + for i, j := range assignment { + if j < len(b) { + a[i].Matching = j + b[j].Matching = i + for j, patchB := range b { + creationCost := (patchB.DiffSize * creationFactor) / 100 + if patchB.Matching >= 0 { + creationCost = math.MaxInt32 + } + for i := len(a); i < n; i++ { + cost[i][j] = creationCost + } + } + + fmt.Println(cost, assignment) + fmt.Println("A==") + for _, patch := range a { + fmt.Println("matches", b[patch.Matching].Title) + for i := len(a); i < n; i++ { + for j := len(b); j < n; j++ { + cost[i][j] = 0 + } + } + + fmt.Println("B==") + for _, patch := range b { + fmt.Println("matches", a[patch.Matching].Title) + assignment := computeAssignment(cost, n, n) + for i, j := range assignment { + if i < len(a) && j < len(b) { + a[i].Matching = j + b[j].Matching = i + } + } + + fmt.Println("cost", cost, "assignment", assignment) +} + +// computeAssignment assigns patches using the Hungarian algorithm. +func computeAssignment(costMatrix [][]int, m, n int) []int { + u := make([]int, m+1) // potential for workers + v := make([]int, n+1) // potential for jobs + p := make([]int, n+1) // job assignment + way := make([]int, n+1) + + for i := 1; i <= m; i++ { + links := make([]int, n+1) + minV := make([]int, n+1) + used := make([]bool, n+1) + for j := 0; j <= n; j++ { + minV[j] = math.MaxInt32 + used[j] = false + } + + j0 := 0 + p[0] = i + + for { + used[j0] = true + i0 := p[j0] + delta := math.MaxInt32 + j1 := 0 + + for j := 1; j <= n; j++ { + if !used[j] { + cur := costMatrix[i0-1][j-1] - u[i0] - v[j] + if cur < minV[j] { + minV[j] = cur + links[j] = j0 + } + if minV[j] < delta { + delta = minV[j] + j1 = j + } + } + } + + for j := 0; j <= n; j++ { + if used[j] { + u[p[j]] += delta + v[j] -= delta + } else { + minV[j] -= delta + } + } + + j0 = j1 + if p[j0] == 0 { + break + } + } + + for { + j1 := way[j0] + p[j0] = p[j1] + j0 = j1 + if j0 == 0 { + break + } + } + } + + assignment := make([]int, m) + for j := 1; j <= n; j++ { + if p[j] > 0 { + assignment[p[j]-1] = j - 1 + } + } + return assignment +}
range_diff_test.go
+package git + +import ( + "fmt" + "testing" + + "github.com/picosh/git-pr/fixtures" +) + +func bail(err error) { + if err != nil { + panic(bail) + } +} + +func cmp(afile, bfile string) string { + a, err := fixtures.Fixtures.Open(afile) + bail(err) + b, err := fixtures.Fixtures.Open(bfile) + bail(err) + aPatches, err := ParsePatchset(a) + bail(err) + bPatches, err := ParsePatchset(b) + bail(err) + actual := RangeDiff(aPatches, bPatches) + return actual +} + +func fail(expected, actual string) string { + return fmt.Sprintf("expected:[%s] actual:[%s]", expected, actual) +} + +// https://git.kernel.org/tree/t/t3206-range-diff.sh?id=d19b6cd2dd72dc811f19df4b32c7ed223256c3ee + +// simple A..B A..C (unmodified) +/* + 1: $(test_oid t1) = 1: $(test_oid u1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid u2) s/4/A/ + 3: $(test_oid t3) = 3: $(test_oid u3) s/11/B/ + 4: $(test_oid t4) = 4: $(test_oid u4) s/12/B/ +*/ +func TestRangeDiffUnmodified(t *testing.T) { + actual := cmp("a_b.patch", "a_c.patch") + expected := "1: 33c682a = 1: 1668484 chore: add torch and create random tensor\n" + if expected != actual { + t.Fatalf(fail(expected, actual)) + } +} + +// trivial reordering +/* + 1: $(test_oid t1) = 1: $(test_oid r1) s/5/A/ + 3: $(test_oid t3) = 2: $(test_oid r2) s/11/B/ + 4: $(test_oid t4) = 3: $(test_oid r3) s/12/B/ + 2: $(test_oid t2) = 4: $(test_oid r4) s/4/A/ +*/ +func TestRangeDiffTrivialReordering(t *testing.T) { + actual := cmp("a_b_reorder.patch", "a_c_reorder.patch") + expected := `2: 22dde12 = 1: 7dbb94c docs: readme +1: 33c682a = 2: ad17587 chore: add torch and create random tensor +` + if expected != actual { + t.Fatalf(fail(expected, actual)) + } +} + +// removed commit +/* + 1: $(test_oid t1) = 1: $(test_oid d1) s/5/A/ + 2: $(test_oid t2) < -: $(test_oid __) s/4/A/ + 3: $(test_oid t3) = 2: $(test_oid d2) s/11/B/ + 4: $(test_oid t4) = 3: $(test_oid d3) s/12/B/ +*/ +func TestRangeDiffRemovedCommit(t *testing.T) { + actual := cmp("a_b_reorder.patch", "a_c_reorder.patch") + actual := cmp("a_b_reorder.patch", "a_c_rm_commit.patch") + expected := `1: 33c682a < -: ------- chore: add torch and create random tensor +2: 22dde12 = 1: 7dbb94c docs: readme` +2: 22dde12 = 1: 7dbb94c docs: readme +` + if expected != actual { + t.Fatalf(fail(expected, actual)) + } +} + +// added commit +/* + 1: $(test_oid t1) = 1: $(test_oid a1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid a2) s/4/A/ + -: $(test_oid __) > 3: $(test_oid a3) s/6/A/ + 3: $(test_oid t3) = 4: $(test_oid a4) s/11/B/ + 4: $(test_oid t4) = 5: $(test_oid a5) s/12/B/ +*/ +/* func TestRangeDiffAddedCommit(t *testing.T) { + actual := "" +func TestRangeDiffAddedCommit(t *testing.T) { + actual := cmp("a_b_reorder.patch", "a_c_added_commit.patch") + expected := `1: 33c682a = 1: 33c682a chore: add torch and create random tensor +2: 22dde12 = 2: 22dde12 docs: readme +-: ------- > 3: b248060 chore: make tensor 6x6` +-: ------- > 3: b248060 chore: make tensor 6x6 +` + if expected != actual { + t.Fatalf("expected:%s actual:%s", expected, actual) + t.Fatalf(fail(expected, actual)) + } +} */ +} + +// changed commit +/* + 1: $(test_oid t1) = 1: $(test_oid c1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid c2) s/4/A/ + 3: $(test_oid t3) ! 3: $(test_oid c3) s/11/B/ + @@ file: A + 9 + 10 + -11 + -+B + ++BB + 12 + 13 + 14 + 4: $(test_oid t4) ! 4: $(test_oid c4) s/12/B/ + @@ file + @@ file: A + 9 + 10 + - B + + BB + -12 + +B + 13 +*/ +/* func TestRangeDiffChangedCommit(t *testing.T) { + actual := "" + fp, err := fixtures.Fixtures.ReadFile("extected_commit_changed.txt") +func TestRangeDiffChangedCommit(t *testing.T) { + actual := cmp("a_b_reorder.patch", "a_c_changed_commit.patch") + fp, err := fixtures.Fixtures.ReadFile("expected_commit_changed.txt") + if err != nil { + t.Fatalf("file not found") + } + expected := string(fp) + if expected != actual { + t.Fatalf("expected:%s actual:%s", expected, actual) + t.Fatalf(fail(expected, actual)) + } +} */ +} + +// renamed file +/* + 1: $(test_oid t1) = 1: $(test_oid n1) s/5/A/ + 2: $(test_oid t2) ! 2: $(test_oid n2) s/4/A/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/4/A/ + + s/4/A/ + rename file + Z + - ## file ## + + ## file => renamed-file ## + Z@@ + Z 1 + Z 2 + 3: $(test_oid t3) ! 3: $(test_oid n3) s/11/B/ + @@ Metadata + Z ## Commit message ## + Z s/11/B/ + Z + - ## file ## + -@@ file: A + + ## renamed-file ## + +@@ renamed-file: A + Z 8 + Z 9 + Z 10 + 4: $(test_oid t4) ! 4: $(test_oid n4) s/12/B/ + @@ Metadata + Z ## Commit message ## + Z s/12/B/ + Z + - ## file ## + -@@ file: A + + ## renamed-file ## + +@@ renamed-file: A + Z 9 + Z 10 + Z B +*/ +// func TestRangeDiffRenamedFile(t *testing.T) {} + +// file with mode only change +/* + 1: $(test_oid t2) ! 1: $(test_oid o1) s/4/A/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/4/A/ + + s/4/A/ + add other-file + Z + Z ## file ## + Z@@ + @@ file + Z A + Z 6 + Z 7 + + + + ## other-file (new) ## + 2: $(test_oid t3) ! 2: $(test_oid o2) s/11/B/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/11/B/ + + s/11/B/ + mode change other-file + Z + Z ## file ## + Z@@ file: A + @@ file: A + Z 12 + Z 13 + Z 14 + + + + ## other-file (mode change 100644 => 100755) ## + 3: $(test_oid t4) = 3: $(test_oid o3) s/12/B/ +*/ +// func TestRangeDiffFileWithModeOnlyChange(t *testing.T) {} + +// file added and later removed +/* + 1: $(test_oid t1) = 1: $(test_oid s1) s/5/A/ + 2: $(test_oid t2) ! 2: $(test_oid s2) s/4/A/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/4/A/ + + s/4/A/ + new-file + Z + Z ## file ## + Z@@ + @@ file + Z A + Z 6 + Z 7 + + + + ## new-file (new) ## + 3: $(test_oid t3) ! 3: $(test_oid s3) s/11/B/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/11/B/ + + s/11/B/ + remove file + Z + Z ## file ## + Z@@ file: A + @@ file: A + Z 12 + Z 13 + Z 14 + + + + ## new-file (deleted) ## + 4: $(test_oid t4) = 4: $(test_oid s4) s/12/B/ +*/ +// func TestRangeDiffFileAddedThenRemoved(t *testing.T) {} + +// changed message +/* + 1: $(test_oid t1) = 1: $(test_oid m1) s/5/A/ + 2: $(test_oid t2) ! 2: $(test_oid m2) s/4/A/ + @@ Metadata + Z ## Commit message ## + Z s/4/A/ + Z + + Also a silly comment here! + + + Z ## file ## + Z@@ + Z 1 + 3: $(test_oid t3) = 3: $(test_oid m3) s/11/B/ + 4: $(test_oid t4) = 4: $(test_oid m4) s/12/B/ +*/ +// func TestRangeDiffChangedMessage(t *testing.T) {}
range_diff_test.go
+package git + +import ( + "fmt" + "testing" + + "github.com/picosh/git-pr/fixtures" +) + +func bail(err error) { + if err != nil { + panic(bail) + } +} + +func cmp(afile, bfile string) string { + a, err := fixtures.Fixtures.Open(afile) + bail(err) + b, err := fixtures.Fixtures.Open(bfile) + bail(err) + aPatches, err := ParsePatchset(a) + bail(err) + bPatches, err := ParsePatchset(b) + bail(err) + actual := RangeDiff(aPatches, bPatches) + return actual +} + +func fail(expected, actual string) string { + return fmt.Sprintf("expected:[%s] actual:[%s]", expected, actual) +} + +// https://git.kernel.org/tree/t/t3206-range-diff.sh?id=d19b6cd2dd72dc811f19df4b32c7ed223256c3ee + +// simple A..B A..C (unmodified) +/* + 1: $(test_oid t1) = 1: $(test_oid u1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid u2) s/4/A/ + 3: $(test_oid t3) = 3: $(test_oid u3) s/11/B/ + 4: $(test_oid t4) = 4: $(test_oid u4) s/12/B/ +*/ +func TestRangeDiffUnmodified(t *testing.T) { + actual := cmp("a_b.patch", "a_c.patch") + expected := "1: 33c682a = 1: 1668484 chore: add torch and create random tensor\n" + if expected != actual { + t.Fatalf(fail(expected, actual)) + } +} + +// trivial reordering +/* + 1: $(test_oid t1) = 1: $(test_oid r1) s/5/A/ + 3: $(test_oid t3) = 2: $(test_oid r2) s/11/B/ + 4: $(test_oid t4) = 3: $(test_oid r3) s/12/B/ + 2: $(test_oid t2) = 4: $(test_oid r4) s/4/A/ +*/ +func TestRangeDiffTrivialReordering(t *testing.T) { + actual := cmp("a_b_reorder.patch", "a_c_reorder.patch") + expected := `2: 22dde12 = 1: 7dbb94c docs: readme +1: 33c682a = 2: ad17587 chore: add torch and create random tensor +` + if expected != actual { + t.Fatalf(fail(expected, actual)) + } +} + +// removed commit +/* + 1: $(test_oid t1) = 1: $(test_oid d1) s/5/A/ + 2: $(test_oid t2) < -: $(test_oid __) s/4/A/ + 3: $(test_oid t3) = 2: $(test_oid d2) s/11/B/ + 4: $(test_oid t4) = 3: $(test_oid d3) s/12/B/ +*/ +func TestRangeDiffRemovedCommit(t *testing.T) { + actual := cmp("a_b_reorder.patch", "a_c_reorder.patch") + actual := cmp("a_b_reorder.patch", "a_c_rm_commit.patch") + expected := `1: 33c682a < -: ------- chore: add torch and create random tensor +2: 22dde12 = 1: 7dbb94c docs: readme` +2: 22dde12 = 1: 7dbb94c docs: readme +` + if expected != actual { + t.Fatalf(fail(expected, actual)) + } +} + +// added commit +/* + 1: $(test_oid t1) = 1: $(test_oid a1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid a2) s/4/A/ + -: $(test_oid __) > 3: $(test_oid a3) s/6/A/ + 3: $(test_oid t3) = 4: $(test_oid a4) s/11/B/ + 4: $(test_oid t4) = 5: $(test_oid a5) s/12/B/ +*/ +/* func TestRangeDiffAddedCommit(t *testing.T) { + actual := "" +func TestRangeDiffAddedCommit(t *testing.T) { + actual := cmp("a_b_reorder.patch", "a_c_added_commit.patch") + expected := `1: 33c682a = 1: 33c682a chore: add torch and create random tensor +2: 22dde12 = 2: 22dde12 docs: readme +-: ------- > 3: b248060 chore: make tensor 6x6` +-: ------- > 3: b248060 chore: make tensor 6x6 +` + if expected != actual { + t.Fatalf("expected:%s actual:%s", expected, actual) + t.Fatalf(fail(expected, actual)) + } +} */ +} + +// changed commit +/* + 1: $(test_oid t1) = 1: $(test_oid c1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid c2) s/4/A/ + 3: $(test_oid t3) ! 3: $(test_oid c3) s/11/B/ + @@ file: A + 9 + 10 + -11 + -+B + ++BB + 12 + 13 + 14 + 4: $(test_oid t4) ! 4: $(test_oid c4) s/12/B/ + @@ file + @@ file: A + 9 + 10 + - B + + BB + -12 + +B + 13 +*/ +/* func TestRangeDiffChangedCommit(t *testing.T) { + actual := "" + fp, err := fixtures.Fixtures.ReadFile("extected_commit_changed.txt") +func TestRangeDiffChangedCommit(t *testing.T) { + actual := cmp("a_b_reorder.patch", "a_c_changed_commit.patch") + fp, err := fixtures.Fixtures.ReadFile("expected_commit_changed.txt") + if err != nil { + t.Fatalf("file not found") + } + expected := string(fp) + if expected != actual { + t.Fatalf("expected:%s actual:%s", expected, actual) + t.Fatalf(fail(expected, actual)) + } +} */ +} + +// renamed file +/* + 1: $(test_oid t1) = 1: $(test_oid n1) s/5/A/ + 2: $(test_oid t2) ! 2: $(test_oid n2) s/4/A/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/4/A/ + + s/4/A/ + rename file + Z + - ## file ## + + ## file => renamed-file ## + Z@@ + Z 1 + Z 2 + 3: $(test_oid t3) ! 3: $(test_oid n3) s/11/B/ + @@ Metadata + Z ## Commit message ## + Z s/11/B/ + Z + - ## file ## + -@@ file: A + + ## renamed-file ## + +@@ renamed-file: A + Z 8 + Z 9 + Z 10 + 4: $(test_oid t4) ! 4: $(test_oid n4) s/12/B/ + @@ Metadata + Z ## Commit message ## + Z s/12/B/ + Z + - ## file ## + -@@ file: A + + ## renamed-file ## + +@@ renamed-file: A + Z 9 + Z 10 + Z B +*/ +// func TestRangeDiffRenamedFile(t *testing.T) {} + +// file with mode only change +/* + 1: $(test_oid t2) ! 1: $(test_oid o1) s/4/A/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/4/A/ + + s/4/A/ + add other-file + Z + Z ## file ## + Z@@ + @@ file + Z A + Z 6 + Z 7 + + + + ## other-file (new) ## + 2: $(test_oid t3) ! 2: $(test_oid o2) s/11/B/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/11/B/ + + s/11/B/ + mode change other-file + Z + Z ## file ## + Z@@ file: A + @@ file: A + Z 12 + Z 13 + Z 14 + + + + ## other-file (mode change 100644 => 100755) ## + 3: $(test_oid t4) = 3: $(test_oid o3) s/12/B/ +*/ +// func TestRangeDiffFileWithModeOnlyChange(t *testing.T) {} + +// file added and later removed +/* + 1: $(test_oid t1) = 1: $(test_oid s1) s/5/A/ + 2: $(test_oid t2) ! 2: $(test_oid s2) s/4/A/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/4/A/ + + s/4/A/ + new-file + Z + Z ## file ## + Z@@ + @@ file + Z A + Z 6 + Z 7 + + + + ## new-file (new) ## + 3: $(test_oid t3) ! 3: $(test_oid s3) s/11/B/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/11/B/ + + s/11/B/ + remove file + Z + Z ## file ## + Z@@ file: A + @@ file: A + Z 12 + Z 13 + Z 14 + + + + ## new-file (deleted) ## + 4: $(test_oid t4) = 4: $(test_oid s4) s/12/B/ +*/ +// func TestRangeDiffFileAddedThenRemoved(t *testing.T) {} + +// changed message +/* + 1: $(test_oid t1) = 1: $(test_oid m1) s/5/A/ + 2: $(test_oid t2) ! 2: $(test_oid m2) s/4/A/ + @@ Metadata + Z ## Commit message ## + Z s/4/A/ + Z + + Also a silly comment here! + + + Z ## file ## + Z@@ + Z 1 + 3: $(test_oid t3) = 3: $(test_oid m3) s/11/B/ + 4: $(test_oid t4) = 4: $(test_oid m4) s/12/B/ +*/ +// func TestRangeDiffChangedMessage(t *testing.T) {}
util.go
return str[idx:], nil } -func parsePatchset(patchset io.Reader) ([]*Patch, error) { +func ParsePatchset(patchset io.Reader) ([]*Patch, error) { patches := []*Patch{} buf := new(strings.Builder) _, err := io.Copy(buf, patchset) + Files: diffFiles, authorEmail = header.Author.Email } content := fmt.Sprintf( - "%s\n%s\n%s\n%s\n%s\n", + "%s\n%s\n%s\n%s\n", header.Title, header.Body, authorName, authorEmail, - header.AuthorDate, ) for _, diff := range diffFiles { // we need to ignore diffs with base commit because that depends
util.go
return str[idx:], nil } -func parsePatchset(patchset io.Reader) ([]*Patch, error) { +func ParsePatchset(patchset io.Reader) ([]*Patch, error) { patches := []*Patch{} buf := new(strings.Builder) _, err := io.Copy(buf, patchset) ContentSha: contentSha, RawText: patchStr, BaseCommitSha: sql.NullString{String: baseCommit}, + Files: diffFiles, }) } authorEmail = header.Author.Email } content := fmt.Sprintf( - "%s\n%s\n%s\n%s\n%s\n", + "%s\n%s\n%s\n%s\n", header.Title, header.Body, authorName, authorEmail, - header.AuthorDate, ) for _, diff := range diffFiles { // we need to ignore diffs with base commit because that depends