From a0530f8d90dc32edbfa4cab2c96374d076d8ce7b Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 11 Oct 2024 16:36:13 -0700 Subject: [PATCH 1/7] First pass at dolt checkout tables from commit --- .../sqle/dprocedures/dolt_checkout.go | 94 ++++++++++++++++++- go/libraries/utils/argparser/parser_test.go | 7 ++ 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go index aa945c0b29..a939362621 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go @@ -18,6 +18,7 @@ import ( "errors" "fmt" + "github.com/dolthub/dolt/go/libraries/doltcore/sqle/resolve" "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/types" @@ -80,7 +81,7 @@ func doDoltCheckout(ctx *sql.Context, args []string) (statusCode int, successMes if apr.Contains(cli.TrackFlag) && apr.NArg() > 0 { return 1, "", errors.New("Improper usage. Too many arguments provided.") } - if (branchOrTrack && apr.NArg() > 1) || (!branchOrTrack && apr.NArg() == 0) { + if !branchOrTrack && apr.NArg() == 0 { return 1, "", errors.New("Improper usage.") } @@ -122,10 +123,25 @@ func doDoltCheckout(ctx *sql.Context, args []string) (statusCode int, successMes if err != nil { return 1, "", err } - if !isModification { + if !isModification && apr.NArg() == 1 { return 0, fmt.Sprintf("Already on branch '%s'", branchName), nil } + // Handle dolt_checkout HEAD~3 -- table1 table2 table3 + if apr.NArg() > 1 { + database := ctx.GetCurrentDatabase() + if database == "" { + return 1, "", sql.ErrNoDatabaseSelected.New() + } + err = checkoutTablesFromCommit(ctx, database, branchName, apr.Args[1:]) + if err != nil { + return 0, "", err + } + + dsess.WaitForReplicationController(ctx, rsc) + return 0, generateSuccessMessage(branchName, ""), nil + } + // Check if user wants to checkout branch. if isBranch, err := actions.IsBranch(ctx, dbData.Ddb, branchName); err != nil { return 1, "", err @@ -190,7 +206,7 @@ func doDoltCheckout(ctx *sql.Context, args []string) (statusCode int, successMes return 0, "", err } - err = checkoutTables(ctx, roots, currentDbName, apr.Args) + err = checkoutTablesFromHead(ctx, roots, currentDbName, apr.Args) if err != nil && apr.NArg() == 1 { upstream, err := checkoutRemoteBranch(ctx, dSess, currentDbName, dbData, branchName, apr, &rsc) if err != nil { @@ -479,6 +495,74 @@ func checkoutExistingBranch(ctx *sql.Context, dbName string, branchName string, return nil } +// checkoutTablesFromCommit checks out the tables named from the branch named and overwrites those tables in the +// staged root. +func checkoutTablesFromCommit( + ctx *sql.Context, + databaseName string, + commitRef string, + tables []string, +) error { + dSess := dsess.DSessFromSess(ctx.Session) + dbData, ok := dSess.GetDbData(ctx, databaseName) + if !ok { + return fmt.Errorf("Could not load database %s", ctx.GetCurrentDatabase()) + } + + currentBranch, err := dSess.GetBranch() + if err != nil { + return err + } + if currentBranch == "" { + return fmt.Errorf("error: no current branch") + } + currentBranchRef := ref.NewBranchRef(currentBranch) + + cs, err := doltdb.NewCommitSpec(commitRef) + if err != nil { + return err + } + + headCommit, err := dbData.Ddb.Resolve(ctx, cs, currentBranchRef) + if err != nil { + return err + } + cm, ok := headCommit.ToCommit() + if !ok { + return fmt.Errorf("HEAD is not a commit") + } + + headRoot, err := cm.GetRootValue(ctx) + if err != nil { + return err + } + + ws, err := dSess.WorkingSet(ctx, databaseName) + if err != nil { + return err + } + + tableNames := make([]doltdb.TableName, len(tables)) + for i, table := range tables { + // TODO: we should allow schema-qualified table names here as well + name, _, tableExistsInHead, err := resolve.Table(ctx, headRoot, table) + if err != nil { + return err + } + if !tableExistsInHead { + return fmt.Errorf("error: table %s does not exist in branch %s", table, commitRef) + } + tableNames[i] = name + } + + newStagedRoot, err := actions.MoveTablesBetweenRoots(ctx, tableNames, headRoot, ws.StagedRoot()) + if err != nil { + return err + } + + return dSess.SetWorkingSet(ctx, databaseName, ws.WithStagedRoot(newStagedRoot)) +} + // doGlobalCheckout implements the behavior of the `dolt checkout` command line, moving the working set into // the new branch and persisting the checked-out branch into future sessions func doGlobalCheckout(ctx *sql.Context, branchName string, isForce bool, isNewBranch bool) error { @@ -490,7 +574,9 @@ func doGlobalCheckout(ctx *sql.Context, branchName string, isForce bool, isNewBr return nil } -func checkoutTables(ctx *sql.Context, roots doltdb.Roots, name string, tables []string) error { +// checkoutTablesFromHead checks out the tables named from the current head and overwrites those tables in the +// working root. The working root is then set as the new staged root. +func checkoutTablesFromHead(ctx *sql.Context, roots doltdb.Roots, name string, tables []string) error { tableNames := make([]doltdb.TableName, len(tables)) for i, table := range tables { diff --git a/go/libraries/utils/argparser/parser_test.go b/go/libraries/utils/argparser/parser_test.go index 5a45b83250..25ef235833 100644 --- a/go/libraries/utils/argparser/parser_test.go +++ b/go/libraries/utils/argparser/parser_test.go @@ -150,6 +150,13 @@ func TestArgParser(t *testing.T) { map[string]string{"param": "value", "optional": ""}, []string{}, }, + { + NewArgParserWithVariableArgs("test").SupportsString("param", "p", "", ""), + []string{"--param", "value", "arg1", "--", "table1", "table2"}, + nil, + map[string]string{"param": "value"}, + []string{"arg1", "--", "table1", "table2"}, + }, } for _, test := range tests { From 9f6000165be95348eab077ccc63ac1d4d4000a7c Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 11 Oct 2024 17:25:02 -0700 Subject: [PATCH 2/7] tests --- .../sqle/dprocedures/dolt_checkout.go | 15 ++- .../sqle/enginetest/dolt_engine_test.go | 116 +++++++++++++++--- .../doltcore/sqle/enginetest/dolt_queries.go | 23 ++++ 3 files changed, 132 insertions(+), 22 deletions(-) diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go index a939362621..e8129346ac 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go @@ -18,10 +18,6 @@ import ( "errors" "fmt" - "github.com/dolthub/dolt/go/libraries/doltcore/sqle/resolve" - "github.com/dolthub/go-mysql-server/sql" - "github.com/dolthub/go-mysql-server/sql/types" - "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" @@ -29,8 +25,11 @@ import ( "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/libraries/doltcore/sqle/resolve" "github.com/dolthub/dolt/go/libraries/utils/argparser" "github.com/dolthub/dolt/go/store/hash" + "github.com/dolthub/go-mysql-server/sql" + "github.com/dolthub/go-mysql-server/sql/types" ) var ErrEmptyBranchName = errors.New("error: cannot checkout empty string") @@ -139,7 +138,7 @@ func doDoltCheckout(ctx *sql.Context, args []string) (statusCode int, successMes } dsess.WaitForReplicationController(ctx, rsc) - return 0, generateSuccessMessage(branchName, ""), nil + return 0, "", nil } // Check if user wants to checkout branch. @@ -496,7 +495,7 @@ func checkoutExistingBranch(ctx *sql.Context, dbName string, branchName string, } // checkoutTablesFromCommit checks out the tables named from the branch named and overwrites those tables in the -// staged root. +// staged and working roots. func checkoutTablesFromCommit( ctx *sql.Context, databaseName string, @@ -555,12 +554,12 @@ func checkoutTablesFromCommit( tableNames[i] = name } - newStagedRoot, err := actions.MoveTablesBetweenRoots(ctx, tableNames, headRoot, ws.StagedRoot()) + newRoot, err := actions.MoveTablesBetweenRoots(ctx, tableNames, headRoot, ws.WorkingRoot()) if err != nil { return err } - return dSess.SetWorkingSet(ctx, databaseName, ws.WithStagedRoot(newStagedRoot)) + return dSess.SetWorkingSet(ctx, databaseName, ws.WithStagedRoot(newRoot).WithWorkingRoot(newRoot)) } // doGlobalCheckout implements the behavior of the `dolt checkout` command line, moving the working set into diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 13f7a75e35..3729586863 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -104,38 +104,126 @@ func TestSchemaOverrides(t *testing.T) { // Convenience test for debugging a single query. Unskip and set to the desired query. func TestSingleScript(t *testing.T) { - t.Skip() + // t.Skip() var scripts = []queries.ScriptTest{ { - Name: "create database in a transaction", + Name: "Checkout tables from commit", SetUpScript: []string{ - "START TRANSACTION", - "CREATE DATABASE test", + "create table t1 (a int primary key, b int);", + "create table t2 (a int primary key, b int);", + "call dolt_commit('-Am', 'creating tables');", + "call dolt_tag('tag1');", + "insert into t1 values (1, 1);", + "insert into t2 values (2, 2);", + "call dolt_commit('-Am', 'one row in each table');", + "call dolt_branch('b1');", + "insert into t1 values (3, 3);", + "insert into t2 values (4, 4);", + "call dolt_commit('-Am', 'two rows in each table');", + "insert into t1 values (5, 5);", }, Assertions: []queries.ScriptTestAssertion{ { - Query: "USE test", - SkipResultsCheck: true, + Query: "call dolt_checkout('HEAD~', '--', 't1')", + Expected: []sql.Row{ + {0, ""}, + }, }, { - Query: "CREATE TABLE foo (bar INT)", - SkipResultsCheck: true, + Query: "select * from t1 order by 1", + Expected: []sql.Row{ + {1, 1}, + }, }, { - Query: "USE mydb", - SkipResultsCheck: true, + Query: "select * from t2 order by 1", + Expected: []sql.Row{ + {2, 2}, + {4, 4}, + }, }, { - Query: "INSERT INTO test.foo VALUES (1)", - SkipResultsCheck: true, + Query: "select * from dolt_status", + Expected: []sql.Row{ + {"t1", true, "modified"}, + }, + }, + { + Query: "call dolt_reset('--hard')", + Expected: []sql.Row{ + {0}, + }, + }, + { + Query: "call dolt_checkout('HEAD~', '--', 't2')", + Expected: []sql.Row{ + {0, ""}, + }, + }, + { + Query: "select * from t1 order by 1", + Expected: []sql.Row{ + {1, 1}, + {3, 3}, + }, + }, + { + Query: "select * from t2 order by 1", + Expected: []sql.Row{ + {2, 2}, + }, }, { - Query: "SELECT * FROM test.foo", + Query: "select * from dolt_status", Expected: []sql.Row{ - {1}, + {"t2", true, "modified"}, }, }, + { + Query: "call dolt_reset('--hard')", + Expected: []sql.Row{ + {0}, + }, + }, + { + Query: "call dolt_checkout('b1', 't2', 't1')", + Expected: []sql.Row{ + {0, ""}, + }, + }, + { + Query: "select * from t1 order by 1", + Expected: []sql.Row{ + {1, 1}, + }, + }, + { + Query: "select * from t2 order by 1", + Expected: []sql.Row{ + {2, 2}, + }, + }, + { + Query: "call dolt_reset('--hard')", + Expected: []sql.Row{ + {0}, + }, + }, + { + Query: "call dolt_checkout('tag1', '.')", + Expected: []sql.Row{ + {0, ""}, + }, + }, + { + Query: "select * from t1 order by 1", + Expected: []sql.Row{}, + }, + { + Query: "select * from t2 order by 1", + Expected: []sql.Row{}, + }, }, }, } diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go index f5f8a0caa8..5197fddfaf 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go @@ -3174,6 +3174,29 @@ var DoltCheckoutScripts = []queries.ScriptTest{ }, }, }, + { + Name: "Checkout tables from commit", + SetUpScript: []string{ + "create table t1 (a int primary key, b int);", + "create table t2 (a int primary key, b int);", + "call dolt_commit('-Am', 'creating tables');", + "insert into t1 values (1, 1);", + "insert into t2 values (2, 2);", + "call dolt_commit('-Am', 'one row in each table');", + "call dolt_branch('b1');", + "call dolt_tag('tag1');", + "insert into t1 values (3, 3);", + "insert into t2 values (4, 4);", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "call dolt_checkout('HEAD~', '--', 't1')", + Expected: []sql.Row{ + {types.OkResult{RowsAffected: 0}}, + }, + }, + }, + }, } var DoltCheckoutReadOnlyScripts = []queries.ScriptTest{ From adad437236caf1dc0dc71ad0920afd8a88cc4494 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 11 Oct 2024 17:39:27 -0700 Subject: [PATCH 3/7] Updated tests, implemented . for table names --- .../sqle/dprocedures/dolt_checkout.go | 22 ++- .../sqle/enginetest/dolt_engine_test.go | 121 +-------------- .../doltcore/sqle/enginetest/dolt_queries.go | 144 +++++++++++++++++- 3 files changed, 158 insertions(+), 129 deletions(-) diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go index e8129346ac..08cc9d74a7 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go @@ -541,17 +541,25 @@ func checkoutTablesFromCommit( return err } - tableNames := make([]doltdb.TableName, len(tables)) - for i, table := range tables { - // TODO: we should allow schema-qualified table names here as well - name, _, tableExistsInHead, err := resolve.Table(ctx, headRoot, table) + var tableNames []doltdb.TableName + if len(tables) == 1 && tables[0] == "." { + tableNames, err = doltdb.UnionTableNames(ctx, ws.WorkingRoot()) if err != nil { return err } - if !tableExistsInHead { - return fmt.Errorf("error: table %s does not exist in branch %s", table, commitRef) + } else { + tableNames = make([]doltdb.TableName, len(tables)) + for i, table := range tables { + // TODO: we should allow schema-qualified table names here as well + name, _, tableExistsInHead, err := resolve.Table(ctx, headRoot, table) + if err != nil { + return err + } + if !tableExistsInHead { + return fmt.Errorf("table %s does not exist in %s", table, commitRef) + } + tableNames[i] = name } - tableNames[i] = name } newRoot, err := actions.MoveTablesBetweenRoots(ctx, tableNames, headRoot, ws.WorkingRoot()) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 3729586863..39ff65a6be 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -104,128 +104,9 @@ func TestSchemaOverrides(t *testing.T) { // Convenience test for debugging a single query. Unskip and set to the desired query. func TestSingleScript(t *testing.T) { - // t.Skip() + t.Skip() var scripts = []queries.ScriptTest{ - { - Name: "Checkout tables from commit", - SetUpScript: []string{ - "create table t1 (a int primary key, b int);", - "create table t2 (a int primary key, b int);", - "call dolt_commit('-Am', 'creating tables');", - "call dolt_tag('tag1');", - "insert into t1 values (1, 1);", - "insert into t2 values (2, 2);", - "call dolt_commit('-Am', 'one row in each table');", - "call dolt_branch('b1');", - "insert into t1 values (3, 3);", - "insert into t2 values (4, 4);", - "call dolt_commit('-Am', 'two rows in each table');", - "insert into t1 values (5, 5);", - }, - Assertions: []queries.ScriptTestAssertion{ - { - Query: "call dolt_checkout('HEAD~', '--', 't1')", - Expected: []sql.Row{ - {0, ""}, - }, - }, - { - Query: "select * from t1 order by 1", - Expected: []sql.Row{ - {1, 1}, - }, - }, - { - Query: "select * from t2 order by 1", - Expected: []sql.Row{ - {2, 2}, - {4, 4}, - }, - }, - { - Query: "select * from dolt_status", - Expected: []sql.Row{ - {"t1", true, "modified"}, - }, - }, - { - Query: "call dolt_reset('--hard')", - Expected: []sql.Row{ - {0}, - }, - }, - { - Query: "call dolt_checkout('HEAD~', '--', 't2')", - Expected: []sql.Row{ - {0, ""}, - }, - }, - { - Query: "select * from t1 order by 1", - Expected: []sql.Row{ - {1, 1}, - {3, 3}, - }, - }, - { - Query: "select * from t2 order by 1", - Expected: []sql.Row{ - {2, 2}, - }, - }, - { - Query: "select * from dolt_status", - Expected: []sql.Row{ - {"t2", true, "modified"}, - }, - }, - { - Query: "call dolt_reset('--hard')", - Expected: []sql.Row{ - {0}, - }, - }, - { - Query: "call dolt_checkout('b1', 't2', 't1')", - Expected: []sql.Row{ - {0, ""}, - }, - }, - { - Query: "select * from t1 order by 1", - Expected: []sql.Row{ - {1, 1}, - }, - }, - { - Query: "select * from t2 order by 1", - Expected: []sql.Row{ - {2, 2}, - }, - }, - { - Query: "call dolt_reset('--hard')", - Expected: []sql.Row{ - {0}, - }, - }, - { - Query: "call dolt_checkout('tag1', '.')", - Expected: []sql.Row{ - {0, ""}, - }, - }, - { - Query: "select * from t1 order by 1", - Expected: []sql.Row{}, - }, - { - Query: "select * from t2 order by 1", - Expected: []sql.Row{}, - }, - }, - }, } for _, script := range scripts { diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go index 5197fddfaf..7a28ea413b 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go @@ -3180,21 +3180,161 @@ var DoltCheckoutScripts = []queries.ScriptTest{ "create table t1 (a int primary key, b int);", "create table t2 (a int primary key, b int);", "call dolt_commit('-Am', 'creating tables');", + "call dolt_tag('tag1');", "insert into t1 values (1, 1);", "insert into t2 values (2, 2);", "call dolt_commit('-Am', 'one row in each table');", "call dolt_branch('b1');", - "call dolt_tag('tag1');", "insert into t1 values (3, 3);", "insert into t2 values (4, 4);", + "call dolt_commit('-Am', 'two rows in each table');", + "insert into t1 values (5, 5);", }, Assertions: []queries.ScriptTestAssertion{ { Query: "call dolt_checkout('HEAD~', '--', 't1')", Expected: []sql.Row{ - {types.OkResult{RowsAffected: 0}}, + {0, ""}, + }, + }, + { + Query: "select * from t1 order by 1", + Expected: []sql.Row{ + {1, 1}, + }, + }, + { + Query: "select * from t2 order by 1", + Expected: []sql.Row{ + {2, 2}, + {4, 4}, + }, + }, + { + Query: "select * from dolt_status", + Expected: []sql.Row{ + {"t1", true, "modified"}, + }, + }, + { + Query: "call dolt_reset('--hard')", + Expected: []sql.Row{ + {0}, }, }, + { + Query: "call dolt_checkout('HEAD~', '--', 't2')", + Expected: []sql.Row{ + {0, ""}, + }, + }, + { + Query: "select * from t1 order by 1", + Expected: []sql.Row{ + {1, 1}, + {3, 3}, + }, + }, + { + Query: "select * from t2 order by 1", + Expected: []sql.Row{ + {2, 2}, + }, + }, + { + Query: "select * from dolt_status", + Expected: []sql.Row{ + {"t2", true, "modified"}, + }, + }, + { + Query: "call dolt_reset('--hard')", + Expected: []sql.Row{ + {0}, + }, + }, + { + Query: "call dolt_checkout('b1', 't2', 't1')", + Expected: []sql.Row{ + {0, ""}, + }, + }, + { + Query: "select * from t1 order by 1", + Expected: []sql.Row{ + {1, 1}, + }, + }, + { + Query: "select * from t2 order by 1", + Expected: []sql.Row{ + {2, 2}, + }, + }, + { + Query: "call dolt_reset('--hard')", + Expected: []sql.Row{ + {0}, + }, + }, + { + Query: "call dolt_checkout('tag1', '.')", + Expected: []sql.Row{ + {0, ""}, + }, + }, + { + Query: "select * from t1 order by 1", + Expected: []sql.Row{}, + }, + { + Query: "select * from t2 order by 1", + Expected: []sql.Row{}, + }, + { + Query: "select * from dolt_status", + Expected: []sql.Row{ + {"t1", true, "modified"}, + {"t2", true, "modified"}, + }, + }, + { + Query: "call dolt_reset('--hard')", + Expected: []sql.Row{ + {0}, + }, + }, + { + Query: "SET @commit1 = (select commit_hash from dolt_log order by date desc limit 1);", + Expected: []sql.Row{{}}, + }, + { + Query: "call dolt_checkout(@commit1, 't1')", + Expected: []sql.Row{ + {0, ""}, + }, + }, + { + Query: "select * from t1 order by 1", + Expected: []sql.Row{ + {1, 1}, + {3, 3}, + }, + }, + { + Query: "call dolt_reset('--hard')", + Expected: []sql.Row{ + {0}, + }, + }, + { + Query: "call dolt_checkout('nosuchbranch', 't1')", + ExpectedErrStr: "branch not found: nosuchbranch", + }, + { + Query: "call dolt_checkout('HEAD', 't3')", + ExpectedErrStr: "table t3 does not exist in HEAD", + }, }, }, } From dfefb0674a787d4b3ace1ecf3e742a9180d34032 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 11 Oct 2024 17:43:23 -0700 Subject: [PATCH 4/7] New docs --- go/cmd/dolt/commands/checkout.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/go/cmd/dolt/commands/checkout.go b/go/cmd/dolt/commands/checkout.go index c09631ab31..8ebed49ebb 100644 --- a/go/cmd/dolt/commands/checkout.go +++ b/go/cmd/dolt/commands/checkout.go @@ -44,6 +44,9 @@ dolt checkout {{.LessThan}}branch{{.GreaterThan}} To prepare for working on {{.LessThan}}branch{{.GreaterThan}}, switch to it by updating the index and the tables in the working tree, and by pointing HEAD at the branch. Local modifications to the tables in the working tree are kept, so that they can be committed to the {{.LessThan}}branch{{.GreaterThan}}. +dolt checkout {{.LessThan}}commit{{.GreaterThan}} [--] {{.LessThan}}table{{.GreaterThan}}... + Specifying table names after a commit reference (branch, commit hash, tag, etc.) updates the working set to match that commit for one or more tables, but keeps the current branch. Local modifications to the tables named will be overwritten by their versions in the commit named. + dolt checkout -b {{.LessThan}}new_branch{{.GreaterThan}} [{{.LessThan}}start_point{{.GreaterThan}}] Specifying -b causes a new branch to be created as if dolt branch were called and then checked out. @@ -51,6 +54,7 @@ dolt checkout {{.LessThan}}table{{.GreaterThan}}... To update table(s) with their values in HEAD `, Synopsis: []string{ `{{.LessThan}}branch{{.GreaterThan}}`, + `{{.LessThan}}commit{{.GreaterThan}} [--] {{.LessThan}}table{{.GreaterThan}}...`, `{{.LessThan}}table{{.GreaterThan}}...`, `-b {{.LessThan}}new-branch{{.GreaterThan}} [{{.LessThan}}start-point{{.GreaterThan}}]`, `--track {{.LessThan}}remote{{.GreaterThan}}/{{.LessThan}}branch{{.GreaterThan}}`, From ad154f1eb0cbe7383e2e212e45bc4608ea20906b Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 11 Oct 2024 18:52:17 -0700 Subject: [PATCH 5/7] Bats test --- integration-tests/bats/checkout.bats | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/integration-tests/bats/checkout.bats b/integration-tests/bats/checkout.bats index 030e9bc6db..41d322f58f 100755 --- a/integration-tests/bats/checkout.bats +++ b/integration-tests/bats/checkout.bats @@ -249,6 +249,30 @@ SQL [[ "$output" =~ "foreign_key1" ]] || false } +@test "checkout: dolt checkout table from another branch" { + dolt sql -q "create table t (c1 int primary key, c2 int, check(c2 > 0))" + dolt sql -q "create table z (c1 int primary key, c2 int)" + dolt sql -q "insert into t values (1,1)" + dolt sql -q "insert into z values (2,2);" + dolt commit -Am "new values in t" + dolt branch b1 + dolt sql -q "insert into t values (3,3);" + dolt sql -q "insert into z values (4,4);" + dolt checkout b1 -- t + + dolt status + run dolt status + [[ "$output" =~ "On branch main" ]] || false + [[ "$output" =~ "modified: z" ]] || false + [[ ! "$output" =~ "modified: t" ]] || false + + run dolt sql -q "select count(*) from t" -r csv + [[ "$output" =~ "1" ]] || false + + run dolt sql -q "select count(*) from z" -r csv + [[ "$output" =~ "2" ]] || false +} + @test "checkout: with -f flag without conflict" { dolt sql -q 'create table test (id int primary key);' dolt sql -q 'insert into test (id) values (8);' From 5734023ee60698bf5b395f39a1b6d8310f642e29 Mon Sep 17 00:00:00 2001 From: zachmu Date: Sat, 12 Oct 2024 02:02:22 +0000 Subject: [PATCH 6/7] [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh --- .../sqle/dprocedures/dolt_checkout.go | 25 ++++++++++--------- .../sqle/enginetest/dolt_engine_test.go | 3 +-- .../doltcore/sqle/enginetest/dolt_queries.go | 10 ++++---- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go index 08cc9d74a7..6a5efa96fd 100644 --- a/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go +++ b/go/libraries/doltcore/sqle/dprocedures/dolt_checkout.go @@ -18,6 +18,9 @@ import ( "errors" "fmt" + "github.com/dolthub/go-mysql-server/sql" + "github.com/dolthub/go-mysql-server/sql/types" + "github.com/dolthub/dolt/go/cmd/dolt/cli" "github.com/dolthub/dolt/go/cmd/dolt/errhand" "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" @@ -28,8 +31,6 @@ import ( "github.com/dolthub/dolt/go/libraries/doltcore/sqle/resolve" "github.com/dolthub/dolt/go/libraries/utils/argparser" "github.com/dolthub/dolt/go/store/hash" - "github.com/dolthub/go-mysql-server/sql" - "github.com/dolthub/go-mysql-server/sql/types" ) var ErrEmptyBranchName = errors.New("error: cannot checkout empty string") @@ -130,7 +131,7 @@ func doDoltCheckout(ctx *sql.Context, args []string) (statusCode int, successMes if apr.NArg() > 1 { database := ctx.GetCurrentDatabase() if database == "" { - return 1, "", sql.ErrNoDatabaseSelected.New() + return 1, "", sql.ErrNoDatabaseSelected.New() } err = checkoutTablesFromCommit(ctx, database, branchName, apr.Args[1:]) if err != nil { @@ -494,13 +495,13 @@ func checkoutExistingBranch(ctx *sql.Context, dbName string, branchName string, return nil } -// checkoutTablesFromCommit checks out the tables named from the branch named and overwrites those tables in the +// checkoutTablesFromCommit checks out the tables named from the branch named and overwrites those tables in the // staged and working roots. func checkoutTablesFromCommit( - ctx *sql.Context, - databaseName string, - commitRef string, - tables []string, + ctx *sql.Context, + databaseName string, + commitRef string, + tables []string, ) error { dSess := dsess.DSessFromSess(ctx.Session) dbData, ok := dSess.GetDbData(ctx, databaseName) @@ -530,7 +531,7 @@ func checkoutTablesFromCommit( if !ok { return fmt.Errorf("HEAD is not a commit") } - + headRoot, err := cm.GetRootValue(ctx) if err != nil { return err @@ -540,7 +541,7 @@ func checkoutTablesFromCommit( if err != nil { return err } - + var tableNames []doltdb.TableName if len(tables) == 1 && tables[0] == "." { tableNames, err = doltdb.UnionTableNames(ctx, ws.WorkingRoot()) @@ -550,7 +551,7 @@ func checkoutTablesFromCommit( } else { tableNames = make([]doltdb.TableName, len(tables)) for i, table := range tables { - // TODO: we should allow schema-qualified table names here as well + // TODO: we should allow schema-qualified table names here as well name, _, tableExistsInHead, err := resolve.Table(ctx, headRoot, table) if err != nil { return err @@ -581,7 +582,7 @@ func doGlobalCheckout(ctx *sql.Context, branchName string, isForce bool, isNewBr return nil } -// checkoutTablesFromHead checks out the tables named from the current head and overwrites those tables in the +// checkoutTablesFromHead checks out the tables named from the current head and overwrites those tables in the // working root. The working root is then set as the new staged root. func checkoutTablesFromHead(ctx *sql.Context, roots doltdb.Roots, name string, tables []string) error { tableNames := make([]doltdb.TableName, len(tables)) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index 39ff65a6be..7880599883 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -106,8 +106,7 @@ func TestSchemaOverrides(t *testing.T) { func TestSingleScript(t *testing.T) { t.Skip() - var scripts = []queries.ScriptTest{ - } + var scripts = []queries.ScriptTest{} for _, script := range scripts { harness := newDoltHarness(t) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go index 7a28ea413b..36c6883fb7 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go @@ -3284,11 +3284,11 @@ var DoltCheckoutScripts = []queries.ScriptTest{ }, }, { - Query: "select * from t1 order by 1", + Query: "select * from t1 order by 1", Expected: []sql.Row{}, }, { - Query: "select * from t2 order by 1", + Query: "select * from t2 order by 1", Expected: []sql.Row{}, }, { @@ -3305,7 +3305,7 @@ var DoltCheckoutScripts = []queries.ScriptTest{ }, }, { - Query: "SET @commit1 = (select commit_hash from dolt_log order by date desc limit 1);", + Query: "SET @commit1 = (select commit_hash from dolt_log order by date desc limit 1);", Expected: []sql.Row{{}}, }, { @@ -3328,11 +3328,11 @@ var DoltCheckoutScripts = []queries.ScriptTest{ }, }, { - Query: "call dolt_checkout('nosuchbranch', 't1')", + Query: "call dolt_checkout('nosuchbranch', 't1')", ExpectedErrStr: "branch not found: nosuchbranch", }, { - Query: "call dolt_checkout('HEAD', 't3')", + Query: "call dolt_checkout('HEAD', 't3')", ExpectedErrStr: "table t3 does not exist in HEAD", }, }, From cf49cebf0b7e2d5fe7084d6dfaf7870823ccaad2 Mon Sep 17 00:00:00 2001 From: Zach Musgrave Date: Fri, 11 Oct 2024 19:08:38 -0700 Subject: [PATCH 7/7] fix test --- go/libraries/utils/argparser/parser_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/utils/argparser/parser_test.go b/go/libraries/utils/argparser/parser_test.go index 25ef235833..225a5cdffd 100644 --- a/go/libraries/utils/argparser/parser_test.go +++ b/go/libraries/utils/argparser/parser_test.go @@ -155,7 +155,7 @@ func TestArgParser(t *testing.T) { []string{"--param", "value", "arg1", "--", "table1", "table2"}, nil, map[string]string{"param": "value"}, - []string{"arg1", "--", "table1", "table2"}, + []string{"arg1", "table1", "table2"}, }, }