diff --git a/go/libraries/doltcore/sqle/read_replica_database.go b/go/libraries/doltcore/sqle/read_replica_database.go index 22323d94ea2..fba8ca14cd4 100644 --- a/go/libraries/doltcore/sqle/read_replica_database.go +++ b/go/libraries/doltcore/sqle/read_replica_database.go @@ -275,7 +275,7 @@ type pullBehavior bool const pullBehaviorFastForward pullBehavior = false const pullBehaviorForcePull pullBehavior = true -// pullBranches pulls the remote branches named and returns the map of their hashes keyed by branch path. +// pullBranches pulls the named remote branches and tags and returns the map of their hashes keyed by ref ID. func pullBranches( ctx *sql.Context, rrd ReadReplicaDatabase, @@ -283,17 +283,17 @@ func pullBranches( localRefs []doltdb.RefWithHash, behavior pullBehavior, ) (map[string]doltdb.RefWithHash, error) { - localRefsByPath := make(map[string]doltdb.RefWithHash) - remoteRefsByPath := make(map[string]doltdb.RefWithHash) + localRefsById := make(map[string]doltdb.RefWithHash) + remoteRefsById := make(map[string]doltdb.RefWithHash) remoteHashes := make([]hash.Hash, len(remoteRefs)) for i, b := range remoteRefs { - remoteRefsByPath[b.Ref.GetPath()] = b + remoteRefsById[b.Ref.String()] = b remoteHashes[i] = b.Hash } for _, b := range localRefs { - localRefsByPath[b.Ref.GetPath()] = b + localRefsById[b.Ref.String()] = b } // XXX: Our view of which remote branches to pull and what to set the @@ -311,7 +311,7 @@ func pullBranches( REFS: // every successful pass through the loop below must end with `continue REFS` to get out of the retry loop for _, remoteRef := range remoteRefs { trackingRef := ref.NewRemoteRef(rrd.remote.Name, remoteRef.Ref.GetPath()) - localRef, localRefExists := localRefsByPath[remoteRef.Ref.GetPath()] + localRef, localRefExists := localRefsById[remoteRef.Ref.String()] // loop on optimistic lock failures OPTIMISTIC_RETRY: @@ -378,7 +378,7 @@ func pullBranches( return nil, err } - return remoteRefsByPath, nil + return remoteRefsById, nil } // expandWildcardBranchPattern evaluates |pattern| and returns a list of branch names from the source database that diff --git a/integration-tests/bats/replication.bats b/integration-tests/bats/replication.bats index e6d80c8e94b..460ebdc3f62 100644 --- a/integration-tests/bats/replication.bats +++ b/integration-tests/bats/replication.bats @@ -163,6 +163,44 @@ teardown() { [[ ! "$output" =~ "feature" ]] || false } +# Asserts that when a branch is deleted and a tag is created and they have the same name, +# the replica is able to correctly apply both changes. +@test "replication: pull branch delete and tag create with same name on read" { + # Configure repo1 to push changes on commit and create branch b1 + cd repo1 + dolt config --local --add sqlserver.global.dolt_replicate_to_remote remote1 + dolt sql -q "call dolt_branch('b1');" + + # Configure repo2 to pull changes on read and assert the b1 branch exists + cd .. + dolt clone file://./rem1 repo2 + cd repo2 + dolt config --local --add sqlserver.global.dolt_read_replica_remote origin + dolt config --local --add sqlserver.global.dolt_replicate_all_heads 1 + run dolt sql -q "select name from dolt_branches" -r csv + [ "$status" -eq 0 ] + [ "${#lines[@]}" -eq 3 ] + [[ "$output" =~ "name" ]] || false + [[ "$output" =~ "main" ]] || false + [[ "$output" =~ "b1" ]] || false + + # Delete branch b1 in repo1 and create tag b1 + cd ../repo1 + dolt sql -q "call dolt_branch('-D', 'b1'); call dolt_tag('b1');" + + # Confirm that branch b1 is deleted and tag b1 is created in repo2 + cd ../repo2 + run dolt sql -q "select name from dolt_branches" -r csv + [ "$status" -eq 0 ] + [ "${#lines[@]}" -eq 2 ] + [[ "$output" =~ "main" ]] || false + run dolt sql -q "select tag_name from dolt_tags" -r csv + [ "$status" -eq 0 ] + [ "${#lines[@]}" -eq 2 ] + [[ "$output" =~ "tag_name" ]] || false + [[ "$output" =~ "b1" ]] || false +} + @test "replication: pull branch delete current branch" { skip "broken by latest transaction changes"