fix inconsistencies of dolt checkout and pull commands (#3725)

This commit is contained in:
jennifersp
2022-07-05 09:19:53 -07:00
committed by GitHub
parent 43c3d8d068
commit 6229f6acb3
13 changed files with 433 additions and 139 deletions

View File

@@ -16,6 +16,9 @@ package commands
import (
"context"
"fmt"
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
"github.com/dolthub/dolt/go/cmd/dolt/cli"
"github.com/dolthub/dolt/go/cmd/dolt/errhand"
@@ -141,12 +144,15 @@ func (cmd CheckoutCmd) Exec(ctx context.Context, commandStr string, args []strin
return HandleVErrAndExitCode(verr, usagePrt)
}
// checkoutRemoteBranchOrSuggestNew checks out a new branch guessing the remote branch,
// if there is a branch with matching name from exactly one remote.
func checkoutRemoteBranchOrSuggestNew(ctx context.Context, dEnv *env.DoltEnv, name string) errhand.VerboseError {
if ref, refExists, err := actions.GetRemoteBranchRef(ctx, dEnv.DoltDB, name); err != nil {
remoteRefs, err := actions.GetRemoteBranchRef(ctx, dEnv.DoltDB, name)
if err != nil {
return errhand.BuildDError("fatal: unable to read from data repository.").AddCause(err).Build()
} else if refExists {
return checkoutNewBranchFromStartPt(ctx, dEnv, name, ref.String())
} else {
}
if len(remoteRefs) == 0 {
// Check if the user is trying to enter a detached head state
commit, _ := actions.MaybeGetCommit(ctx, dEnv, name)
if commit != nil {
@@ -159,6 +165,15 @@ func checkoutRemoteBranchOrSuggestNew(ctx context.Context, dEnv *env.DoltEnv, na
return errhand.BuildDError(str, name).Build()
}
return errhand.BuildDError("error: could not find %s", name).Build()
} else if len(remoteRefs) == 1 {
verr := checkoutNewBranchFromStartPt(ctx, dEnv, name, remoteRefs[0].String())
if verr == nil {
verr = setRemoteUpstreamForCheckout(dEnv, remoteRefs[0])
}
return verr
} else {
// TODO : add hint of using `dolt checkout --track <remote>/<branch>` when --track flag is supported
return errhand.BuildDError("'%s' matched multiple (%v) remote tracking branches", name, len(remoteRefs)).Build()
}
}
@@ -235,7 +250,7 @@ func checkoutBranch(ctx context.Context, dEnv *env.DoltEnv, name string, force b
return bdr.Build()
} else if err == doltdb.ErrAlreadyOnBranch {
// Being on the same branch shouldn't be an error
cli.Printf("Already on branch '%s'", name)
cli.Printf("Already on branch '%s'\n", name)
return nil
} else {
bdr := errhand.BuildDError("fatal: Unexpected error checking out branch '%s'", name)
@@ -249,6 +264,35 @@ func checkoutBranch(ctx context.Context, dEnv *env.DoltEnv, name string, force b
return nil
}
// setRemoteUpstreamForCheckout sets upstream for checked out branch. This applies `dolt checkout <bn>`,
// if <bn> matches any remote branch name. This should not happen for `dolt checkout -b <bn>` case.
func setRemoteUpstreamForCheckout(dEnv *env.DoltEnv, branchRef ref.RemoteRef) errhand.VerboseError {
refSpec, err := ref.ParseRefSpecForRemote(branchRef.GetRemote(), branchRef.GetBranch())
if err != nil {
return errhand.BuildDError(fmt.Errorf("%w: '%s'", err, branchRef.GetRemote()).Error()).Build()
}
src := refSpec.SrcRef(dEnv.RepoStateReader().CWBHeadRef())
dest := refSpec.DestRef(src)
err = dEnv.RepoStateWriter().UpdateBranch(src.GetPath(), env.BranchConfig{
Merge: ref.MarshalableRef{
Ref: dest,
},
Remote: branchRef.GetRemote(),
})
if err != nil {
return errhand.BuildDError(err.Error()).Build()
}
err = dEnv.RepoState.Save(dEnv.FS)
if err != nil {
return errhand.BuildDError(actions.ErrFailedToSaveRepoState.Error()).AddCause(err).Build()
}
cli.Printf("branch '%s' set up to track '%s'.\n", src.GetPath(), branchRef.GetPath())
return nil
}
func unreadableRootToVErr(err error) errhand.VerboseError {
rt := doltdb.GetUnreachableRootType(err)
bdr := errhand.BuildDError("error: unable to read the %s", rt.String())

View File

@@ -85,7 +85,7 @@ func (cmd PullCmd) Exec(ctx context.Context, commandStr string, args []string, d
remoteName = apr.Arg(0)
}
pullSpec, err := env.NewPullSpec(ctx, dEnv.RepoStateReader(), remoteName, apr.Contains(cli.SquashParam), apr.Contains(cli.NoFFParam), apr.Contains(cli.ForceFlag))
pullSpec, err := env.NewPullSpec(ctx, dEnv.RepoStateReader(), remoteName, apr.Contains(cli.SquashParam), apr.Contains(cli.NoFFParam), apr.Contains(cli.ForceFlag), apr.NArg() == 1)
if err != nil {
return HandleVErrAndExitCode(errhand.VerboseErrorFromError(err), usage)
}
@@ -130,6 +130,11 @@ func pullHelper(ctx context.Context, dEnv *env.DoltEnv, pullSpec *env.PullSpec)
return fmt.Errorf("fetch failed; %w", err)
}
// Only merge iff branch is current branch and there is an upstream set (pullSpec.Branch is set to nil if there is no upstream)
if branchRef != pullSpec.Branch {
continue
}
t := datas.CommitNowFunc()
roots, err := dEnv.Roots(ctx)
@@ -147,11 +152,6 @@ func pullHelper(ctx context.Context, dEnv *env.DoltEnv, pullSpec *env.PullSpec)
name, email = "", ""
}
// Only merge iff branch is current branch
if branchRef != pullSpec.Branch {
continue
}
// Begin merge
mergeSpec, ok, err := merge.NewMergeSpec(ctx, dEnv.RepoStateReader(), dEnv.DoltDB, roots, name, email, pullSpec.Msg, remoteTrackRef.String(), pullSpec.Squash, pullSpec.Noff, pullSpec.Force, t)
if err != nil {

View File

@@ -131,21 +131,20 @@ func RemoveDocsTable(tbls []string) []string {
return result
}
// GetRemoteBranchRef returns the ref of a branch and ensures it matched with name. It will also return boolean value
// representing whether there is not match or not and an error if there is one.
func GetRemoteBranchRef(ctx context.Context, ddb *doltdb.DoltDB, name string) (ref.DoltRef, bool, error) {
// GetRemoteBranchRef returns a remote ref with matching name for a branch for each remotes.
func GetRemoteBranchRef(ctx context.Context, ddb *doltdb.DoltDB, name string) ([]ref.RemoteRef, error) {
remoteRefFilter := map[ref.RefType]struct{}{ref.RemoteRefType: {}}
refs, err := ddb.GetRefsOfType(ctx, remoteRefFilter)
if err != nil {
return nil, false, err
return nil, err
}
var remoteRef []ref.RemoteRef
for _, rf := range refs {
if remRef, ok := rf.(ref.RemoteRef); ok && remRef.GetBranch() == name {
return rf, true, nil
remoteRef = append(remoteRef, remRef)
}
}
return nil, false, nil
return remoteRef, nil
}

View File

@@ -45,6 +45,8 @@ var ErrCannotPushRef = errors.New("cannot push ref")
var ErrNoRefSpecForRemote = errors.New("no refspec for remote")
var ErrInvalidSetUpstreamArgs = errors.New("invalid set-upstream arguments")
var ErrInvalidFetchSpec = errors.New("invalid fetch spec")
var ErrPullWithRemoteNoUpstream = errors.New("You asked to pull from the remote '%s', but did not specify a branch. Because this is not the default configured remote for your current branch, you must specify a branch on the command line.")
var ErrPullWithNoRemoteAndNoUpstream = errors.New("There is no tracking information for the current branch.\nPlease specify which branch you want to merge with.\n\n\tdolt pull <remote> <branch>\n\nIf you wish to set tracking information for this branch you can do so with:\n\n\t dolt push --set-upstream <remote> <branch>\n")
func IsEmptyRemote(r Remote) bool {
return len(r.Name) == 0 && len(r.Url) == 0 && r.FetchSpecs == nil && r.Params == nil
@@ -360,7 +362,7 @@ type PullSpec struct {
Branch ref.DoltRef
}
func NewPullSpec(ctx context.Context, rsr RepoStateReader, remoteName string, squash, noff, force bool) (*PullSpec, error) {
func NewPullSpec(ctx context.Context, rsr RepoStateReader, remoteName string, squash, noff, force, remoteOnly bool) (*PullSpec, error) {
branch := rsr.CWBHeadRef()
refSpecs, err := GetRefSpecs(rsr, remoteName)
@@ -372,6 +374,19 @@ func NewPullSpec(ctx context.Context, rsr RepoStateReader, remoteName string, sq
return nil, ErrNoRefSpecForRemote
}
trackedBranches, err := rsr.GetBranches()
if err != nil {
return nil, err
}
if _, hasUpstream := trackedBranches[branch.GetPath()]; !hasUpstream {
if remoteOnly {
return nil, fmt.Errorf(ErrPullWithRemoteNoUpstream.Error(), remoteName)
} else {
return nil, ErrPullWithNoRemoteAndNoUpstream
}
}
remotes, err := rsr.GetRemotes()
if err != nil {
return nil, err

View File

@@ -23,6 +23,7 @@ import (
"github.com/dolthub/go-mysql-server/sql/expression"
"github.com/dolthub/dolt/go/cmd/dolt/cli"
"github.com/dolthub/dolt/go/cmd/dolt/errhand"
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
"github.com/dolthub/dolt/go/libraries/doltcore/env"
"github.com/dolthub/dolt/go/libraries/doltcore/env/actions"
@@ -92,6 +93,9 @@ func DoDoltCheckout(ctx *sql.Context, args []string) (int, error) {
}
name := apr.Arg(0)
if len(name) == 0 {
return 1, ErrEmptyBranchName
}
// Check if user wants to checkout branch.
if isBranch, err := actions.IsBranch(ctx, dbData.Ddb, name); err != nil {
@@ -117,16 +121,38 @@ func DoDoltCheckout(ctx *sql.Context, args []string) (int, error) {
}
func checkoutRemoteBranch(ctx *sql.Context, dbName string, dbData env.DbData, roots doltdb.Roots, branchName string) error {
if len(branchName) == 0 {
return ErrEmptyBranchName
remoteRefs, err := actions.GetRemoteBranchRef(ctx, dbData.Ddb, branchName)
if err != nil {
return errors.New("fatal: unable to read from data repository")
}
if ref, refExists, err := actions.GetRemoteBranchRef(ctx, dbData.Ddb, branchName); err != nil {
return errors.New("fatal: unable to read from data repository")
} else if refExists {
return checkoutNewBranch(ctx, dbName, dbData, roots, branchName, ref.String())
} else {
if len(remoteRefs) == 0 {
return fmt.Errorf("error: could not find %s", branchName)
} else if len(remoteRefs) == 1 {
remoteRef := remoteRefs[0]
err = checkoutNewBranch(ctx, dbName, dbData, roots, branchName, remoteRef.String())
if err != nil {
return err
}
refSpec, err := ref.ParseRefSpecForRemote(remoteRef.GetRemote(), remoteRef.GetBranch())
if err != nil {
return errhand.BuildDError(fmt.Errorf("%w: '%s'", err, remoteRef.GetRemote()).Error()).Build()
}
src := refSpec.SrcRef(dbData.Rsr.CWBHeadRef())
dest := refSpec.DestRef(src)
err = dbData.Rsw.UpdateBranch(src.GetPath(), env.BranchConfig{
Merge: ref.MarshalableRef{
Ref: dest,
},
Remote: remoteRef.GetRemote(),
})
// TODO : set upstream should be persisted outside of session
return err
} else {
return fmt.Errorf("'%s' matched multiple (%v) remote tracking branches", branchName, len(remoteRefs))
}
}
@@ -148,9 +174,6 @@ func checkoutNewBranch(ctx *sql.Context, dbName string, dbData env.DbData, roots
}
func checkoutBranch(ctx *sql.Context, dbName string, roots doltdb.Roots, dbData env.DbData, branchName string) error {
if len(branchName) == 0 {
return ErrEmptyBranchName
}
wsRef, err := ref.WorkingSetRefForHead(ref.NewBranchRef(branchName))
if err != nil {
return err

View File

@@ -28,6 +28,7 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
"github.com/dolthub/dolt/go/libraries/doltcore/env"
"github.com/dolthub/dolt/go/libraries/doltcore/env/actions"
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
"github.com/dolthub/dolt/go/store/datas/pull"
)
@@ -100,7 +101,7 @@ func DoDoltPull(ctx *sql.Context, args []string) (int, int, error) {
remoteName = apr.Arg(0)
}
pullSpec, err := env.NewPullSpec(ctx, dbData.Rsr, remoteName, apr.Contains(cli.SquashParam), apr.Contains(cli.NoFFParam), apr.Contains(cli.ForceFlag))
pullSpec, err := env.NewPullSpec(ctx, dbData.Rsr, remoteName, apr.Contains(cli.SquashParam), apr.Contains(cli.NoFFParam), apr.Contains(cli.ForceFlag), apr.NArg() == 1)
if err != nil {
return noConflictsOrViolations, threeWayMerge, err
}
@@ -115,15 +116,26 @@ func DoDoltPull(ctx *sql.Context, args []string) (int, int, error) {
return noConflictsOrViolations, threeWayMerge, err
}
// Fetch all references
branchRefs, err := srcDB.GetHeadRefs(ctx)
if err != nil {
return noConflictsOrViolations, threeWayMerge, env.ErrFailedToReadDb
}
var conflicts int
var fastForward int
for _, refSpec := range pullSpec.RefSpecs {
remoteTrackRef := refSpec.DestRef(pullSpec.Branch)
rsSeen := false // track invalid refSpecs
for _, branchRef := range branchRefs {
remoteTrackRef := refSpec.DestRef(branchRef)
if remoteTrackRef != nil {
if remoteTrackRef == nil {
continue
}
rsSeen = true
// todo: can we pass nil for either of the channels?
srcDBCommit, err := actions.FetchRemoteBranch(ctx, dbData.Rsw.TempTableFilesDir(), pullSpec.Remote, srcDB, dbData.Ddb, pullSpec.Branch, runProgFuncs, stopProgFuncs)
srcDBCommit, err := actions.FetchRemoteBranch(ctx, dbData.Rsw.TempTableFilesDir(), pullSpec.Remote, srcDB, dbData.Ddb, branchRef, runProgFuncs, stopProgFuncs)
if err != nil {
return noConflictsOrViolations, threeWayMerge, err
}
@@ -134,6 +146,11 @@ func DoDoltPull(ctx *sql.Context, args []string) (int, int, error) {
return noConflictsOrViolations, threeWayMerge, fmt.Errorf("fetch failed; %w", err)
}
// Only merge iff branch is current branch and there is an upstream set (pullSpec.Branch is set to nil if there is no upstream)
if branchRef != pullSpec.Branch {
continue
}
roots, ok := sess.GetRoots(ctx, dbName)
if !ok {
return noConflictsOrViolations, threeWayMerge, sql.ErrDatabaseNotFound.New(dbName)
@@ -153,6 +170,9 @@ func DoDoltPull(ctx *sql.Context, args []string) (int, int, error) {
return conflicts, fastForward, err
}
}
if !rsSeen {
return noConflictsOrViolations, threeWayMerge, fmt.Errorf("%w: '%s'", ref.ErrInvalidRefSpec, refSpec.GetRemRefToLocal())
}
}
err = actions.FetchFollowTags(ctx, dbData.Rsw.TempTableFilesDir(), srcDB, dbData.Ddb, runProgFuncs, stopProgFuncs)

View File

@@ -102,5 +102,6 @@ func DoDoltPush(ctx *sql.Context, args []string) (int, error) {
return cmdFailure, err
}
}
// TODO : set upstream should be persisted outside of session
return cmdSuccess, nil
}

View File

@@ -47,7 +47,7 @@ SQL
# push to a file based remote
mkdir remotedir
dolt remote add origin file://remotedir
dolt push origin main
dolt push --set-upstream origin main
# clone from a directory
cd dolt-repo-clones

View File

@@ -35,7 +35,7 @@ SQL
# push to a localbs based remote
mkdir remotedir
dolt remote add origin localbs://remotedir
dolt push origin main
dolt push --set-upstream origin main
# clone from a directory
cd dolt-repo-clones

View File

@@ -40,14 +40,15 @@ teardown() {
cd repo1
dolt remote add origin file://../rem1
dolt commit -am "add test"
dolt checkout -b other
start_sql_server repo1
dolt push origin main
run server_query repo1 1 "select dolt_push() as p" "p\n0"
[ "$status" -eq 1 ]
[[ "$output" =~ "the current branch has no upstream branch" ]] || false
server_query repo1 1 "select dolt_push('--set-upstream', 'origin', 'main') as p" "p\n1"
server_query repo1 1 "select dolt_push('--set-upstream', 'origin', 'other') as p" "p\n1"
skip "In-memory branch doesn't track upstream"
server_query repo1 1 "select dolt_push() as p" "p\n1"

View File

@@ -55,53 +55,237 @@ teardown() {
@test "remotes: pull also fetches, but does not merge other branches" {
mkdir remote
mkdir repo1
cd remote
cd repo1
dolt init
dolt commit --allow-empty -m "first commit on main"
dolt branch other
dolt commit --allow-empty -m "second commit on main"
dolt remote add origin file://../remote
dolt push --set-upstream origin main
dolt checkout -b other
dolt commit --allow-empty -m "first commit on other"
dolt push --set-upstream origin other
cd ..
dolt clone file://./remote/.dolt/noms local
dolt clone file://./remote repo2
cd local
cd repo2
run dolt pull
[ "$status" -eq 0 ]
[[ "$output" =~ "Everything up-to-date." ]] || false
run dolt log --oneline -n 1
[ "$status" -eq 0 ]
[[ "$output" =~ "second commit on main" ]] || false
dolt commit --allow-empty -m "a commit for main from repo2"
dolt push
dolt checkout other
run dolt log --oneline -n 1
[ "$status" -eq 0 ]
[[ "$output" =~ "first commit on main" ]] || false
run dolt branch
[[ ! "$output" =~ "other" ]] || false
cd ../remote
dolt checkout other
dolt commit --allow-empty -m "first commit on other"
cd ../local
dolt checkout main
run dolt pull
run dolt checkout other
[ "$status" -eq 0 ]
[[ "$output" =~ "Everything up-to-date." ]] || false
dolt checkout other
run dolt log --oneline -n 1
[ "$status" -eq 0 ]
[[ "$output" =~ "first commit on main" ]] || false
run dolt pull
[ "$status" -eq 0 ]
[[ "$output" =~ "Updating" ]] || false
[[ "$output" =~ "Fast-forward" ]] || false
[[ "$output" =~ "branch 'other' set up to track 'origin/other'." ]] || false
run dolt log --oneline -n 1
[ "$status" -eq 0 ]
[[ "$output" =~ "first commit on other" ]] || false
run dolt status
[[ "$output" =~ "Your branch is up to date with 'origin/other'." ]] || false
dolt commit --allow-empty -m "second commit on other from repo2"
dolt push
cd ../repo1
dolt checkout other
run dolt pull
[ "$status" -eq 0 ]
[[ "$output" =~ "Updating" ]] || false
run dolt log --oneline -n 1
[ "$status" -eq 0 ]
[[ "$output" =~ "second commit on other from repo2" ]] || false
dolt checkout main
run dolt status
[[ "$output" =~ "behind 'origin/main' by 1 commit" ]] || false
run dolt log --oneline -n 1
[ "$status" -eq 0 ]
[[ ! "$output" =~ "a commit for main from repo2" ]] || false
run dolt pull
[ "$status" -eq 0 ]
[[ "$output" =~ "Updating" ]] || false
run dolt log --oneline -n 1
[ "$status" -eq 0 ]
[[ "$output" =~ "a commit for main from repo2" ]] || false
}
@test "remotes: cli 'dolt checkout new_branch' without -b flag creates new branch and sets upstream if there is a remote branch with matching name" {
mkdir remote
mkdir repo1
cd repo1
dolt init
dolt remote add origin file://../remote
dolt push origin main
dolt checkout -b other
dolt push --set-upstream origin other
cd ..
dolt clone file://./remote repo2
cd repo2
dolt commit --allow-empty -m "a commit for main from repo2"
dolt push
run dolt branch
[[ ! "$output" =~ "other" ]] || false
run dolt checkout other
[ "$status" -eq 0 ]
[[ "$output" =~ "branch 'other' set up to track 'origin/other'." ]] || false
run dolt status
[[ "$output" =~ "Your branch is up to date with 'origin/other'." ]] || false
}
@test "remotes: guessing the remote branch fails if there are multiple remotes with branches with matching name" {
mkdir remote
mkdir repo1
cd repo1
dolt init
dolt remote add origin file://../remote
dolt push origin main
dolt checkout -b other
dolt push origin other
cd ..
dolt clone file://./remote repo2
cd repo2
dolt remote add test-remote file://../remote
dolt push test-remote main
dolt checkout -b other
dolt push test-remote other
dolt branch -a
dolt checkout main
dolt branch -d other
run dolt branch
[[ ! "$output" =~ "other" ]] || false
run dolt checkout other
[ "$status" -eq 1 ]
[[ "$output" =~ "'other' matched multiple (2) remote tracking branches" ]] || false
}
@test "remotes: cli 'dolt checkout -b new_branch' should not set upstream if there is a remote branch with matching name" {
mkdir remote
mkdir repo1
cd repo1
dolt init
dolt remote add origin file://../remote
dolt sql -q "CREATE TABLE a (pk int)"
dolt commit -am "add table a"
dolt push --set-upstream origin main
dolt checkout -b other
dolt push --set-upstream origin other
cd ..
dolt clone file://./remote repo2
cd repo2
dolt branch
[[ ! "$output" =~ "other" ]] || false
run dolt checkout -b other
[ "$status" -eq 0 ]
[[ ! "$output" =~ "branch 'other' set up to track 'origin/other'." ]] || false
run dolt status
[[ ! "$output" =~ "Your branch is up to date with 'origin/other'." ]] || false
cd ../repo1
dolt checkout other
dolt sql -q "INSERT INTO a VALUES (1), (2)"
dolt commit -am "add table a"
dolt push
cd ../repo2
dolt checkout other
run dolt pull
[ "$status" -eq 1 ]
[[ "$output" =~ "There is no tracking information for the current branch." ]] || false
}
@test "remotes: select DOLT_CHECKOUT('new_branch') without '-b' sets upstream if there is a remote branch with matching name" {
mkdir remote
mkdir repo1
cd repo1
dolt init
dolt remote add test-remote http://localhost:50051/test-org/test-repo
dolt sql -q "CREATE TABLE test (pk INT)"
dolt commit -am "main commit"
dolt push test-remote main
cd ..
run dolt clone http://localhost:50051/test-org/test-repo repo2
[ "$status" -eq 0 ]
[[ "$output" =~ "cloning http://localhost:50051/test-org/test-repo" ]] || false
cd repo1
dolt checkout -b test-branch
dolt sql -q "INSERT INTO test VALUES (1);"
dolt commit -am "test commit"
dolt push test-remote test-branch
cd ../repo2
dolt fetch
# Checkout with DOLT_CHECKOUT and confirm the table has the row added in the remote
run dolt sql << SQL
SELECT DOLT_CHECKOUT('test-branch');
SELECT * FROM test;
SELECT DOLT_PULL();
SQL
[ "$status" -eq 0 ]
[[ "$output" =~ "pk" ]] || false
[[ "$output" =~ "1" ]] || false
skip # above checkout command should set upstream persisting outside of session
dolt checkout test-branch
run dolt status
[ "$status" -eq 0 ]
[[ "$output" =~ "branch 'test-branch' set up to track 'origin/test-branch'." ]] || false
}
@test "remotes: select 'DOLT_CHECKOUT('-b','new_branch') should not set upstream if there is a remote branch with matching name" {
mkdir remote
mkdir repo1
cd repo1
dolt init
dolt remote add origin file://../remote
dolt sql -q "CREATE TABLE a (pk int)"
dolt commit -am "add table a"
dolt push --set-upstream origin main
dolt checkout -b other
dolt push --set-upstream origin other
cd ..
dolt clone file://./remote repo2
cd repo2
dolt branch
[[ ! "$output" =~ "other" ]] || false
# Checkout with DOLT_CHECKOUT and confirm the table has the row added in the remote
run dolt sql << SQL
SELECT DOLT_CHECKOUT('-b','other');
SELECT DOLT_PULL();
SQL
[ "$status" -eq 1 ]
[[ "$output" =~ "There is no tracking information for the current branch." ]] || false
}
@test "remotes: add a remote using dolt remote" {
@@ -150,7 +334,7 @@ teardown() {
@test "remotes: push and pull main branch from a remote" {
dolt remote add test-remote http://localhost:50051/test-org/test-repo
run dolt push test-remote main
run dolt push --set-upstream test-remote main
[ "$status" -eq 0 ]
[ -d "$BATS_TMPDIR/remotes-$$/test-org/test-repo" ]
run dolt pull test-remote
@@ -161,7 +345,7 @@ teardown() {
@test "remotes: push and pull non-main branch from remote" {
dolt remote add test-remote http://localhost:50051/test-org/test-repo
dolt checkout -b test-branch
run dolt push test-remote test-branch
run dolt push --set-upstream test-remote test-branch
[ "$status" -eq 0 ]
run dolt pull test-remote
[ "$status" -eq 0 ]
@@ -814,7 +998,7 @@ CREATE TABLE test (
SQL
dolt add test
dolt commit -m "created table"
dolt push test-remote main
dolt push --set-upstream test-remote main
cd "dolt-repo-clones"
dolt clone http://localhost:50051/test-org/test-repo
cd ..
@@ -960,7 +1144,7 @@ SQL
@test "remotes: force fetch from main" {
dolt remote add test-remote http://localhost:50051/test-org/test-repo
dolt push test-remote main
dolt push --set-upstream test-remote main
cd "dolt-repo-clones"
dolt clone http://localhost:50051/test-org/test-repo
@@ -1003,41 +1187,10 @@ SQL
[ "$status" -ne 0 ]
run dolt fetch -f test-remote
[ "$status" -eq 0 ]
dolt pull
run dolt pull
[ "$status" -eq 0 ]
}
@test "remotes: DOLT_CHECKOUT to checkout to a remote branch." {
dolt remote add test-remote http://localhost:50051/test-org/test-repo
dolt sql <<SQL
CREATE TABLE test (
pk BIGINT NOT NULL,
PRIMARY KEY (pk)
);
SQL
dolt commit -a -m "main commit"
dolt push test-remote main
dolt checkout -b test-branch
dolt sql -q "INSERT INTO test VALUES (1);"
dolt commit -a -m "test commit"
dolt push test-remote test-branch
cd "dolt-repo-clones"
run dolt clone http://localhost:50051/test-org/test-repo
[ "$status" -eq 0 ]
[[ "$output" =~ "cloning http://localhost:50051/test-org/test-repo" ]] || false
cd test-repo
# Checkout with DOLT_CHECKOUT and confirm the table has the row added in the remote
run dolt sql << SQL
SELECT DOLT_CHECKOUT('test-branch');
SELECT * FROM test;
SQL
[ "$status" -eq 0 ]
[[ "$output" =~ "pk" ]] || false
[[ "$output" =~ "1" ]] || false
}
@test "remotes: validate that a config isn't needed for a pull." {
dolt remote add test-remote http://localhost:50051/test-org/test-repo
dolt push test-remote main

View File

@@ -22,7 +22,7 @@ setup() {
dolt branch feature
dolt remote add test-remote file://../rem1
# table and comits only present on repo1, rem1 at start
# table and commits only present on repo1, rem1 at start
cd $TMPDIRS/repo1
dolt sql -q "create table t1 (a int primary key, b int)"
dolt commit -am "First commit"
@@ -175,7 +175,7 @@ teardown() {
dolt checkout feature
run dolt sql -q "select dolt_pull('origin')"
[ "$status" -eq 1 ]
[[ "$output" =~ "branch not found" ]] || false
[[ "$output" =~ "You asked to pull from the remote 'origin', but did not specify a branch" ]] || false
[[ ! "$output" =~ "panic" ]] || false
}
@@ -184,18 +184,24 @@ teardown() {
dolt checkout feature
run dolt sql -q "CALL dolt_pull('origin')"
[ "$status" -eq 1 ]
[[ "$output" =~ "branch not found" ]] || false
[[ "$output" =~ "You asked to pull from the remote 'origin', but did not specify a branch" ]] || false
[[ ! "$output" =~ "panic" ]] || false
}
@test "sql-pull: dolt_pull feature branch" {
cd repo1
dolt checkout feature
dolt merge main
dolt push origin feature
dolt push --set-upstream origin feature
cd ../repo2
dolt checkout feature
dolt push --set-upstream origin feature
cd ../repo1
dolt merge main
dolt push
cd ../repo2
dolt sql -q "select dolt_pull('origin')"
run dolt sql -q "show tables" -r csv
[ "$status" -eq 0 ]
@@ -207,11 +213,17 @@ teardown() {
@test "sql-pull: CALL dolt_pull feature branch" {
cd repo1
dolt checkout feature
dolt merge main
dolt push origin feature
dolt push --set-upstream origin feature
cd ../repo2
dolt checkout feature
dolt push --set-upstream origin feature
cd ../repo1
dolt merge main
dolt push
cd ../repo2
dolt sql -q "CALL dolt_pull('origin')"
run dolt sql -q "show tables" -r csv
[ "$status" -eq 0 ]
@@ -429,3 +441,43 @@ teardown() {
[[ "$output" =~ "v2" ]] || false
[[ ! "$output" =~ "v3" ]] || false
}
@test "sql-pull: dolt_pull also fetches, but does not merge other branches" {
cd repo1
dolt checkout -b other
dolt push --set-upstream origin other
dolt checkout feature
dolt push origin feature
cd ../repo2
dolt fetch
# this checkout will set upstream because 'other' branch is a new branch that matches one of remote tracking branch
dolt checkout other
# this checkout will not set upstream because this 'feature' branch existed before matching remote tracking branch was created
dolt checkout feature
dolt push --set-upstream origin feature
cd ../repo1
dolt merge main
dolt push origin feature
dolt checkout other
dolt commit --allow-empty -m "new commit on other"
dolt push
cd ../repo2
dolt sql -q "select dolt_pull()"
run dolt sql -q "show tables" -r csv
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 2 ]
[[ "$output" =~ "Table" ]] || false
[[ "$output" =~ "t1" ]] || false
dolt checkout other
run dolt log --oneline -n 1
[ "$status" -eq 0 ]
[[ ! "$output" =~ "new commit on other" ]] || false
run dolt status
[ "$status" -eq 0 ]
[[ "$output" =~ "behind 'origin/other' by 1 commit" ]] || false
}

View File

@@ -158,42 +158,28 @@ teardown() {
[[ "$output" =~ "t1" ]] || false
}
@test "sql-push: dolt_push --set-upstream transient outside of session" {
@test "sql-push: dolt_push --set-upstream persists outside of session" {
skip # setting upstream run in a session should persist outside of session
cd repo1
dolt sql -q "select dolt_push('-u', 'origin', 'main')"
dolt push
dolt checkout -b other
dolt sql -q "select dolt_push('-u', 'origin', 'other')"
cd ../repo2
dolt pull origin
run dolt sql -q "show tables" -r csv
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 2 ]
[[ "$output" =~ "Table" ]] || false
[[ "$output" =~ "t1" ]] || false
cd ../repo1
# TODO persist branch config?
# upstream should be set still
run dolt sql -q "select dolt_push()"
[ "$status" -eq 1 ]
[[ "$output" =~ "the current branch has no upstream branch" ]] || false
[ "$status" -eq 0 ]
}
@test "sql-push: CALL dolt_push --set-upstream transient outside of session" {
@test "sql-push: CALL dolt_push --set-upstream persists outside of session" {
skip # setting upstream run in a session should persist outside of session
cd repo1
dolt sql -q "CALL dolt_push('-u', 'origin', 'main')"
dolt push
dolt checkout -b other
dolt sql -q "CALL dolt_push('-u', 'origin', 'other')"
cd ../repo2
dolt pull origin
run dolt sql -q "show tables" -r csv
[ "$status" -eq 0 ]
[ "${#lines[@]}" -eq 2 ]
[[ "$output" =~ "Table" ]] || false
[[ "$output" =~ "t1" ]] || false
cd ../repo1
# TODO persist branch config?
# upstream should be set still
run dolt sql -q "CALL dolt_push()"
[ "$status" -eq 1 ]
[[ "$output" =~ "the current branch has no upstream branch" ]] || false
[ "$status" -eq 0 ]
}
@test "sql-push: dolt_push --force flag" {