mirror of
https://github.com/dolthub/dolt.git
synced 2026-03-09 01:56:30 -05:00
fix inconsistencies of dolt checkout and pull commands (#3725)
This commit is contained in:
@@ -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())
|
||||
|
||||
@@ -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 {
|
||||
|
||||
13
go/libraries/doltcore/env/actions/table.go
vendored
13
go/libraries/doltcore/env/actions/table.go
vendored
@@ -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
|
||||
}
|
||||
|
||||
17
go/libraries/doltcore/env/remotes.go
vendored
17
go/libraries/doltcore/env/remotes.go
vendored
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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" {
|
||||
|
||||
Reference in New Issue
Block a user