mirror of
https://github.com/dolthub/dolt.git
synced 2026-01-07 00:39:44 -06:00
Merge pull request #875 from liquidata-inc/aaron/cross-db-commitwalks
go: Changes to support some commit walks used in Dolthub diffs when the commits come from different repositories.
This commit is contained in:
@@ -199,7 +199,7 @@ func GetCommitAncestor(ctx context.Context, cm1, cm2 *Commit) (*Commit, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ref, err := getCommitAncestorRef(ctx, ref1, ref2, cm1.vrw)
|
||||
ref, err := getCommitAncestorRef(ctx, ref1, ref2, cm1.vrw, cm2.vrw)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -220,8 +220,8 @@ func GetCommitAncestor(ctx context.Context, cm1, cm2 *Commit) (*Commit, error) {
|
||||
return NewCommit(cm1.vrw, ancestorSt), nil
|
||||
}
|
||||
|
||||
func getCommitAncestorRef(ctx context.Context, ref1, ref2 types.Ref, vrw types.ValueReadWriter) (types.Ref, error) {
|
||||
ancestorRef, ok, err := datas.FindCommonAncestor(ctx, ref1, ref2, vrw)
|
||||
func getCommitAncestorRef(ctx context.Context, ref1, ref2 types.Ref, vrw1, vrw2 types.ValueReadWriter) (types.Ref, error) {
|
||||
ancestorRef, ok, err := datas.FindCommonAncestor(ctx, ref1, ref2, vrw1, vrw2)
|
||||
|
||||
if err != nil {
|
||||
return types.Ref{}, err
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
)
|
||||
|
||||
type c struct {
|
||||
ddb *doltdb.DoltDB
|
||||
commit *doltdb.Commit
|
||||
hash hash.Hash
|
||||
height uint64
|
||||
@@ -34,8 +35,6 @@ type q struct {
|
||||
pending []*c
|
||||
numVisiblePending int
|
||||
loaded map[hash.Hash]*c
|
||||
|
||||
ddb *doltdb.DoltDB
|
||||
}
|
||||
|
||||
func (q *q) NumVisiblePending() int {
|
||||
@@ -51,8 +50,8 @@ func (q *q) PopPending() *c {
|
||||
return c
|
||||
}
|
||||
|
||||
func (q *q) AddPendingIfUnseen(ctx context.Context, id hash.Hash) error {
|
||||
c, err := q.Get(ctx, id)
|
||||
func (q *q) AddPendingIfUnseen(ctx context.Context, ddb *doltdb.DoltDB, id hash.Hash) error {
|
||||
c, err := q.Get(ctx, ddb, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -90,8 +89,8 @@ func (q *q) AddPendingIfUnseen(ctx context.Context, id hash.Hash) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *q) SetInvisible(ctx context.Context, id hash.Hash) error {
|
||||
c, err := q.Get(ctx, id)
|
||||
func (q *q) SetInvisible(ctx context.Context, ddb *doltdb.DoltDB, id hash.Hash) error {
|
||||
c, err := q.Get(ctx, ddb, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -104,24 +103,24 @@ func (q *q) SetInvisible(ctx context.Context, id hash.Hash) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *q) load(ctx context.Context, h hash.Hash) (*doltdb.Commit, error) {
|
||||
func load(ctx context.Context, ddb *doltdb.DoltDB, h hash.Hash) (*doltdb.Commit, error) {
|
||||
cs, err := doltdb.NewCommitSpec(h.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c, err := q.ddb.Resolve(ctx, cs, nil)
|
||||
c, err := ddb.Resolve(ctx, cs, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (q *q) Get(ctx context.Context, id hash.Hash) (*c, error) {
|
||||
func (q *q) Get(ctx context.Context, ddb *doltdb.DoltDB, id hash.Hash) (*c, error) {
|
||||
if l, ok := q.loaded[id]; ok {
|
||||
return l, nil
|
||||
}
|
||||
|
||||
l, err := q.load(ctx, id)
|
||||
l, err := load(ctx, ddb, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -130,13 +129,13 @@ func (q *q) Get(ctx context.Context, id hash.Hash) (*c, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &c{commit: l, height: h, hash: id}
|
||||
c := &c{ddb: ddb, commit: l, height: h, hash: id}
|
||||
q.loaded[id] = c
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func newQueue(ddb *doltdb.DoltDB) *q {
|
||||
return &q{ddb: ddb, loaded: make(map[hash.Hash]*c)}
|
||||
func newQueue() *q {
|
||||
return &q{loaded: make(map[hash.Hash]*c)}
|
||||
}
|
||||
|
||||
// GetDotDotRevisions returns the commits reachable from commit at hash
|
||||
@@ -148,16 +147,16 @@ func newQueue(ddb *doltdb.DoltDB) *q {
|
||||
// ties are broken by timestamp; newer commits appear first.
|
||||
//
|
||||
// Roughly mimics `git log master..feature`.
|
||||
func GetDotDotRevisions(ctx context.Context, ddb *doltdb.DoltDB, includedHead hash.Hash, excludedHead hash.Hash, num int) ([]*doltdb.Commit, error) {
|
||||
func GetDotDotRevisions(ctx context.Context, includedDB *doltdb.DoltDB, includedHead hash.Hash, excludedDB *doltdb.DoltDB, excludedHead hash.Hash, num int) ([]*doltdb.Commit, error) {
|
||||
commitList := make([]*doltdb.Commit, 0, num)
|
||||
q := newQueue(ddb)
|
||||
if err := q.SetInvisible(ctx, excludedHead); err != nil {
|
||||
q := newQueue()
|
||||
if err := q.SetInvisible(ctx, excludedDB, excludedHead); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := q.AddPendingIfUnseen(ctx, excludedHead); err != nil {
|
||||
if err := q.AddPendingIfUnseen(ctx, excludedDB, excludedHead); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := q.AddPendingIfUnseen(ctx, includedHead); err != nil {
|
||||
if err := q.AddPendingIfUnseen(ctx, includedDB, includedHead); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for q.NumVisiblePending() > 0 {
|
||||
@@ -168,11 +167,11 @@ func GetDotDotRevisions(ctx context.Context, ddb *doltdb.DoltDB, includedHead ha
|
||||
}
|
||||
for _, parentID := range parents {
|
||||
if nextC.invisible {
|
||||
if err := q.SetInvisible(ctx, parentID); err != nil {
|
||||
if err := q.SetInvisible(ctx, nextC.ddb, parentID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := q.AddPendingIfUnseen(ctx, parentID); err != nil {
|
||||
if err := q.AddPendingIfUnseen(ctx, nextC.ddb, parentID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -231,7 +230,7 @@ func (i *commiterator) Next(ctx context.Context) (hash.Hash, *doltdb.Commit, err
|
||||
}
|
||||
|
||||
for _, parentID := range parents {
|
||||
if err := i.q.AddPendingIfUnseen(ctx, parentID); err != nil {
|
||||
if err := i.q.AddPendingIfUnseen(ctx, nextC.ddb, parentID); err != nil {
|
||||
return hash.Hash{}, nil, err
|
||||
}
|
||||
}
|
||||
@@ -244,8 +243,8 @@ func (i *commiterator) Next(ctx context.Context) (hash.Hash, *doltdb.Commit, err
|
||||
|
||||
// Reset implements doltdb.CommitItr
|
||||
func (i *commiterator) Reset(ctx context.Context) error {
|
||||
i.q = newQueue(i.ddb)
|
||||
if err := i.q.AddPendingIfUnseen(ctx, i.startCommitHash); err != nil {
|
||||
i.q = newQueue()
|
||||
if err := i.q.AddPendingIfUnseen(ctx, i.ddb, i.startCommitHash); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/env"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/doltcore/ref"
|
||||
"github.com/liquidata-inc/dolt/go/libraries/utils/filesys"
|
||||
"github.com/liquidata-inc/dolt/go/store/datas"
|
||||
"github.com/liquidata-inc/dolt/go/store/hash"
|
||||
"github.com/liquidata-inc/dolt/go/store/types"
|
||||
)
|
||||
@@ -105,34 +106,97 @@ func TestGetDotDotRevisions(t *testing.T) {
|
||||
masterHash := mustGetHash(t, masterCommits[6])
|
||||
featurePreMergeHash := mustGetHash(t, featureCommits[3])
|
||||
|
||||
res, err := GetDotDotRevisions(context.Background(), env.DoltDB, featureHash, masterHash, 100)
|
||||
res, err := GetDotDotRevisions(context.Background(), env.DoltDB, featureHash, env.DoltDB, masterHash, 100)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res, 7)
|
||||
assert.Equal(t, featureCommits[7], res[0])
|
||||
assert.Equal(t, featureCommits[6], res[1])
|
||||
assert.Equal(t, featureCommits[5], res[2])
|
||||
assert.Equal(t, featureCommits[4], res[3])
|
||||
assert.Equal(t, featureCommits[3], res[4])
|
||||
assert.Equal(t, featureCommits[2], res[5])
|
||||
assert.Equal(t, featureCommits[1], res[6])
|
||||
assertEqualHashes(t, featureCommits[7], res[0])
|
||||
assertEqualHashes(t, featureCommits[6], res[1])
|
||||
assertEqualHashes(t, featureCommits[5], res[2])
|
||||
assertEqualHashes(t, featureCommits[4], res[3])
|
||||
assertEqualHashes(t, featureCommits[3], res[4])
|
||||
assertEqualHashes(t, featureCommits[2], res[5])
|
||||
assertEqualHashes(t, featureCommits[1], res[6])
|
||||
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, masterHash, featureHash, 100)
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, masterHash, env.DoltDB, featureHash, 100)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res, 0)
|
||||
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, featureHash, masterHash, 3)
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, featureHash, env.DoltDB, masterHash, 3)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res, 3)
|
||||
assert.Equal(t, featureCommits[7], res[0])
|
||||
assert.Equal(t, featureCommits[6], res[1])
|
||||
assert.Equal(t, featureCommits[5], res[2])
|
||||
assertEqualHashes(t, featureCommits[7], res[0])
|
||||
assertEqualHashes(t, featureCommits[6], res[1])
|
||||
assertEqualHashes(t, featureCommits[5], res[2])
|
||||
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, featurePreMergeHash, masterHash, 3)
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, featurePreMergeHash, env.DoltDB, masterHash, 3)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res, 3)
|
||||
assert.Equal(t, featureCommits[3], res[0])
|
||||
assert.Equal(t, featureCommits[2], res[1])
|
||||
assert.Equal(t, featureCommits[1], res[2])
|
||||
assertEqualHashes(t, featureCommits[3], res[0])
|
||||
assertEqualHashes(t, featureCommits[2], res[1])
|
||||
assertEqualHashes(t, featureCommits[1], res[2])
|
||||
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, featurePreMergeHash, env.DoltDB, masterHash, 3)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res, 3)
|
||||
assertEqualHashes(t, featureCommits[3], res[0])
|
||||
assertEqualHashes(t, featureCommits[2], res[1])
|
||||
assertEqualHashes(t, featureCommits[1], res[2])
|
||||
|
||||
// Create a similar branch to "feature" on a forked repository and GetDotDotRevisions using that as well.
|
||||
forkEnv := mustForkDB(t, env.DoltDB, "feature", featureCommits[4])
|
||||
|
||||
// Create 3 commits on feature branch.
|
||||
for i := 5; i < 8; i++ {
|
||||
featureCommits[i] = mustCreateCommit(t, forkEnv.DoltDB, "feature", rvh, featureCommits[i-1])
|
||||
}
|
||||
|
||||
featureHash = mustGetHash(t, featureCommits[7])
|
||||
masterHash = mustGetHash(t, masterCommits[6])
|
||||
featurePreMergeHash = mustGetHash(t, featureCommits[3])
|
||||
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, featureHash, env.DoltDB, masterHash, 100)
|
||||
require.Error(t, err)
|
||||
res, err = GetDotDotRevisions(context.Background(), forkEnv.DoltDB, featureHash, env.DoltDB, masterHash, 100)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res, 7)
|
||||
assertEqualHashes(t, featureCommits[7], res[0])
|
||||
assertEqualHashes(t, featureCommits[6], res[1])
|
||||
assertEqualHashes(t, featureCommits[5], res[2])
|
||||
assertEqualHashes(t, featureCommits[4], res[3])
|
||||
assertEqualHashes(t, featureCommits[3], res[4])
|
||||
assertEqualHashes(t, featureCommits[2], res[5])
|
||||
assertEqualHashes(t, featureCommits[1], res[6])
|
||||
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, masterHash, env.DoltDB, featureHash, 100)
|
||||
require.Error(t, err)
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, masterHash, forkEnv.DoltDB, featureHash, 100)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res, 0)
|
||||
|
||||
res, err = GetDotDotRevisions(context.Background(), forkEnv.DoltDB, featureHash, env.DoltDB, masterHash, 3)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res, 3)
|
||||
assertEqualHashes(t, featureCommits[7], res[0])
|
||||
assertEqualHashes(t, featureCommits[6], res[1])
|
||||
assertEqualHashes(t, featureCommits[5], res[2])
|
||||
|
||||
res, err = GetDotDotRevisions(context.Background(), env.DoltDB, featurePreMergeHash, env.DoltDB, masterHash, 3)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res, 3)
|
||||
assertEqualHashes(t, featureCommits[3], res[0])
|
||||
assertEqualHashes(t, featureCommits[2], res[1])
|
||||
assertEqualHashes(t, featureCommits[1], res[2])
|
||||
|
||||
res, err = GetDotDotRevisions(context.Background(), forkEnv.DoltDB, featurePreMergeHash, env.DoltDB, masterHash, 3)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, res, 3)
|
||||
assertEqualHashes(t, featureCommits[3], res[0])
|
||||
assertEqualHashes(t, featureCommits[2], res[1])
|
||||
assertEqualHashes(t, featureCommits[1], res[2])
|
||||
}
|
||||
|
||||
func assertEqualHashes(t *testing.T, lc, rc *doltdb.Commit) {
|
||||
assert.Equal(t, mustGetHash(t, lc), mustGetHash(t, rc))
|
||||
}
|
||||
|
||||
func mustCreateCommit(t *testing.T, ddb *doltdb.DoltDB, bn string, rvh hash.Hash, parents ...*doltdb.Commit) *doltdb.Commit {
|
||||
@@ -150,6 +214,29 @@ func mustCreateCommit(t *testing.T, ddb *doltdb.DoltDB, bn string, rvh hash.Hash
|
||||
return commit
|
||||
}
|
||||
|
||||
func mustForkDB(t *testing.T, fromDB *doltdb.DoltDB, bn string, cm *doltdb.Commit) *env.DoltEnv {
|
||||
stref, err := cm.GetStRef()
|
||||
require.NoError(t, err)
|
||||
forkEnv := createUninitializedEnv()
|
||||
err = forkEnv.InitRepo(context.Background(), types.Format_LD_1, "Bill Billerson", "bill@billerson.com")
|
||||
require.NoError(t, err)
|
||||
p1 := make(chan datas.PullProgress)
|
||||
p2 := make(chan datas.PullerEvent)
|
||||
go func() {
|
||||
for range p1 {
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for range p2 {
|
||||
}
|
||||
}()
|
||||
err = forkEnv.DoltDB.PullChunks(context.Background(), "", fromDB, stref, p1, p2)
|
||||
require.NoError(t, err)
|
||||
err = forkEnv.DoltDB.SetHead(context.Background(), ref.NewBranchRef(bn), stref)
|
||||
require.NoError(t, err)
|
||||
return forkEnv
|
||||
}
|
||||
|
||||
func mustGetHash(t *testing.T, c *doltdb.Commit) hash.Hash {
|
||||
h, err := c.HashOf()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -192,7 +192,7 @@ func getMergeCandidates(ctx context.Context, db datas.Database, leftDS, rightDS
|
||||
}
|
||||
|
||||
func getCommonAncestor(ctx context.Context, r1, r2 types.Ref, vr types.ValueReader) (a types.Struct, found bool) {
|
||||
aRef, found, err := datas.FindCommonAncestor(ctx, r1, r2, vr)
|
||||
aRef, found, err := datas.FindCommonAncestor(ctx, r1, r2, vr, vr)
|
||||
d.PanicIfError(err)
|
||||
if !found {
|
||||
return
|
||||
|
||||
@@ -23,6 +23,7 @@ package datas
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/liquidata-inc/dolt/go/store/d"
|
||||
@@ -76,8 +77,9 @@ func NewCommit(ctx context.Context, value types.Value, parentsList types.List, m
|
||||
|
||||
// FindCommonAncestor returns the most recent common ancestor of c1 and c2, if
|
||||
// one exists, setting ok to true. If there is no common ancestor, ok is set
|
||||
// to false.
|
||||
func FindCommonAncestor(ctx context.Context, c1, c2 types.Ref, vr types.ValueReader) (a types.Ref, ok bool, err error) {
|
||||
// to false. Refs of |c1| are dereferenced through |vr1|, while refs of |c2|
|
||||
// are dereference through |vr2|.
|
||||
func FindCommonAncestor(ctx context.Context, c1, c2 types.Ref, vr1, vr2 types.ValueReader) (a types.Ref, ok bool, err error) {
|
||||
t1, err := types.TypeOf(c1)
|
||||
|
||||
if err != nil {
|
||||
@@ -107,12 +109,24 @@ func FindCommonAncestor(ctx context.Context, c1, c2 types.Ref, vr types.ValueRea
|
||||
if common, ok := findCommonRef(c1Parents, c2Parents); ok {
|
||||
return common, true, nil
|
||||
}
|
||||
parentsToQueue(ctx, c1Parents, c1Q, vr)
|
||||
parentsToQueue(ctx, c2Parents, c2Q, vr)
|
||||
err = parentsToQueue(ctx, c1Parents, c1Q, vr1)
|
||||
if err != nil {
|
||||
return types.Ref{}, false, err
|
||||
}
|
||||
err = parentsToQueue(ctx, c2Parents, c2Q, vr2)
|
||||
if err != nil {
|
||||
return types.Ref{}, false, err
|
||||
}
|
||||
} else if c1Ht > c2Ht {
|
||||
parentsToQueue(ctx, c1Q.PopRefsOfHeight(c1Ht), c1Q, vr)
|
||||
err = parentsToQueue(ctx, c1Q.PopRefsOfHeight(c1Ht), c1Q, vr1)
|
||||
if err != nil {
|
||||
return types.Ref{}, false, err
|
||||
}
|
||||
} else {
|
||||
parentsToQueue(ctx, c2Q.PopRefsOfHeight(c2Ht), c2Q, vr)
|
||||
err = parentsToQueue(ctx, c2Q.PopRefsOfHeight(c2Ht), c2Q, vr2)
|
||||
if err != nil {
|
||||
return types.Ref{}, false, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,24 +142,39 @@ func parentsToQueue(ctx context.Context, refs types.RefSlice, q *types.RefByHeig
|
||||
seen[r.TargetHash()] = true
|
||||
|
||||
v, err := r.TargetValue(ctx, vr)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v == nil {
|
||||
return fmt.Errorf("target not found: %v", r.TargetHash())
|
||||
}
|
||||
|
||||
c := v.(types.Struct)
|
||||
ps, ok, err := c.MaybeGet(ParentsField)
|
||||
|
||||
c, ok := v.(types.Struct)
|
||||
if !ok {
|
||||
return fmt.Errorf("target ref is not struct: %v", v)
|
||||
}
|
||||
ps, ok, err := c.MaybeGet(ParentsListField)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ok {
|
||||
p := ps.(types.Set)
|
||||
err = p.IterAll(ctx, func(v types.Value) error {
|
||||
p := ps.(types.List)
|
||||
err = p.IterAll(ctx, func(v types.Value, _ uint64) error {
|
||||
q.PushBack(v.(types.Ref))
|
||||
return nil
|
||||
})
|
||||
} else {
|
||||
ps, ok, err := c.MaybeGet(ParentsField)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok {
|
||||
p := ps.(types.Set)
|
||||
err = p.IterAll(ctx, func(v types.Value) error {
|
||||
q.PushBack(v.(types.Ref))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -243,12 +243,9 @@ func toRefList(vrw types.ValueReadWriter, commits ...types.Struct) (types.List,
|
||||
|
||||
func TestFindCommonAncestor(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
storage := &chunks.TestStorage{}
|
||||
db := NewDatabase(storage.NewView())
|
||||
defer db.Close()
|
||||
|
||||
// Add a commit and return it
|
||||
addCommit := func(datasetID string, val string, parents ...types.Struct) types.Struct {
|
||||
addCommit := func(db Database, datasetID string, val string, parents ...types.Struct) types.Struct {
|
||||
ds, err := db.GetDataset(context.Background(), datasetID)
|
||||
assert.NoError(err)
|
||||
ds, err = db.Commit(context.Background(), ds, types.String(val), CommitOptions{ParentsList: mustList(toRefList(db, parents...))})
|
||||
@@ -257,12 +254,12 @@ func TestFindCommonAncestor(t *testing.T) {
|
||||
}
|
||||
|
||||
// Assert that c is the common ancestor of a and b
|
||||
assertCommonAncestor := func(expected, a, b types.Struct) {
|
||||
found, ok, err := FindCommonAncestor(context.Background(), mustRef(types.NewRef(a, types.Format_7_18)), mustRef(types.NewRef(b, types.Format_7_18)), db)
|
||||
assertCommonAncestor := func(expected, a, b types.Struct, ldb, rdb Database) {
|
||||
found, ok, err := FindCommonAncestor(context.Background(), mustRef(types.NewRef(a, types.Format_7_18)), mustRef(types.NewRef(b, types.Format_7_18)), ldb, rdb)
|
||||
assert.NoError(err)
|
||||
|
||||
if assert.True(ok) {
|
||||
tv, err := found.TargetValue(context.Background(), db)
|
||||
tv, err := found.TargetValue(context.Background(), ldb)
|
||||
assert.NoError(err)
|
||||
ancestor := tv.(types.Struct)
|
||||
expV, _, _ := expected.MaybeGet(ValueField)
|
||||
@@ -280,6 +277,9 @@ func TestFindCommonAncestor(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
storage := &chunks.TestStorage{}
|
||||
db := NewDatabase(storage.NewView())
|
||||
|
||||
// Build commit DAG
|
||||
//
|
||||
// ds-a: a1<-a2<-a3<-a4<-a5<-a6
|
||||
@@ -296,28 +296,28 @@ func TestFindCommonAncestor(t *testing.T) {
|
||||
// ds-d: d1<-d2
|
||||
//
|
||||
a, b, c, d := "ds-a", "ds-b", "ds-c", "ds-d"
|
||||
a1 := addCommit(a, "a1")
|
||||
d1 := addCommit(d, "d1")
|
||||
a2 := addCommit(a, "a2", a1)
|
||||
c2 := addCommit(c, "c2", a1)
|
||||
d2 := addCommit(d, "d2", d1)
|
||||
a3 := addCommit(a, "a3", a2)
|
||||
b3 := addCommit(b, "b3", a2)
|
||||
c3 := addCommit(c, "c3", c2, d2)
|
||||
a4 := addCommit(a, "a4", a3)
|
||||
b4 := addCommit(b, "b4", b3)
|
||||
a5 := addCommit(a, "a5", a4)
|
||||
b5 := addCommit(b, "b5", b4, a3)
|
||||
a6 := addCommit(a, "a6", a5, b5)
|
||||
a1 := addCommit(db, a, "a1")
|
||||
d1 := addCommit(db, d, "d1")
|
||||
a2 := addCommit(db, a, "a2", a1)
|
||||
c2 := addCommit(db, c, "c2", a1)
|
||||
d2 := addCommit(db, d, "d2", d1)
|
||||
a3 := addCommit(db, a, "a3", a2)
|
||||
b3 := addCommit(db, b, "b3", a2)
|
||||
c3 := addCommit(db, c, "c3", c2, d2)
|
||||
a4 := addCommit(db, a, "a4", a3)
|
||||
b4 := addCommit(db, b, "b4", b3)
|
||||
a5 := addCommit(db, a, "a5", a4)
|
||||
b5 := addCommit(db, b, "b5", b4, a3)
|
||||
a6 := addCommit(db, a, "a6", a5, b5)
|
||||
|
||||
assertCommonAncestor(a1, a1, a1) // All self
|
||||
assertCommonAncestor(a1, a1, a2) // One side self
|
||||
assertCommonAncestor(a2, a3, b3) // Common parent
|
||||
assertCommonAncestor(a2, a4, b4) // Common grandparent
|
||||
assertCommonAncestor(a1, a6, c3) // Traversing multiple parents on both sides
|
||||
assertCommonAncestor(a1, a1, a1, db, db) // All self
|
||||
assertCommonAncestor(a1, a1, a2, db, db) // One side self
|
||||
assertCommonAncestor(a2, a3, b3, db, db) // Common parent
|
||||
assertCommonAncestor(a2, a4, b4, db, db) // Common grandparent
|
||||
assertCommonAncestor(a1, a6, c3, db, db) // Traversing multiple parents on both sides
|
||||
|
||||
// No common ancestor
|
||||
found, ok, err := FindCommonAncestor(context.Background(), mustRef(types.NewRef(d2, types.Format_7_18)), mustRef(types.NewRef(a6, types.Format_7_18)), db)
|
||||
found, ok, err := FindCommonAncestor(context.Background(), mustRef(types.NewRef(d2, types.Format_7_18)), mustRef(types.NewRef(a6, types.Format_7_18)), db, db)
|
||||
assert.NoError(err)
|
||||
|
||||
if !assert.False(ok) {
|
||||
@@ -334,6 +334,68 @@ func TestFindCommonAncestor(t *testing.T) {
|
||||
fV,
|
||||
)
|
||||
}
|
||||
|
||||
assert.NoError(db.Close())
|
||||
|
||||
storage = &chunks.TestStorage{}
|
||||
db = NewDatabase(storage.NewView())
|
||||
defer db.Close()
|
||||
|
||||
rstorage := &chunks.TestStorage{}
|
||||
rdb := NewDatabase(rstorage.NewView())
|
||||
defer rdb.Close()
|
||||
|
||||
// Rerun the tests when using two difference Databases for left and
|
||||
// right commits. Both databases have all the previous commits.
|
||||
a, b, c, d = "ds-a", "ds-b", "ds-c", "ds-d"
|
||||
a1 = addCommit(db, a, "a1")
|
||||
d1 = addCommit(db, d, "d1")
|
||||
a2 = addCommit(db, a, "a2", a1)
|
||||
c2 = addCommit(db, c, "c2", a1)
|
||||
d2 = addCommit(db, d, "d2", d1)
|
||||
a3 = addCommit(db, a, "a3", a2)
|
||||
b3 = addCommit(db, b, "b3", a2)
|
||||
c3 = addCommit(db, c, "c3", c2, d2)
|
||||
a4 = addCommit(db, a, "a4", a3)
|
||||
b4 = addCommit(db, b, "b4", b3)
|
||||
a5 = addCommit(db, a, "a5", a4)
|
||||
b5 = addCommit(db, b, "b5", b4, a3)
|
||||
a6 = addCommit(db, a, "a6", a5, b5)
|
||||
|
||||
addCommit(rdb, a, "a1")
|
||||
addCommit(rdb, d, "d1")
|
||||
addCommit(rdb, a, "a2", a1)
|
||||
addCommit(rdb, c, "c2", a1)
|
||||
addCommit(rdb, d, "d2", d1)
|
||||
addCommit(rdb, a, "a3", a2)
|
||||
addCommit(rdb, b, "b3", a2)
|
||||
addCommit(rdb, c, "c3", c2, d2)
|
||||
addCommit(rdb, a, "a4", a3)
|
||||
addCommit(rdb, b, "b4", b3)
|
||||
addCommit(rdb, a, "a5", a4)
|
||||
addCommit(rdb, b, "b5", b4, a3)
|
||||
addCommit(rdb, a, "a6", a5, b5)
|
||||
|
||||
// Additionally, |db| has a6<-a7<-a8<-a9.
|
||||
// |rdb| has a6<-ra7<-ra8<-ra9.
|
||||
a7 := addCommit(db, a, "a7", a6)
|
||||
a8 := addCommit(db, a, "a8", a7)
|
||||
a9 := addCommit(db, a, "a9", a8)
|
||||
|
||||
ra7 := addCommit(rdb, a, "ra7", a6)
|
||||
ra8 := addCommit(rdb, a, "ra8", ra7)
|
||||
ra9 := addCommit(rdb, a, "ra9", ra8)
|
||||
|
||||
assertCommonAncestor(a1, a1, a1, db, rdb) // All self
|
||||
assertCommonAncestor(a1, a1, a2, db, rdb) // One side self
|
||||
assertCommonAncestor(a2, a3, b3, db, rdb) // Common parent
|
||||
assertCommonAncestor(a2, a4, b4, db, rdb) // Common grandparent
|
||||
assertCommonAncestor(a1, a6, c3, db, rdb) // Traversing multiple parents on both sides
|
||||
|
||||
assertCommonAncestor(a6, a9, ra9, db, rdb) // Common third parent
|
||||
|
||||
_, _, err = FindCommonAncestor(context.Background(), mustRef(types.NewRef(a9, types.Format_7_18)), mustRef(types.NewRef(ra9, types.Format_7_18)), rdb, db)
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
func TestNewCommitRegressionTest(t *testing.T) {
|
||||
|
||||
@@ -361,7 +361,7 @@ func (db *database) doCommit(ctx context.Context, datasetID string, commit types
|
||||
return err
|
||||
}
|
||||
|
||||
ancestorRef, found, err := FindCommonAncestor(ctx, commitRef, currentHeadRef, db)
|
||||
ancestorRef, found, err := FindCommonAncestor(ctx, commitRef, currentHeadRef, db, db)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user