mirror of
https://github.com/dolthub/dolt.git
synced 2026-04-19 19:21:44 -05:00
add dolt_cherry_pick procedure (#5233)
This commit is contained in:
@@ -88,7 +88,7 @@ func (cmd CherryPickCmd) Exec(ctx context.Context, commandStr string, args []str
|
||||
usage()
|
||||
return 1
|
||||
} else if apr.NArg() > 1 {
|
||||
return HandleVErrAndExitCode(errhand.BuildDError("multiple commits not supported yet.").SetPrintUsage().Build(), usage)
|
||||
return HandleVErrAndExitCode(errhand.BuildDError("cherry-picking multiple commits is not supported yet").SetPrintUsage().Build(), usage)
|
||||
}
|
||||
|
||||
cherryStr := apr.Arg(0)
|
||||
@@ -97,17 +97,12 @@ func (cmd CherryPickCmd) Exec(ctx context.Context, commandStr string, args []str
|
||||
return HandleVErrAndExitCode(verr, usage)
|
||||
}
|
||||
|
||||
authorStr := ""
|
||||
if as, ok := apr.GetValue(cli.AuthorParam); ok {
|
||||
authorStr = as
|
||||
}
|
||||
|
||||
verr := cherryPick(ctx, dEnv, cherryStr, authorStr)
|
||||
verr := cherryPick(ctx, dEnv, cherryStr)
|
||||
return HandleVErrAndExitCode(verr, usage)
|
||||
}
|
||||
|
||||
// cherryPick returns error if any step of cherry-picking fails. It receives cherry-picked commit and performs cherry-picking and commits.
|
||||
func cherryPick(ctx context.Context, dEnv *env.DoltEnv, cherryStr, authorStr string) errhand.VerboseError {
|
||||
func cherryPick(ctx context.Context, dEnv *env.DoltEnv, cherryStr string) errhand.VerboseError {
|
||||
// check for clean working state
|
||||
headRoot, err := dEnv.HeadRoot(ctx)
|
||||
if err != nil {
|
||||
@@ -166,12 +161,7 @@ func cherryPick(ctx context.Context, dEnv *env.DoltEnv, cherryStr, authorStr str
|
||||
return errhand.BuildDError("dolt add failed").AddCause(err).Build()
|
||||
}
|
||||
|
||||
// Pass in the final parameters for the author string.
|
||||
commitParams := []string{"-m", commitMsg}
|
||||
if authorStr != "" {
|
||||
commitParams = append(commitParams, "--author", authorStr)
|
||||
}
|
||||
|
||||
res = CommitCmd{}.Exec(ctx, "commit", commitParams, dEnv)
|
||||
if res != 0 {
|
||||
return errhand.BuildDError("dolt commit failed").AddCause(err).Build()
|
||||
|
||||
@@ -45,9 +45,9 @@ const (
|
||||
EncodingBytesAddr Encoding = 21
|
||||
EncodingCommitAddr Encoding = 22
|
||||
EncodingStringAddr Encoding = 23
|
||||
EncodingJSONAddr Encoding = 24
|
||||
EncodingCell Encoding = 25
|
||||
EncodingString Encoding = 128
|
||||
EncodingJSONAddr Encoding = 24
|
||||
EncodingCell Encoding = 25
|
||||
EncodingString Encoding = 128
|
||||
EncodingBytes Encoding = 129
|
||||
EncodingDecimal Encoding = 130
|
||||
EncodingJSON Encoding = 131
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
)
|
||||
|
||||
// doltAdd is the stored procedure version of the function `dolt_add`.
|
||||
// doltAdd is the stored procedure version for the CLI command `dolt add`.
|
||||
func doltAdd(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltAdd(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -37,7 +37,7 @@ const (
|
||||
statusErr = 0
|
||||
)
|
||||
|
||||
// doltBackup is the stored procedure version of the function `dolt_backup`.
|
||||
// doltBackup is the stored procedure version for the CLI command `dolt backup`.
|
||||
func doltBackup(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltBackup(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -37,7 +37,7 @@ var (
|
||||
InvalidArgErr = errors.New("error: invalid usage")
|
||||
)
|
||||
|
||||
// doltBranch is the stored procedure version of the function `dolt_branch`.
|
||||
// doltBranch is the stored procedure version for the CLI command `dolt branch`.
|
||||
func doltBranch(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltBranch(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
|
||||
var ErrEmptyBranchName = errors.New("error: cannot checkout empty string")
|
||||
|
||||
// doltCheckout is the stored procedure version of the function `dolt_checkout`.
|
||||
// doltCheckout is the stored procedure version for the CLI command `dolt checkout`.
|
||||
func doltCheckout(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltCheckout(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
206
go/libraries/doltcore/sqle/dprocedures/dolt_cherry_pick.go
Normal file
206
go/libraries/doltcore/sqle/dprocedures/dolt_cherry_pick.go
Normal file
@@ -0,0 +1,206 @@
|
||||
// Copyright 2023 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package dprocedures
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/dolt/go/cmd/dolt/cli"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/branch_control"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/merge"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
|
||||
)
|
||||
|
||||
var ErrEmptyCherryPick = errors.New("cannot cherry-pick empty string")
|
||||
var ErrCherryPickUncommittedChanges = errors.New("cannot cherry-pick with uncommitted changes")
|
||||
|
||||
// doltCherryPick is the stored procedure version for the CLI command `dolt cherry-pick`.
|
||||
func doltCherryPick(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltCherryPick(ctx, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rowToIter(res), nil
|
||||
}
|
||||
|
||||
func doDoltCherryPick(ctx *sql.Context, args []string) (string, error) {
|
||||
// Get the information for the sql context.
|
||||
dbName := ctx.GetCurrentDatabase()
|
||||
if len(dbName) == 0 {
|
||||
return "", fmt.Errorf("error: empty database name")
|
||||
}
|
||||
|
||||
if err := branch_control.CheckAccess(ctx, branch_control.Permissions_Write); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
apr, err := cli.CreateCherryPickArgParser().Parse(args)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// we only support cherry-picking a single commit for now.
|
||||
if apr.NArg() == 0 {
|
||||
return "", ErrEmptyCherryPick
|
||||
} else if apr.NArg() > 1 {
|
||||
return "", fmt.Errorf("cherry-picking multiple commits is not supported yet")
|
||||
}
|
||||
|
||||
cherryStr := apr.Arg(0)
|
||||
if len(cherryStr) == 0 {
|
||||
return "", ErrEmptyCherryPick
|
||||
}
|
||||
|
||||
dSess := dsess.DSessFromSess(ctx.Session)
|
||||
|
||||
roots, ok := dSess.GetRoots(ctx, dbName)
|
||||
if !ok {
|
||||
return "", sql.ErrDatabaseNotFound.New(dbName)
|
||||
}
|
||||
|
||||
newWorkingRoot, commitMsg, err := cherryPick(ctx, dSess, roots, dbName, cherryStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = dSess.SetRoot(ctx, dbName, newWorkingRoot)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
res, err := doDoltAdd(ctx, []string{"-A"})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if res != 0 {
|
||||
return "", fmt.Errorf("dolt add failed")
|
||||
}
|
||||
|
||||
return doDoltCommit(ctx, []string{"-m", commitMsg})
|
||||
}
|
||||
|
||||
// cherryPick checks that the current working set is clean, verifies the cherry-pick commit is not a merge commit
|
||||
// or a commit without parent commit, performs merge and returns the new working set root value and
|
||||
// the commit message of cherry-picked commit as the commit message of the new commit created during this command.
|
||||
func cherryPick(ctx *sql.Context, dSess *dsess.DoltSession, roots doltdb.Roots, dbName, cherryStr string) (*doltdb.RootValue, string, error) {
|
||||
// check for clean working set
|
||||
headRootHash, err := roots.Head.HashOf()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
workingRootHash, err := roots.Working.HashOf()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if workingRootHash != headRootHash {
|
||||
return nil, "", ErrCherryPickUncommittedChanges
|
||||
}
|
||||
|
||||
stagedRootHash, err := roots.Staged.HashOf()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if stagedRootHash != headRootHash {
|
||||
return nil, "", ErrCherryPickUncommittedChanges
|
||||
}
|
||||
|
||||
doltDB, ok := dSess.GetDoltDB(ctx, dbName)
|
||||
if !ok {
|
||||
return nil, "", fmt.Errorf("failed to get DoltDB")
|
||||
}
|
||||
|
||||
dbData, ok := dSess.GetDbData(ctx, dbName)
|
||||
if !ok {
|
||||
return nil, "", fmt.Errorf("failed to get dbData")
|
||||
}
|
||||
|
||||
cherryCommitSpec, err := doltdb.NewCommitSpec(cherryStr)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
cherryCommit, err := doltDB.Resolve(ctx, cherryCommitSpec, dbData.Rsr.CWBHeadRef())
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
if len(cherryCommit.DatasParents()) > 1 {
|
||||
return nil, "", fmt.Errorf("cherry-picking a merge commit is not supported")
|
||||
}
|
||||
if len(cherryCommit.DatasParents()) == 0 {
|
||||
return nil, "", fmt.Errorf("cherry-picking a commit without parents is not supported")
|
||||
}
|
||||
|
||||
cherryRoot, err := cherryCommit.GetRootValue(ctx)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
parentCommit, err := doltDB.ResolveParent(ctx, cherryCommit, 0)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
parentRoot, err := parentCommit.GetRootValue(ctx)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
dbState, ok, err := dSess.LookupDbState(ctx, dbName)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
} else if !ok {
|
||||
return nil, "", sql.ErrDatabaseNotFound.New(dbName)
|
||||
}
|
||||
|
||||
// use parent of cherry-pick as ancestor root to merge
|
||||
mo := merge.MergeOpts{IsCherryPick: true}
|
||||
mergedRoot, mergeStats, err := merge.MergeRoots(ctx, roots.Working, cherryRoot, parentRoot, cherryCommit, parentCommit, dbState.EditOpts(), mo)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
var tablesWithConflict []string
|
||||
for tbl, stats := range mergeStats {
|
||||
if stats.Conflicts > 0 {
|
||||
tablesWithConflict = append(tablesWithConflict, tbl)
|
||||
}
|
||||
}
|
||||
|
||||
if len(tablesWithConflict) > 0 {
|
||||
tblNames := strings.Join(tablesWithConflict, "', '")
|
||||
return nil, "", fmt.Errorf("conflicts in table {'%s'}", tblNames)
|
||||
}
|
||||
|
||||
workingRootHash, err = mergedRoot.HashOf()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
if headRootHash.Equal(workingRootHash) {
|
||||
return nil, "", fmt.Errorf("no changes were made, nothing to commit")
|
||||
}
|
||||
|
||||
cherryCommitMeta, err := cherryCommit.GetCommitMeta(ctx)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return mergedRoot, cherryCommitMeta.Description, nil
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
|
||||
)
|
||||
|
||||
// doltClean is the stored procedure version of the function `dolt_clean`.
|
||||
// doltClean is the stored procedure version for the CLI command `dolt clean`.
|
||||
func doltClean(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltClean(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/utils/earl"
|
||||
)
|
||||
|
||||
// doltClone is a stored procedure to clone a database from a remote
|
||||
// doltClone is the stored procedure version for the CLI command `dolt clone`.
|
||||
func doltClone(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
ap := cli.CreateCloneArgParser()
|
||||
apr, err := ap.Parse(args)
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
|
||||
var hashType = types.MustCreateString(query.Type_TEXT, 32, sql.Collation_ascii_bin)
|
||||
|
||||
// doltCommit is the stored procedure version for the CLI function `commit`.
|
||||
// doltCommit is the stored procedure version for the CLI command `dolt commit`.
|
||||
func doltCommit(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltCommit(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -42,7 +42,7 @@ import (
|
||||
|
||||
var ErrConfSchIncompatible = errors.New("the conflict schema's columns are not equal to the current schema's columns, please resolve manually")
|
||||
|
||||
// doltConflictsResolve is the stored procedure version of the function `dolt conflict resolve`.
|
||||
// doltConflictsResolve is the stored procedure version for the CLI command `dolt conflict resolve`.
|
||||
func doltConflictsResolve(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := DoDoltConflictsResolve(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
|
||||
)
|
||||
|
||||
// doltFetch is the stored procedure version of the function `dolt_fetch`.
|
||||
// doltFetch is the stored procedure version for the CLI command `dolt fetch`.
|
||||
func doltFetch(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltFetch(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -46,7 +46,7 @@ const (
|
||||
|
||||
var ErrUncommittedChanges = goerrors.NewKind("cannot merge with uncommitted changes")
|
||||
|
||||
// doltMerge is the stored procedure version of the functions `merge` and `dolt_merge`.
|
||||
// doltMerge is the stored procedure version for the CLI command `dolt merge`.
|
||||
func doltMerge(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
hasConflicts, ff, err := doDoltMerge(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/store/datas/pull"
|
||||
)
|
||||
|
||||
// doltPull is the stored procedure version of the function `dolt_pull`.
|
||||
// doltPull is the stored procedure version for the CLI command `dolt pull`.
|
||||
func doltPull(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
conflicts, ff, err := doDoltPull(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/store/datas"
|
||||
)
|
||||
|
||||
// doltPush is the stored procedure version of the function `dolt_push`.
|
||||
// doltPush is the stored procedure version for the CLI command `dolt push`.
|
||||
func doltPush(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltPush(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/utils/config"
|
||||
)
|
||||
|
||||
// doltRemote is the stored procedure version of the CLI `dolt remote` command
|
||||
// doltRemote is the stored procedure version for the CLI command `dolt remote`.
|
||||
func doltRemote(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltRemote(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
|
||||
)
|
||||
|
||||
// doltReset is the stored procedure version of the function `dolt_reset`.
|
||||
// doltReset is the stored procedure version for the CLI command `dolt reset`.
|
||||
func doltReset(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltReset(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
|
||||
)
|
||||
|
||||
// doltRevert is the stored procedure version of the function `revert` and `dolt_revert`.
|
||||
// doltRevert is the stored procedure version for the CLI command `dolt revert`.
|
||||
func doltRevert(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltRevert(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dsess"
|
||||
)
|
||||
|
||||
// doltTag is the stored procedure version of the CLI `dolt tag` command
|
||||
// doltTag is the stored procedure version for the CLI command `dolt tag`.
|
||||
func doltTag(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltTag(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"github.com/dolthub/dolt/go/libraries/utils/set"
|
||||
)
|
||||
|
||||
// doltVerifyConstraints is the stored procedure version of the function `constraints_verify`.
|
||||
// doltVerifyConstraints is the stored procedure version for the CLI command `dolt constraints verify`.
|
||||
func doltVerifyConstraints(ctx *sql.Context, args ...string) (sql.RowIter, error) {
|
||||
res, err := doDoltConstraintsVerify(ctx, args)
|
||||
if err != nil {
|
||||
|
||||
@@ -24,6 +24,7 @@ var DoltProcedures = []sql.ExternalStoredProcedureDetails{
|
||||
{Name: "dolt_backup", Schema: int64Schema("success"), Function: doltBackup},
|
||||
{Name: "dolt_branch", Schema: int64Schema("status"), Function: doltBranch},
|
||||
{Name: "dolt_checkout", Schema: int64Schema("status"), Function: doltCheckout},
|
||||
{Name: "dolt_cherry_pick", Schema: stringSchema("hash"), Function: doltCherryPick},
|
||||
{Name: "dolt_clean", Schema: int64Schema("status"), Function: doltClean},
|
||||
{Name: "dolt_clone", Schema: int64Schema("status"), Function: doltClone},
|
||||
{Name: "dolt_commit", Schema: stringSchema("hash"), Function: doltCommit},
|
||||
@@ -41,9 +42,11 @@ var DoltProcedures = []sql.ExternalStoredProcedureDetails{
|
||||
{Name: "dolt_verify_constraints", Schema: int64Schema("violations"), Function: doltVerifyConstraints},
|
||||
|
||||
// Dolt stored procedure aliases
|
||||
// TODO: Add new procedure aliases in doltProcedureAliasSet in go-mysql-server/sql/information_schema/routines.go file
|
||||
{Name: "dadd", Schema: int64Schema("status"), Function: doltAdd},
|
||||
{Name: "dbranch", Schema: int64Schema("status"), Function: doltBranch},
|
||||
{Name: "dcheckout", Schema: int64Schema("status"), Function: doltCheckout},
|
||||
{Name: "dcherry_pick", Schema: stringSchema("hash"), Function: doltCherryPick},
|
||||
{Name: "dclean", Schema: int64Schema("status"), Function: doltClean},
|
||||
{Name: "dclone", Schema: int64Schema("status"), Function: doltClone},
|
||||
{Name: "dcommit", Schema: stringSchema("hash"), Function: doltCommit},
|
||||
|
||||
423
integration-tests/bats/sql-cherry-pick.bats
Normal file
423
integration-tests/bats/sql-cherry-pick.bats
Normal file
@@ -0,0 +1,423 @@
|
||||
#!/usr/bin/env bats
|
||||
load $BATS_TEST_DIRNAME/helper/common.bash
|
||||
|
||||
setup() {
|
||||
setup_common
|
||||
|
||||
dolt sql -q "CREATE TABLE test(pk BIGINT PRIMARY KEY, v varchar(10))"
|
||||
dolt add .
|
||||
dolt commit -am "Created table"
|
||||
dolt checkout -b branch1
|
||||
dolt sql -q "INSERT INTO test VALUES (1, 'a')"
|
||||
dolt commit -am "Inserted 1"
|
||||
dolt sql -q "INSERT INTO test VALUES (2, 'b')"
|
||||
dolt commit -am "Inserted 2"
|
||||
dolt sql -q "INSERT INTO test VALUES (3, 'c')"
|
||||
dolt commit -am "Inserted 3"
|
||||
|
||||
run dolt sql -q "SELECT * FROM test" -r csv
|
||||
[[ "$output" =~ "1,a" ]] || false
|
||||
[[ "$output" =~ "2,b" ]] || false
|
||||
[[ "$output" =~ "3,c" ]] || false
|
||||
}
|
||||
|
||||
teardown() {
|
||||
assert_feature_version
|
||||
teardown_common
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: simple cherry pick with the latest commit" {
|
||||
dolt checkout main
|
||||
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "0" ]
|
||||
|
||||
run dolt sql -q "SELECT * FROM test" -r csv
|
||||
[[ ! "$output" =~ "1,a" ]] || false
|
||||
[[ ! "$output" =~ "2,b" ]] || false
|
||||
[[ "$output" =~ "3,c" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: multiple simple cherry-picks" {
|
||||
dolt sql <<SQL
|
||||
UPDATE test SET v = 'x' WHERE pk = 2;
|
||||
INSERT INTO test VALUES (5, 'g'), (8, 'u');
|
||||
CALL DOLT_COMMIT('-am','Updated 2b to 2x and inserted more rows');
|
||||
CALL DOLT_CHECKOUT('main');
|
||||
CALL DOLT_CHERRY_PICK('branch1~2');
|
||||
SQL
|
||||
|
||||
# we are still on branch1
|
||||
run dolt sql -q "SELECT * FROM test" -r csv
|
||||
[[ "$output" =~ "1,a" ]] || false
|
||||
[[ "$output" =~ "2,x" ]] || false
|
||||
[[ "$output" =~ "3,c" ]] || false
|
||||
[[ "$output" =~ "5,g" ]] || false
|
||||
[[ "$output" =~ "8,u" ]] || false
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "SELECT * FROM test" -r csv
|
||||
[[ "$output" =~ "2,b" ]] || false
|
||||
[[ ! "$output" =~ "1,a" ]] || false
|
||||
[[ ! "$output" =~ "2,x" ]] || false
|
||||
[[ ! "$output" =~ "3,c" ]] || false
|
||||
|
||||
run dolt sql -q "CALL DCHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "0" ]
|
||||
|
||||
run dolt sql -q "SELECT * FROM test" -r csv
|
||||
[[ ! "$output" =~ "1,a" ]] || false
|
||||
[[ "$output" =~ "2,x" ]] || false
|
||||
[[ ! "$output" =~ "3,c" ]] || false
|
||||
[[ "$output" =~ "5,g" ]] || false
|
||||
[[ "$output" =~ "8,u" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: too far back" {
|
||||
run dolt sql<<SQL
|
||||
CALL DCHECKOUT('main');
|
||||
CALL DCHERRY_PICK('branch1~10');
|
||||
SQL
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "ancestor" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: no changes" {
|
||||
run dolt sql<<SQL
|
||||
CALL DOLT_COMMIT('--allow-empty', '-m', 'empty commit');
|
||||
CALL DOLT_CHECKOUT('main');
|
||||
CALL DOLT_CHERRY_PICK('branch1');
|
||||
SQL
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "no changes were made, nothing to commit" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: invalid hash" {
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "target commit not found" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: has changes in the working set" {
|
||||
dolt checkout main
|
||||
dolt sql -q "INSERT INTO test VALUES (4, 'f')"
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1~2')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "cannot cherry-pick with uncommitted changes" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: staged changes" {
|
||||
dolt checkout main
|
||||
dolt sql -q "INSERT INTO test VALUES (4, 'f')"
|
||||
dolt add -A
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1~2')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "cannot cherry-pick with uncommitted changes" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: insert, update, delete rows and schema changes on non existent table in working set" {
|
||||
dolt sql -q "CREATE TABLE branch1table (id int primary key, col1 int)"
|
||||
dolt add .
|
||||
dolt sql -q "INSERT INTO branch1table VALUES (9,8),(7,6),(5,4)"
|
||||
dolt commit -am "create table with rows"
|
||||
|
||||
dolt sql -q "INSERT INTO branch1table VALUES (1,2)"
|
||||
dolt commit -am "Insert a row"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "conflict: table with same name deleted and modified" ]] || false
|
||||
|
||||
run dolt sql -q "SHOW TABLES" -r csv
|
||||
[[ ! "$output" =~ "branch1table" ]] || false
|
||||
|
||||
dolt checkout branch1
|
||||
dolt sql -q "UPDATE branch1table SET col1 = 0 WHERE id > 6"
|
||||
dolt commit -am "Update a rows"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "conflict: table with same name deleted and modified" ]] || false
|
||||
|
||||
run dolt sql -q "SHOW TABLES" -r csv
|
||||
[[ ! "$output" =~ "branch1table" ]] || false
|
||||
|
||||
dolt checkout branch1
|
||||
dolt sql -q "DELETE FROM branch1table WHERE id > 8"
|
||||
dolt commit -am "Update and delete rows"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "conflict: table with same name deleted and modified" ]] || false
|
||||
|
||||
run dolt sql -q "SHOW TABLES" -r csv
|
||||
[[ ! "$output" =~ "branch1table" ]] || false
|
||||
|
||||
dolt checkout branch1
|
||||
dolt sql -q "ALTER TABLE branch1table ADD COLUMN col2 int"
|
||||
dolt commit -am "Alter table add column"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "conflict: table with same name deleted and modified" ]] || false
|
||||
|
||||
run dolt sql -q "SHOW TABLES" -r csv
|
||||
[[ ! "$output" =~ "branch1table" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: row data conflict, leave working set clean" {
|
||||
dolt sql -q "CREATE TABLE other (pk int primary key, v int)"
|
||||
dolt add .
|
||||
dolt sql -q "INSERT INTO other VALUES (1, 2)"
|
||||
dolt sql -q "INSERT INTO test VALUES (4,'f')"
|
||||
dolt commit -am "add other table"
|
||||
|
||||
dolt checkout main
|
||||
dolt sql -q "CREATE TABLE other (pk int primary key, v int)"
|
||||
dolt add .
|
||||
dolt sql -q "INSERT INTO other VALUES (1, 3)"
|
||||
dolt sql -q "INSERT INTO test VALUES (4,'k')"
|
||||
dolt commit -am "add other table with conflict and test with conflict"
|
||||
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "conflicts in table" ]] || false
|
||||
|
||||
run dolt status
|
||||
[[ "$output" =~ "nothing to commit, working tree clean" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: commit with CREATE TABLE" {
|
||||
dolt sql -q "CREATE TABLE table_a (pk BIGINT PRIMARY KEY, v varchar(10))"
|
||||
dolt add .
|
||||
dolt sql -q "INSERT INTO table_a VALUES (11, 'aa'), (22, 'ab'), (33, 'ac')"
|
||||
dolt sql -q "DELETE FROM test WHERE pk = 2"
|
||||
dolt commit -am "Added table_a with rows and delete pk=2 from test"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "0" ]
|
||||
|
||||
run dolt sql -q "SHOW TABLES" -r csv
|
||||
[[ "$output" =~ "table_a" ]] || false
|
||||
|
||||
run dolt sql -q "SELECT * FROM test" -r csv
|
||||
[[ ! "$output" =~ "1,a" ]] || false
|
||||
[[ ! "$output" =~ "2,b" ]] || false
|
||||
[[ ! "$output" =~ "3,c" ]] || false
|
||||
|
||||
run dolt sql -q "SELECT * FROM table_a" -r csv
|
||||
[[ "$output" =~ "11,aa" ]] || false
|
||||
[[ "$output" =~ "22,ab" ]] || false
|
||||
[[ "$output" =~ "33,ac" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: commit with DROP TABLE" {
|
||||
skip # drop or rename case
|
||||
dolt sql -q "DROP TABLE test"
|
||||
dolt commit -am "Drop table test"
|
||||
|
||||
run dolt sql -q "SHOW TABLES" -r csv
|
||||
[[ ! "$output" =~ "test" ]] || false
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "SHOW TABLES" -r csv
|
||||
[[ "$output" =~ "test" ]] || false
|
||||
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "table was renamed or dropped" ]] || false
|
||||
|
||||
run dolt sql -q "SHOW TABLES" -r csv
|
||||
[[ "$output" =~ "test" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: commit with ALTER TABLE rename table name" {
|
||||
dolt sql -q "ALTER TABLE test RENAME TO new_name"
|
||||
dolt add .
|
||||
dolt commit -am "rename table name"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "table was renamed or dropped" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: cherry-pick commit is a merge commit" {
|
||||
dolt checkout -b branch2
|
||||
dolt sql -q "INSERT INTO test VALUES (4, 'd'), (5, 'e')"
|
||||
dolt commit -am "add more rows in branch2"
|
||||
|
||||
dolt checkout branch1
|
||||
dolt sql -q "INSERT INTO test VALUES (6, 'f'), (7, 'g')"
|
||||
dolt commit -am "add more rows in branch1"
|
||||
dolt merge branch2 -m "merge branch2"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "cherry-picking a merge commit is not supported" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: cherry-pick commit is a cherry-picked commit" {
|
||||
dolt checkout -b branch2
|
||||
dolt sql -q "INSERT INTO test VALUES (4, 'd'), (5, 'e')"
|
||||
dolt commit -am "add more rows in branch2"
|
||||
|
||||
dolt checkout branch1
|
||||
dolt sql -q "INSERT INTO test VALUES (6, 'f'), (7, 'g')"
|
||||
dolt commit -am "add more rows in branch1"
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch2')"
|
||||
[ "$status" -eq "0" ]
|
||||
|
||||
run dolt sql -q "SELECT * FROM test" -r csv
|
||||
[[ "$output" =~ "4,d" ]] || false
|
||||
[[ "$output" =~ "5,e" ]] || false
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "0" ]
|
||||
|
||||
run dolt sql -q "SELECT * FROM test" -r csv
|
||||
[[ "$output" =~ "4,d" ]] || false
|
||||
[[ "$output" =~ "5,e" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: add triggers" {
|
||||
dolt sql -q "CREATE TRIGGER trigger1 BEFORE INSERT ON test FOR EACH ROW SET new.v = concat(new.v, ' inserted')"
|
||||
dolt sql -q "INSERT INTO test VALUES (4,'z')"
|
||||
run dolt sql -q "SELECT * FROM test"
|
||||
[[ "$output" =~ "z inserted" ]] || false
|
||||
|
||||
dolt add .
|
||||
dolt commit -am "add trigger"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "SHOW TRIGGERS"
|
||||
[[ ! "$output" =~ "trigger1" ]] || false
|
||||
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "0" ]
|
||||
|
||||
run dolt sql -q "SELECT * FROM test"
|
||||
[[ "$output" =~ "z inserted" ]] || false
|
||||
|
||||
run dolt sql -q "SHOW TRIGGERS"
|
||||
[[ "$output" =~ "trigger1" ]] || false
|
||||
|
||||
dolt checkout branch1
|
||||
dolt sql -q "DROP TRIGGER trigger1"
|
||||
dolt commit -am "drop trigger"
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "0" ]
|
||||
|
||||
run dolt sql -q "SHOW TRIGGERS"
|
||||
[[ ! "$output" =~ "trigger1" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: add procedures" {
|
||||
dolt sql -q "CREATE PROCEDURE proc1 (in x int) select x from dual"
|
||||
run dolt sql -q "CALL proc1(434)"
|
||||
[[ "$output" =~ "434" ]] || false
|
||||
|
||||
dolt add .
|
||||
dolt commit -am "add procedure"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "SHOW PROCEDURE STATUS"
|
||||
[[ ! "$output" =~ "proc1" ]] || false
|
||||
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "0" ]
|
||||
|
||||
run dolt sql -q "SHOW PROCEDURE STATUS"
|
||||
[[ "$output" =~ "proc1" ]] || false
|
||||
|
||||
run dolt sql -q "CALL proc1(434)"
|
||||
[[ "$output" =~ "434" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: keyless table" {
|
||||
dolt checkout main
|
||||
dolt sql -q "CREATE TABLE keyless (id int, name varchar(10))"
|
||||
dolt add .
|
||||
dolt commit -am "add keyless table"
|
||||
|
||||
dolt checkout -b branch2
|
||||
dolt sql -q "INSERT INTO keyless VALUES (1,'1'), (2,'3')"
|
||||
dolt commit -am "insert into keyless table"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "0" ]
|
||||
|
||||
dolt sql -q "SELECT * FROM keyless" -r csv
|
||||
[[ ! "$output" =~ "1,1" ]] || false
|
||||
[[ ! "$output" =~ "2,3" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: commit with ALTER TABLE add column" {
|
||||
dolt sql -q "ALTER TABLE test ADD COLUMN c int"
|
||||
dolt commit -am "alter table test add column c"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: commit with ALTER TABLE change column" {
|
||||
dolt sql -q "ALTER TABLE test CHANGE COLUMN v c varchar(100)"
|
||||
dolt commit -am "alter table test change column v"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: commit with ALTER TABLE modify column" {
|
||||
dolt sql -q "UPDATE test SET v = '1' WHERE pk < 4"
|
||||
dolt sql -q "ALTER TABLE test MODIFY COLUMN v int"
|
||||
dolt commit -am "alter table test modify column v"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: commit with ALTER TABLE drop column" {
|
||||
dolt sql -q "ALTER TABLE test DROP COLUMN v"
|
||||
dolt commit -am "alter table test drop column v"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: commit with ALTER TABLE rename column" {
|
||||
dolt sql -q "ALTER TABLE test RENAME COLUMN v TO c"
|
||||
dolt commit -am "alter table test rename column v"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-cherry-pick: commit with ALTER TABLE drop and add primary key" {
|
||||
dolt sql -q "ALTER TABLE test DROP PRIMARY KEY, ADD PRIMARY KEY (pk, v)"
|
||||
dolt commit -am "alter table test drop and add primary key"
|
||||
|
||||
dolt checkout main
|
||||
run dolt sql -q "CALL DOLT_CHERRY_PICK('branch1')"
|
||||
[ "$status" -eq "1" ]
|
||||
[[ "$output" =~ "table schema does not match in current HEAD and cherry-pick commit" ]] || false
|
||||
}
|
||||
Reference in New Issue
Block a user