Merge branch 'main' into fulghum/schema-merge

This commit is contained in:
Jason Fulghum
2023-04-25 11:46:18 -07:00
125 changed files with 1304 additions and 591 deletions
+2 -2
View File
@@ -3,8 +3,8 @@ name: Check Formatting, Committers and Generated Code
on:
pull_request:
branches: [ main ]
pull_request_target:
types: [opened, edited, reopened]
# pull_request_target:
# types: [opened, edited, reopened]
concurrency:
group: ci-check-repo-${{ github.event.pull_request.number || github.ref }}
+6 -6
View File
@@ -64,7 +64,7 @@ type Command interface {
// Description returns a description of the command
Description() string
// Exec executes the command
Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *CliContext) int
Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx CliContext) int
// Docs returns the documentation for this command, or nil if it's undocumented
Docs() *CommandDocumentation
// ArgParser returns the arg parser for this command
@@ -169,7 +169,7 @@ func (hc SubCommandHandler) Hidden() bool {
return hc.hidden
}
func (hc SubCommandHandler) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *CliContext) int {
func (hc SubCommandHandler) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx CliContext) int {
if len(args) < 1 && hc.Unspecified == nil {
hc.printUsage(commandStr)
return 1
@@ -183,11 +183,11 @@ func (hc SubCommandHandler) Exec(ctx context.Context, commandStr string, args []
for _, cmd := range hc.Subcommands {
lwrName := strings.ToLower(cmd.Name())
if lwrName == subCommandStr {
return hc.handleCommand(ctx, commandStr+" "+subCommandStr, cmd, args[1:], dEnv)
return hc.handleCommand(ctx, commandStr+" "+subCommandStr, cmd, args[1:], dEnv, cliCtx)
}
}
if hc.Unspecified != nil {
return hc.handleCommand(ctx, commandStr, hc.Unspecified, args, dEnv)
return hc.handleCommand(ctx, commandStr, hc.Unspecified, args, dEnv, cliCtx)
}
if !isHelp(subCommandStr) {
@@ -199,7 +199,7 @@ func (hc SubCommandHandler) Exec(ctx context.Context, commandStr string, args []
return 0
}
func (hc SubCommandHandler) handleCommand(ctx context.Context, commandStr string, cmd Command, args []string, dEnv *env.DoltEnv) int {
func (hc SubCommandHandler) handleCommand(ctx context.Context, commandStr string, cmd Command, args []string, dEnv *env.DoltEnv, cliCtx CliContext) int {
cmdRequiresRepo := true
if rnrCmd, ok := cmd.(RepoNotRequiredCommand); ok {
cmdRequiresRepo = rnrCmd.RequiresRepo()
@@ -234,7 +234,7 @@ func (hc SubCommandHandler) handleCommand(ctx context.Context, commandStr string
return 1
}
ret := cmd.Exec(ctx, commandStr, args, dEnv, nil)
ret := cmd.Exec(ctx, commandStr, args, dEnv, cliCtx)
if evt != nil {
events.GlobalCollector.CloseEventAndAdd(evt)
+1 -1
View File
@@ -68,7 +68,7 @@ func (cmd *trackedCommand) RequiresRepo() bool {
return false
}
func (cmd *trackedCommand) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *CliContext) int {
func (cmd *trackedCommand) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx CliContext) int {
cmd.called = true
cmd.cmdStr = commandStr
cmd.args = args
+1 -1
View File
@@ -60,7 +60,7 @@ func (cmd AddCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd AddCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd AddCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cli.CreateAddArgParser()
helpPr, _ := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, addDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, helpPr)
+1 -1
View File
@@ -64,7 +64,7 @@ func (cmd SetRefCmd) Hidden() bool {
// Version displays the version of the running dolt client
// Exec executes the command
func (cmd SetRefCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd SetRefCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
usage, _ := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{}, ap))
+1 -1
View File
@@ -60,7 +60,7 @@ func (cmd ShowRootCmd) Hidden() bool {
// Version displays the version of the running dolt client
// Exec executes the command
func (cmd ShowRootCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ShowRootCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
usage, _ := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{}, ap))
+1 -1
View File
@@ -66,7 +66,7 @@ func (a Assist) Hidden() bool {
return true
}
func (a *Assist) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (a *Assist) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
a.messages = make([]string, 0)
apiKey, ok := os.LookupEnv("OPENAI_API_KEY")
+1 -1
View File
@@ -105,7 +105,7 @@ func (cmd BackupCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd BackupCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd BackupCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, backupDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -79,7 +79,7 @@ func (cmd BlameCmd) EventType() eventsapi.ClientEventType {
//
// When all nodes have blame information, stop iterating through commits and print the blame graph.
// Exec executes the command
func (cmd BlameCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd BlameCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, blameDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -98,7 +98,7 @@ func (cmd BranchCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd BranchCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd BranchCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, branchDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -78,7 +78,7 @@ func (cmd CheckoutCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd CheckoutCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd CheckoutCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cli.CreateCheckoutArgParser()
helpPrt, usagePrt := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, checkoutDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, helpPrt)
+5 -5
View File
@@ -71,7 +71,7 @@ func (cmd CherryPickCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command.
func (cmd CherryPickCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd CherryPickCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cli.CreateCherryPickArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cherryPickDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
@@ -217,14 +217,14 @@ func getCherryPickedRootValue(ctx context.Context, dEnv *env.DoltEnv, workingRoo
// use parent of cherry-pick as ancestor to merge
mo := merge.MergeOpts{IsCherryPick: true}
mergedRoot, mergeStats, err := merge.MergeRoots(ctx, workingRoot, cherryRoot, parentRoot, cherryCm, parentCm, opts, mo)
result, err := merge.MergeRoots(ctx, workingRoot, cherryRoot, parentRoot, cherryCm, parentCm, opts, mo)
if err != nil {
return nil, "", err
}
var tablesWithConflict []string
for tbl, stats := range mergeStats {
if stats.Conflicts > 0 {
for tbl, stats := range result.Stats {
if stats.HasConflicts() {
tablesWithConflict = append(tablesWithConflict, tbl)
}
}
@@ -234,5 +234,5 @@ func getCherryPickedRootValue(ctx context.Context, dEnv *env.DoltEnv, workingRoo
return nil, "", errors.New(fmt.Sprintf("conflicts in table {'%s'}", tblNames))
}
return mergedRoot, commitMsg, nil
return result.Root, commitMsg, nil
}
+1 -1
View File
@@ -65,7 +65,7 @@ func (cmd CleanCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd CleanCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd CleanCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cli.CreateCleanArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cleanDocContent, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -81,7 +81,7 @@ func (cmd CloneCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd CloneCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd CloneCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cloneDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+59 -10
View File
@@ -51,8 +51,7 @@ func AutoResolveAll(ctx context.Context, dEnv *env.DoltEnv, strategy AutoResolve
return err
}
tbls, err := root.TablesInConflict(ctx)
tbls, err := root.GetTableNames(ctx)
if err != nil {
return err
}
@@ -63,26 +62,77 @@ func AutoResolveAll(ctx context.Context, dEnv *env.DoltEnv, strategy AutoResolve
// AutoResolveTables resolves all conflicts in the given tables according to the
// given |strategy|.
func AutoResolveTables(ctx context.Context, dEnv *env.DoltEnv, strategy AutoResolveStrategy, tbls []string) error {
root, err := dEnv.WorkingRoot(ctx)
ws, err := dEnv.WorkingSet(ctx)
if err != nil {
return err
}
for _, tblName := range tbls {
err = ResolveTable(ctx, dEnv, root, tblName, strategy)
// schema conflicts
if ws.MergeActive() {
ws, err = ResolveSchemaConflicts(ctx, dEnv.DoltDB, ws, tbls, strategy)
if err != nil {
return err
}
if err = dEnv.UpdateWorkingSet(ctx, ws); err != nil {
return err
}
}
// data conflicts
for _, tblName := range tbls {
err = ResolveDataConflicts(ctx, dEnv, ws, tblName, strategy)
if err != nil {
return err
}
}
return nil
}
// ResolveTable resolves all conflicts in the given table according to the given
func ResolveSchemaConflicts(ctx context.Context, ddb *doltdb.DoltDB, ws *doltdb.WorkingSet, tables []string, strategy AutoResolveStrategy) (*doltdb.WorkingSet, error) {
tblSet := set.NewStrSet(tables)
updates := make(map[string]*doltdb.Table)
err := ws.MergeState().IterSchemaConflicts(ctx, ddb, func(table string, conflict doltdb.SchemaConflict) error {
if !tblSet.Contains(table) {
return nil
}
ours, theirs := conflict.GetConflictingTables()
switch strategy {
case AutoResolveStrategyOurs:
updates[table] = ours
case AutoResolveStrategyTheirs:
updates[table] = theirs
default:
panic("unhandled auto resolve strategy")
}
return nil
})
if err != nil {
return nil, err
}
root := ws.WorkingRoot()
for name, tbl := range updates {
if root, err = root.PutTable(ctx, name, tbl); err != nil {
return nil, err
}
}
// clear resolved schema conflicts
var unmerged []string
for _, tbl := range ws.MergeState().TablesWithSchemaConflicts() {
if tblSet.Contains(tbl) {
continue
}
unmerged = append(unmerged, tbl)
}
return ws.WithWorkingRoot(root).WithUnmergableTables(unmerged), nil
}
// ResolveDataConflicts resolves all conflicts in the given table according to the given
// |strategy|. It errors if the schema of the conflict version you are choosing
// differs from the current schema.
func ResolveTable(ctx context.Context, dEnv *env.DoltEnv, root *doltdb.RootValue, tblName string, strategy AutoResolveStrategy) (err error) {
tbl, ok, err := root.GetTable(ctx, tblName)
func ResolveDataConflicts(ctx context.Context, dEnv *env.DoltEnv, ws *doltdb.WorkingSet, tblName string, strategy AutoResolveStrategy) (err error) {
tbl, ok, err := ws.WorkingRoot().GetTable(ctx, tblName)
if err != nil {
return err
}
@@ -92,8 +142,7 @@ func ResolveTable(ctx context.Context, dEnv *env.DoltEnv, root *doltdb.RootValue
has, err := tbl.HasConflicts(ctx)
if err != nil {
return err
}
if !has {
} else if !has {
return nil
}
+1 -1
View File
@@ -75,7 +75,7 @@ func (cmd CatCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd CatCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd CatCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, catDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -88,7 +88,7 @@ func (cmd ResolveCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd ResolveCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ResolveCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, resDocumentation, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+24 -18
View File
@@ -76,7 +76,7 @@ func (cmd CommitCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd CommitCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd CommitCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
res := performCommit(ctx, commandStr, args, dEnv)
if res == 1 {
return res
@@ -198,7 +198,7 @@ func performCommit(ctx context.Context, commandStr string, args []string, dEnv *
mergeParentCommits = parentsHeadForAmend
}
pendingCommit, err := actions.GetCommitStaged(ctx, roots, ws.MergeActive(), mergeParentCommits, dEnv.DbData().Ddb, actions.CommitStagedProps{
pendingCommit, err := actions.GetCommitStaged(ctx, roots, ws, mergeParentCommits, dEnv.DbData().Ddb, actions.CommitStagedProps{
Message: msg,
Date: t,
AllowEmpty: apr.Contains(cli.AllowEmptyFlag) || apr.Contains(cli.AmendFlag),
@@ -276,7 +276,7 @@ func handleCommitErr(ctx context.Context, dEnv *env.DoltEnv, err error, usage cl
if actions.IsNothingStaged(err) {
notStagedTbls := actions.NothingStagedTblDiffs(err)
n := PrintDiffsNotStaged(ctx, dEnv, cli.CliOut, notStagedTbls, false, 0, nil, nil)
n := PrintDiffsNotStaged(ctx, dEnv, cli.CliOut, notStagedTbls, false, 0, merge.ArtifactStatus{})
if n == 0 {
bdr := errhand.BuildDError(`no changes added to commit (use "dolt add")`)
@@ -358,18 +358,19 @@ func buildInitalCommitMsg(ctx context.Context, dEnv *env.DoltEnv, suggestedMsg s
stagedTblDiffs, notStagedTblDiffs, _ := diff.GetStagedUnstagedTableDeltas(ctx, roots)
workingTblsInConflict, _, _, err := merge.GetTablesInConflict(ctx, roots)
ws, err := dEnv.WorkingSet(ctx)
if err != nil {
workingTblsInConflict = []string{}
return "", err
}
workingTblsWithViolations, _, _, err := merge.GetTablesWithConstraintViolations(ctx, roots)
as, err := merge.GetMergeArtifactStatus(ctx, ws)
if err != nil {
workingTblsWithViolations = []string{}
return "", nil
}
buf := bytes.NewBuffer([]byte{})
n := printStagedDiffs(buf, stagedTblDiffs, true)
n = PrintDiffsNotStaged(ctx, dEnv, buf, notStagedTblDiffs, true, n, workingTblsInConflict, workingTblsWithViolations)
n = PrintDiffsNotStaged(ctx, dEnv, buf, notStagedTblDiffs, true, n, as)
currBranch := dEnv.RepoStateReader().CWBHeadRef()
initialCommitMessage := fmt.Sprintf("%s\n# Please enter the commit message for your changes. Lines starting"+
@@ -405,12 +406,13 @@ func PrintDiffsNotStaged(
notStagedTbls []diff.TableDelta,
printHelp bool,
linesPrinted int,
workingTblsInConflict, workingTblsWithViolations []string,
as merge.ArtifactStatus,
) int {
inCnfSet := set.NewStrSet(workingTblsInConflict)
violationSet := set.NewStrSet(workingTblsWithViolations)
inCnfSet := set.NewStrSet(as.DataConflictTables)
inCnfSet.Add(as.SchemaConflictsTables...)
violationSet := set.NewStrSet(as.ConstraintViolationsTables)
if len(workingTblsInConflict) > 0 || len(workingTblsWithViolations) > 0 {
if as.HasConflicts() || as.HasConstraintViolations() {
if linesPrinted > 0 {
cli.Println()
}
@@ -419,16 +421,19 @@ func PrintDiffsNotStaged(
iohelp.WriteLine(wr, mergedTableHelp)
}
if len(workingTblsInConflict) > 0 {
if as.HasConflicts() {
lines := make([]string, 0, len(notStagedTbls))
for _, tblName := range workingTblsInConflict {
for _, tblName := range as.SchemaConflictsTables {
lines = append(lines, fmt.Sprintf(statusFmt, schemaConflictLabel, tblName))
}
for _, tblName := range as.DataConflictTables {
lines = append(lines, fmt.Sprintf(statusFmt, bothModifiedLabel, tblName))
}
iohelp.WriteLine(wr, color.RedString(strings.Join(lines, "\n")))
linesPrinted += len(lines)
}
if len(workingTblsWithViolations) > 0 {
if as.HasConstraintViolations() {
violationOnly, _, _ := violationSet.LeftIntersectionRight(inCnfSet)
lines := make([]string, 0, len(notStagedTbls))
for _, tblName := range violationOnly.AsSortedSlice() {
@@ -543,9 +548,10 @@ const (
untrackedHeader = `Untracked files:`
untrackedHeaderHelp = ` (use "dolt add <table>" to include in what will be committed)`
statusFmt = "\t%-16s%s"
statusRenameFmt = "\t%-16s%s -> %s"
bothModifiedLabel = "both modified:"
statusFmt = "\t%-18s%s"
statusRenameFmt = "\t%-18s%s -> %s"
schemaConflictLabel = "schema conflict:"
bothModifiedLabel = "both modified:"
)
var tblDiffTypeToLabel = map[diff.TableDiffType]string{
+1 -1
View File
@@ -116,7 +116,7 @@ func (cmd ConfigCmd) ArgParser() *argparser.ArgParser {
// Exec is used by the config command to allow users to view / edit their global and repository local configurations.
// Exec executes the command
func (cmd ConfigCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ConfigCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cfgDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -78,7 +78,7 @@ func (cmd CheckCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd CheckCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd CheckCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, checkDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -89,7 +89,7 @@ func (cmd ImportCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd ImportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ImportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, importDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -74,7 +74,7 @@ func (cmd LsCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd LsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd LsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, lsDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -70,7 +70,7 @@ func (cmd NewCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd NewCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd NewCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, newDocs, ap))
cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -67,7 +67,7 @@ func (cmd RmCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd RmCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd RmCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, rmDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -73,7 +73,7 @@ func (cmd UseCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd UseCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd UseCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, useDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
@@ -67,7 +67,7 @@ func (cmd VerifyConstraintsCmd) ArgParser() *argparser.ArgParser {
return cli.CreateVerifyConstraintsArgParser(cmd.Name())
}
func (cmd VerifyConstraintsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd VerifyConstraintsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, _ := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, verifyConstraintsDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -159,7 +159,7 @@ func (cmd DiffCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd DiffCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd DiffCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, diffDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -66,7 +66,7 @@ func (cmd DiffCmd) ArgParser() *argparser.ArgParser {
}
// Exec implements cli.Command.
func (cmd DiffCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd DiffCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, diffDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -71,7 +71,7 @@ func (cmd UploadCmd) ArgParser() *argparser.ArgParser {
}
// Exec implements cli.Command.
func (cmd UploadCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd UploadCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, uploadDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -69,7 +69,7 @@ func (cmd PrintCmd) ArgParser() *argparser.ArgParser {
}
// Exec implements cli.Command.
func (cmd PrintCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd PrintCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, printDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -113,7 +113,7 @@ func (cmd DumpCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd DumpCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd DumpCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, dumpDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -72,7 +72,7 @@ func (cmd *DumpDocsCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd *DumpDocsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd *DumpDocsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{}, ap))
+1 -1
View File
@@ -68,7 +68,7 @@ func (cmd FetchCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd FetchCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd FetchCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cli.CreateFetchArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, fetchDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -96,7 +96,7 @@ func (cmd FilterBranchCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd FilterBranchCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd FilterBranchCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, filterBranchDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -81,7 +81,7 @@ func (cmd GarbageCollectionCmd) EventType() eventsapi.ClientEventType {
// Version displays the version of the running dolt client
// Exec executes the command
func (cmd GarbageCollectionCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd GarbageCollectionCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
var verr errhand.VerboseError
ap := cmd.ArgParser()
+1 -1
View File
@@ -47,7 +47,7 @@ func (z GenZshCompCmd) Description() string {
return "Creates a zsh autocomp file for all dolt commands"
}
func (z GenZshCompCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (z GenZshCompCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := z.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{}, ap))
+1 -1
View File
@@ -79,7 +79,7 @@ func (cmd CatCmd) ArgParser() *argparser.ArgParser {
return ap
}
func (cmd CatCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd CatCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, catDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -55,7 +55,7 @@ func (cmd LsCmd) ArgParser() *argparser.ArgParser {
return ap
}
func (cmd LsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd LsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
ap.TooManyArgsErrorFunc = func(receivedArgs []string) error {
args := strings.Join(receivedArgs, ", ")
+1 -1
View File
@@ -58,7 +58,7 @@ func (cmd RebuildCmd) ArgParser() *argparser.ArgParser {
return ap
}
func (cmd RebuildCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd RebuildCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, rebuildDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -86,7 +86,7 @@ func (cmd InitCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd InitCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd InitCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, initDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -73,7 +73,7 @@ func (cmd InspectCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd InspectCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd InspectCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{}, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -109,7 +109,7 @@ func (cmd LogCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd LogCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd LogCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
return cmd.logWithLoggerFunc(ctx, commandStr, args, dEnv)
}
+1 -1
View File
@@ -94,7 +94,7 @@ func (cmd LoginCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd LoginCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd LoginCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, loginDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -78,7 +78,7 @@ func (cmd LsCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd LsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd LsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, lsDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+38 -32
View File
@@ -31,6 +31,7 @@ import (
"github.com/dolthub/dolt/go/libraries/doltcore/env/actions"
"github.com/dolthub/dolt/go/libraries/doltcore/merge"
"github.com/dolthub/dolt/go/libraries/utils/argparser"
"github.com/dolthub/dolt/go/libraries/utils/set"
"github.com/dolthub/dolt/go/store/datas"
)
@@ -77,7 +78,7 @@ func (cmd MergeCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd MergeCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd MergeCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cli.CreateMergeArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, mergeDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
@@ -98,7 +99,7 @@ func (cmd MergeCmd) Exec(ctx context.Context, commandStr string, args []string,
var verr errhand.VerboseError
if apr.Contains(cli.AbortParam) {
mergeActive, err := dEnv.IsMergeActive(ctx)
mergeActive, err := isMergeActive(ctx, dEnv)
if err != nil {
cli.PrintErrln("fatal:", err.Error())
return 1
@@ -130,7 +131,7 @@ func (cmd MergeCmd) Exec(ctx context.Context, commandStr string, args []string,
}
if verr == nil {
mergeActive, err := dEnv.IsMergeActive(ctx)
mergeActive, err := isMergeActive(ctx, dEnv)
if err != nil {
cli.PrintErrln(err.Error())
return 1
@@ -190,28 +191,33 @@ func (cmd MergeCmd) Exec(ctx context.Context, commandStr string, args []string,
return handleCommitErr(ctx, dEnv, verr, usage)
}
func getUnmergedTableCount(ctx context.Context, root *doltdb.RootValue) (int, error) {
conflicted, err := root.TablesInConflict(ctx)
func isMergeActive(ctx context.Context, denv *env.DoltEnv) (bool, error) {
ws, err := denv.WorkingSet(ctx)
if err != nil {
return 0, err
return false, err
}
cved, err := root.TablesWithConstraintViolations(ctx)
if err != nil {
return 0, err
}
uniqued := make(map[string]interface{})
for _, t := range conflicted {
uniqued[t] = struct{}{}
}
for _, t := range cved {
uniqued[t] = struct{}{}
}
var unmergedTableCount int
for range uniqued {
unmergedTableCount++
return ws.MergeActive(), nil
}
func getUnmergedTableCount(ctx context.Context, ws *doltdb.WorkingSet) (int, error) {
unmerged := set.NewStrSet(nil)
if ws.MergeState() != nil {
unmerged.Add(ws.MergeState().TablesWithSchemaConflicts()...)
}
return unmergedTableCount, nil
conflicted, err := ws.WorkingRoot().TablesWithDataConflicts(ctx)
if err != nil {
return 0, err
}
unmerged.Add(conflicted...)
cved, err := ws.WorkingRoot().TablesWithConstraintViolations(ctx)
if err != nil {
return 0, err
}
unmerged.Add(cved...)
return unmerged.Size(), nil
}
func validateMergeSpec(ctx context.Context, spec *merge.MergeSpec) errhand.VerboseError {
@@ -308,13 +314,13 @@ func printConflictsAndViolations(tblToStats map[string]*merge.MergeStats) (confl
hasConflicts := false
hasConstraintViolations := false
for tblName, stats := range tblToStats {
if stats.Operation == merge.TableModified && (stats.Conflicts > 0 || stats.ConstraintViolations > 0) {
if stats.HasArtifacts() {
cli.Println("Auto-merging", tblName)
if stats.Conflicts > 0 {
if stats.HasConflicts() {
cli.Println("CONFLICT (content): Merge conflict in", tblName)
hasConflicts = true
}
if stats.ConstraintViolations > 0 {
if stats.HasConstraintViolations() {
cli.Println("CONSTRAINT VIOLATION (content): Merge created constraint violation in", tblName)
hasConstraintViolations = true
}
@@ -332,10 +338,10 @@ func printModifications(tblToStats map[string]*merge.MergeStats) {
rowsChanged := 0
var tbls []string
for tblName, stats := range tblToStats {
if stats.Operation == merge.TableModified && stats.Conflicts == 0 && stats.ConstraintViolations == 0 {
if stats.Operation == merge.TableModified && stats.DataConflicts == 0 && stats.ConstraintViolations == 0 {
tbls = append(tbls, tblName)
nameLen := len(tblName)
modCount := stats.Adds + stats.Modifications + stats.Deletes + stats.Conflicts
modCount := stats.Adds + stats.Modifications + stats.Deletes + stats.DataConflicts
if nameLen > maxNameLen {
maxNameLen = nameLen
@@ -346,7 +352,7 @@ func printModifications(tblToStats map[string]*merge.MergeStats) {
}
rowsAdded += stats.Adds
rowsChanged += stats.Modifications + stats.Conflicts
rowsChanged += stats.Modifications + stats.DataConflicts
rowsDeleted += stats.Deletes
}
}
@@ -362,7 +368,7 @@ func printModifications(tblToStats map[string]*merge.MergeStats) {
for _, tbl := range tbls {
stats := tblToStats[tbl]
if stats.Operation == merge.TableModified {
modCount := stats.Adds + stats.Modifications + stats.Deletes + stats.Conflicts
modCount := stats.Adds + stats.Modifications + stats.Deletes + stats.DataConflicts
modCountStr := strconv.FormatInt(int64(modCount), 10)
visualizedChanges := visualizeChangeTypes(stats, maxModCount)
@@ -422,12 +428,12 @@ func fillStringWithChar(ch rune, strLen int) string {
}
func handleMergeErr(ctx context.Context, dEnv *env.DoltEnv, mergeErr error, hasConflicts, hasConstraintViolations bool, usage cli.UsagePrinter) int {
wRoot, err := dEnv.WorkingRoot(ctx)
ws, err := dEnv.WorkingSet(ctx)
if err != nil {
cli.PrintErrln(err.Error())
return 1
}
unmergedCnt, err := getUnmergedTableCount(ctx, wRoot)
unmergedCnt, err := getUnmergedTableCount(ctx, ws)
if err != nil {
cli.PrintErrln(err.Error())
return 1
@@ -514,7 +520,7 @@ func executeNoFFMergeAndCommit(ctx context.Context, dEnv *env.DoltEnv, spec *mer
return tblToStats, err
}
pendingCommit, err := actions.GetCommitStaged(ctx, roots, ws.MergeActive(), mergeParentCommits, dEnv.DbData().Ddb, actions.CommitStagedProps{
pendingCommit, err := actions.GetCommitStaged(ctx, roots, ws, mergeParentCommits, dEnv.DbData().Ddb, actions.CommitStagedProps{
Message: msg,
Date: spec.Date,
AllowEmpty: spec.AllowEmpty,
@@ -593,7 +599,7 @@ func getCommitMsgForMerge(ctx context.Context, dEnv *env.DoltEnv, userDefinedMsg
// hasConflictOrViolations checks for conflicts or constraint violation regardless of a table being modified
func hasConflictOrViolations(tblToStats map[string]*merge.MergeStats) bool {
for _, tblStats := range tblToStats {
if tblStats.Conflicts > 0 || tblStats.ConstraintViolations > 0 {
if tblStats.HasArtifacts() {
return true
}
}
+1 -1
View File
@@ -65,7 +65,7 @@ func (cmd MergeBaseCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd MergeBaseCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd MergeBaseCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, mergeBaseDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -75,7 +75,7 @@ func (cmd MigrateCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd MigrateCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd MigrateCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, migrateDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -68,7 +68,7 @@ func (cmd PullCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd PullCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd PullCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cli.CreatePullArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, pullDocs, ap))
+1 -1
View File
@@ -80,7 +80,7 @@ func (cmd PushCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd PushCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd PushCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, pushDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -84,7 +84,7 @@ func (cmd ReadTablesCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd ReadTablesCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ReadTablesCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, readTablesDocs, ap))
+1 -1
View File
@@ -101,7 +101,7 @@ func (cmd RemoteCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd RemoteCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd RemoteCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, remoteDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -81,7 +81,7 @@ func (cmd ResetCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd ResetCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ResetCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cli.CreateResetArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, resetDocContent, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -64,7 +64,7 @@ func (cmd RevertCmd) ArgParser() *argparser.ArgParser {
}
// Exec implements the interface cli.Command.
func (cmd RevertCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd RevertCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cli.CreateRevertArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, revertDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -80,7 +80,7 @@ func (cmd RootsCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd RootsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd RootsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, _ := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, cli.CommandDocumentationContent{}, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -74,7 +74,7 @@ func (cmd ExportCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd ExportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ExportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, schExportDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -160,7 +160,7 @@ func (cmd ImportCmd) ArgParser() *argparser.ArgParser {
// Exec implements the import schema command that will take a file and infer it's schema, and then create a table matching that schema.
// Exec executes the command
func (cmd ImportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ImportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, schImportDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -73,7 +73,7 @@ func (cmd ShowCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd ShowCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ShowCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, tblSchemaDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -64,7 +64,7 @@ func (cmd TagsCmd) ArgParser() *argparser.ArgParser {
return ap
}
func (cmd TagsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd TagsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, tblTagsDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -65,7 +65,7 @@ func (cmd UpdateTagCmd) ArgParser() *argparser.ArgParser {
return ap
}
func (cmd UpdateTagCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd UpdateTagCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, updateTagDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -74,7 +74,7 @@ func (cmd SendMetricsCmd) ArgParser() *argparser.ArgParser {
// Exec is the implementation of the command that flushes the events to the grpc service
// Exec executes the command
func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd SendMetricsCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
if dEnv.DoltDB != nil { // see go/cmd/dolt/dolt.go:interceptSendMetrics()
cli.PrintErrln("expected DoltEnv without DoltDB")
return 1
+1 -1
View File
@@ -90,7 +90,7 @@ func (cmd ShowCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd ShowCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ShowCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, showDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -179,7 +179,7 @@ func (cmd SqlCmd) RequiresRepo() bool {
// Exec executes the command
// Unlike other commands, sql doesn't set a new working root directly, as the SQL layer updates the working set as
// necessary when committing work.
func (cmd SqlCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd SqlCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, sqlDocs, ap))
+1 -1
View File
@@ -99,7 +99,7 @@ func (cmd SqlClientCmd) Hidden() bool {
return false
}
func (cmd SqlClientCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd SqlClientCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, _ := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, sqlClientDocs, ap))
+2 -2
View File
@@ -155,7 +155,7 @@ func (cmd SqlServerCmd) ArgParserWithName(name string) *argparser.ArgParser {
ap.SupportsString(allowCleartextPasswordsFlag, "", "allow-cleartext-passwords", "Allows use of cleartext passwords. Defaults to false.")
ap.SupportsOptionalString(socketFlag, "", "socket file", "Path for the unix socket file. Defaults to '/tmp/mysql.sock'.")
ap.SupportsUint(remotesapiPortFlag, "", "remotesapi port", "Sets the port for a server which can expose the databases in this sql-server over remotesapi.")
ap.SupportsString(goldenMysqlConn, "", "mysql connection string", "Provides a connection string to a MySQL instance to be user to validate query results")
ap.SupportsString(goldenMysqlConn, "", "mysql connection string", "Provides a connection string to a MySQL instance to be used to validate query results")
return ap
}
@@ -173,7 +173,7 @@ func (cmd SqlServerCmd) RequiresRepo() bool {
}
// Exec executes the command
func (cmd SqlServerCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd SqlServerCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
controller := NewServerController()
newCtx, cancelF := context.WithCancel(context.Background())
go func() {
+1 -1
View File
@@ -63,7 +63,7 @@ func (cmd StashClearCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd StashClearCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd StashClearCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
if !dEnv.DoltDB.Format().UsesFlatbuffers() {
cli.PrintErrln(ErrStashNotSupportedForOldFormat.Error())
return 1
+1 -1
View File
@@ -66,7 +66,7 @@ func (cmd StashDropCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd StashDropCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd StashDropCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
if !dEnv.DoltDB.Format().UsesFlatbuffers() {
cli.PrintErrln(ErrStashNotSupportedForOldFormat.Error())
return 1
+1 -1
View File
@@ -63,7 +63,7 @@ func (cmd StashListCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd StashListCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd StashListCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
if !dEnv.DoltDB.Format().UsesFlatbuffers() {
cli.PrintErrln(ErrStashNotSupportedForOldFormat.Error())
return 1
+5 -5
View File
@@ -70,7 +70,7 @@ func (cmd StashPopCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd StashPopCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd StashPopCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
if !dEnv.DoltDB.Format().UsesFlatbuffers() {
cli.PrintErrln(ErrStashNotSupportedForOldFormat.Error())
return 1
@@ -148,14 +148,14 @@ func applyStashAtIdx(ctx context.Context, dEnv *env.DoltEnv, curWorkingRoot *dol
}
opts := editor.Options{Deaf: dEnv.BulkDbEaFactory(), Tempdir: tmpDir}
mergedRoot, mergeStats, err := merge.MergeRoots(ctx, curWorkingRoot, stashRoot, parentRoot, stashRoot, parentCommit, opts, merge.MergeOpts{IsCherryPick: false})
result, err := merge.MergeRoots(ctx, curWorkingRoot, stashRoot, parentRoot, stashRoot, parentCommit, opts, merge.MergeOpts{IsCherryPick: false})
if err != nil {
return false, err
}
var tablesWithConflict []string
for tbl, stats := range mergeStats {
if stats.Conflicts > 0 {
for tbl, stats := range result.Stats {
if stats.HasConflicts() {
tablesWithConflict = append(tablesWithConflict, tbl)
}
}
@@ -168,7 +168,7 @@ func applyStashAtIdx(ctx context.Context, dEnv *env.DoltEnv, curWorkingRoot *dol
return false, nil
}
err = dEnv.UpdateWorkingRoot(ctx, mergedRoot)
err = dEnv.UpdateWorkingRoot(ctx, result.Root)
if err != nil {
return false, err
}
+1 -1
View File
@@ -88,7 +88,7 @@ func (cmd StashCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd StashCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd StashCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
if !dEnv.DoltDB.Format().UsesFlatbuffers() {
cli.PrintErrln(ErrStashNotSupportedForOldFormat.Error())
return 1
+18 -19
View File
@@ -61,7 +61,7 @@ func (cmd StatusCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd StatusCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd StatusCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, _ := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, statusDocs, ap))
cli.ParseArgsOrDie(ap, args, help)
@@ -76,26 +76,25 @@ func (cmd StatusCmd) Exec(ctx context.Context, commandStr string, args []string,
return handleStatusVErr(err)
}
workingTblsInConflict, _, _, err := merge.GetTablesInConflict(ctx, roots)
ws, err := dEnv.WorkingSet(ctx)
if err != nil {
handleStatusVErr(err)
}
as, err := merge.GetMergeArtifactStatus(ctx, ws)
if err != nil {
handleStatusVErr(err)
}
err = PrintStatus(ctx, dEnv, staged, notStaged, as)
if err != nil {
return handleStatusVErr(err)
}
workingTblsWithViolations, _, _, err := merge.GetTablesWithConstraintViolations(ctx, roots)
if err != nil {
return handleStatusVErr(err)
}
err = PrintStatus(ctx, dEnv, staged, notStaged, workingTblsInConflict, workingTblsWithViolations)
if err != nil {
return handleStatusVErr(err)
}
return 0
}
// TODO: working docs in conflict param not used here
func PrintStatus(ctx context.Context, dEnv *env.DoltEnv, stagedTbls, notStagedTbls []diff.TableDelta, workingTblsInConflict, workingTblsWithViolations []string) error {
func PrintStatus(ctx context.Context, dEnv *env.DoltEnv, stagedTbls, notStagedTbls []diff.TableDelta, as merge.ArtifactStatus) error {
cli.Printf(branchHeader, dEnv.RepoStateReader().CWBHeadRef().GetPath())
err := printRemoteRefTrackingInfo(ctx, dEnv)
@@ -103,17 +102,17 @@ func PrintStatus(ctx context.Context, dEnv *env.DoltEnv, stagedTbls, notStagedTb
return err
}
mergeActive, err := dEnv.IsMergeActive(ctx)
mergeActive, err := isMergeActive(ctx, dEnv)
if err != nil {
return err
}
if mergeActive {
if len(workingTblsInConflict) > 0 && len(workingTblsWithViolations) > 0 {
if as.HasConflicts() && as.HasConstraintViolations() {
cli.Println(fmt.Sprintf(unmergedTablesHeader, "conflicts and constraint violations"))
} else if len(workingTblsInConflict) > 0 {
} else if as.HasConflicts() {
cli.Println(fmt.Sprintf(unmergedTablesHeader, "conflicts"))
} else if len(workingTblsWithViolations) > 0 {
} else if as.HasConstraintViolations() {
cli.Println(fmt.Sprintf(unmergedTablesHeader, "constraint violations"))
} else {
cli.Println(allMergedHeader)
@@ -121,7 +120,7 @@ func PrintStatus(ctx context.Context, dEnv *env.DoltEnv, stagedTbls, notStagedTb
}
n := printStagedDiffs(cli.CliOut, stagedTbls, true)
n = PrintDiffsNotStaged(ctx, dEnv, cli.CliOut, notStagedTbls, true, n, workingTblsInConflict, workingTblsWithViolations)
n = PrintDiffsNotStaged(ctx, dEnv, cli.CliOut, notStagedTbls, true, n, as)
if !mergeActive && n == 0 {
cli.Println("nothing to commit, working tree clean")
+1 -1
View File
@@ -71,7 +71,7 @@ func (cmd TagCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd TagCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd TagCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cli.CreateTagArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, tagDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -70,7 +70,7 @@ func (cmd CpCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd CpCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd CpCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, tblCpDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -185,7 +185,7 @@ func (cmd ExportCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd ExportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ExportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
_, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, exportDocs, ap))
+1 -1
View File
@@ -372,7 +372,7 @@ func (cmd ImportCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd ImportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd ImportCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, importDocs, ap))
+1 -1
View File
@@ -72,7 +72,7 @@ func (cmd MvCmd) EventType() eventsapi.ClientEventType {
}
// Exec executes the command
func (cmd MvCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd MvCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, tblMvDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -66,7 +66,7 @@ func (cmd RmCmd) ArgParser() *argparser.ArgParser {
}
// Exec executes the command
func (cmd RmCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd RmCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
ap := cmd.ArgParser()
help, usage := cli.HelpAndUsagePrinters(cli.CommandDocsForCommandString(commandStr, tblRmDocs, ap))
apr := cli.ParseArgsOrDie(ap, args, help)
+1 -1
View File
@@ -60,7 +60,7 @@ func (cmd VersionCmd) ArgParser() *argparser.ArgParser {
// Version displays the version of the running dolt client
// Exec executes the command
func (cmd VersionCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx *cli.CliContext) int {
func (cmd VersionCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int {
cli.Println("dolt version", cmd.VersionStr)
if dEnv.HasDoltDir() && dEnv.RSLoadErr == nil && !cli.CheckEnvIsValid(dEnv) {
+24 -1
View File
@@ -353,7 +353,24 @@ func (rcv *MergeState) FromCommitSpecStr() []byte {
return nil
}
const MergeStateNumFields = 3
func (rcv *MergeState) UnmergableTables(j int) []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.ByteVector(a + flatbuffers.UOffsetT(j*4))
}
return nil
}
func (rcv *MergeState) UnmergableTablesLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
const MergeStateNumFields = 4
func MergeStateStart(builder *flatbuffers.Builder) {
builder.StartObject(MergeStateNumFields)
@@ -373,6 +390,12 @@ func MergeStateStartFromCommitAddrVector(builder *flatbuffers.Builder, numElems
func MergeStateAddFromCommitSpecStr(builder *flatbuffers.Builder, fromCommitSpecStr flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(fromCommitSpecStr), 0)
}
func MergeStateAddUnmergableTables(builder *flatbuffers.Builder, unmergableTables flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(unmergableTables), 0)
}
func MergeStateStartUnmergableTablesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func MergeStateEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}
+2 -2
View File
@@ -694,7 +694,7 @@ func (root *RootValue) getTableMap(ctx context.Context) (tableMap, error) {
return root.st.GetTablesMap(ctx, root.vrw, root.ns)
}
func (root *RootValue) TablesInConflict(ctx context.Context) ([]string, error) {
func (root *RootValue) TablesWithDataConflicts(ctx context.Context) ([]string, error) {
names, err := root.GetTableNames(ctx)
if err != nil {
return nil, err
@@ -747,7 +747,7 @@ func (root *RootValue) TablesWithConstraintViolations(ctx context.Context) ([]st
}
func (root *RootValue) HasConflicts(ctx context.Context) (bool, error) {
cnfTbls, err := root.TablesInConflict(ctx)
cnfTbls, err := root.TablesWithDataConflicts(ctx)
if err != nil {
return false, err
@@ -277,6 +277,9 @@ const (
// TableOfTablesWithViolationsName is the constraint violations system table name
TableOfTablesWithViolationsName = "dolt_constraint_violations"
// SchemaConflictsTableName is the schema conflicts system table name
SchemaConflictsTableName = "dolt_schema_conflicts"
// BranchesTableName is the branches system table name
BranchesTableName = "dolt_branches"
+99 -6
View File
@@ -19,6 +19,8 @@ import (
"fmt"
"time"
"github.com/dolthub/dolt/go/libraries/doltcore/schema"
"github.com/dolthub/dolt/go/libraries/doltcore/ref"
"github.com/dolthub/dolt/go/store/datas"
"github.com/dolthub/dolt/go/store/hash"
@@ -30,8 +32,22 @@ type MergeState struct {
// the source commit
commit *Commit
// the spec string that was used to specify |commit|
commitSpecStr string
preMergeWorking *RootValue
commitSpecStr string
preMergeWorking *RootValue
unmergableTables []string
}
// todo(andy): this might make more sense in pkg merge
type SchemaConflict struct {
ToSch, FromSch schema.Schema
ToFks, FromFks []ForeignKey
ToParentSchemas map[string]schema.Schema
FromParentSchemas map[string]schema.Schema
toTbl, fromTbl *Table
}
func (sc SchemaConflict) GetConflictingTables() (ours, theirs *Table) {
return sc.toTbl, sc.fromTbl
}
// TodoWorkingSetMeta returns an incomplete WorkingSetMeta, suitable for methods that don't have the means to construct
@@ -63,6 +79,72 @@ func (m MergeState) PreMergeWorkingRoot() *RootValue {
return m.preMergeWorking
}
type SchemaConflictFn func(table string, conflict SchemaConflict) error
func (m MergeState) HasSchemaConflicts() bool {
return len(m.unmergableTables) > 0
}
func (m MergeState) TablesWithSchemaConflicts() []string {
return m.unmergableTables
}
func (m MergeState) IterSchemaConflicts(ctx context.Context, ddb *DoltDB, cb SchemaConflictFn) (err error) {
var to, from *RootValue
to = m.preMergeWorking
if from, err = m.commit.GetRootValue(ctx); err != nil {
return err
}
toFKs, err := to.GetForeignKeyCollection(ctx)
if err != nil {
return err
}
toSchemas, err := to.GetAllSchemas(ctx)
if err != nil {
return err
}
fromFKs, err := from.GetForeignKeyCollection(ctx)
if err != nil {
return err
}
fromSchemas, err := from.GetAllSchemas(ctx)
if err != nil {
return err
}
for _, name := range m.unmergableTables {
var sc SchemaConflict
if sc.toTbl, _, err = to.GetTable(ctx, name); err != nil {
return err
}
// todo: handle schema conflicts for renamed tables
if sc.fromTbl, _, err = from.GetTable(ctx, name); err != nil {
return err
}
if sc.ToSch, err = sc.toTbl.GetSchema(ctx); err != nil {
return err
}
if sc.FromSch, err = sc.fromTbl.GetSchema(ctx); err != nil {
return err
}
sc.ToFks, _ = toFKs.KeysForTable(name)
sc.ToParentSchemas = toSchemas
sc.FromFks, _ = fromFKs.KeysForTable(name)
sc.FromParentSchemas = fromSchemas
if err = cb(name, sc); err != nil {
return err
}
}
return nil
}
type WorkingSet struct {
Name string
meta *datas.WorkingSetMeta
@@ -96,6 +178,11 @@ func (ws WorkingSet) WithMergeState(mergeState *MergeState) *WorkingSet {
return &ws
}
func (ws WorkingSet) WithUnmergableTables(tables []string) *WorkingSet {
ws.mergeState.unmergableTables = tables
return &ws
}
func (ws WorkingSet) StartMerge(commit *Commit, commitSpecStr string) *WorkingSet {
ws.mergeState = &MergeState{
commit: commit,
@@ -207,10 +294,16 @@ func NewWorkingSet(ctx context.Context, name string, vrw types.ValueReadWriter,
return nil, err
}
unmergableTables, err := dsws.MergeState.UnmergableTables(ctx, vrw)
if err != nil {
return nil, err
}
mergeState = &MergeState{
commit: commit,
commitSpecStr: commitSpec,
preMergeWorking: preMergeWorkingRoot,
commit: commit,
commitSpecStr: commitSpec,
preMergeWorking: preMergeWorkingRoot,
unmergableTables: unmergableTables,
}
}
@@ -286,7 +379,7 @@ func (ws *WorkingSet) writeValues(ctx context.Context, db *DoltDB) (
return types.Ref{}, types.Ref{}, nil, err
}
mergeState, err = datas.NewMergeState(ctx, db.vrw, preMergeWorking, dCommit, ws.mergeState.commitSpecStr)
mergeState, err = datas.NewMergeState(ctx, db.vrw, preMergeWorking, dCommit, ws.mergeState.commitSpecStr, ws.mergeState.unmergableTables)
if err != nil {
return types.Ref{}, types.Ref{}, nil, err
}
@@ -248,7 +248,7 @@ func (mr *MultiRepoTestSetup) CommitWithWorkingSet(dbName string) *doltdb.Commit
if err != nil {
panic("couldn't get roots: " + err.Error())
}
pendingCommit, err := actions.GetCommitStaged(ctx, roots, ws.MergeActive(), mergeParentCommits, dEnv.DbData().Ddb, actions.CommitStagedProps{
pendingCommit, err := actions.GetCommitStaged(ctx, roots, ws, mergeParentCommits, dEnv.DbData().Ddb, actions.CommitStagedProps{
Message: "auto commit",
Date: t,
AllowEmpty: true,
+10 -3
View File
@@ -37,7 +37,7 @@ type CommitStagedProps struct {
func GetCommitStaged(
ctx context.Context,
roots doltdb.Roots,
mergeActive bool,
ws *doltdb.WorkingSet,
mergeParents []*doltdb.Commit,
db *doltdb.DoltDB,
props CommitStagedProps,
@@ -61,13 +61,13 @@ func GetCommitStaged(
}
isEmpty := len(staged) == 0
allowEmpty := mergeActive || props.AllowEmpty || props.Amend
allowEmpty := ws.MergeActive() || props.AllowEmpty || props.Amend
if isEmpty && !allowEmpty {
return nil, NothingStaged{notStaged}
}
if !props.Force {
inConflict, err := roots.Working.TablesInConflict(ctx)
inConflict, err := roots.Working.TablesWithDataConflicts(ctx)
if err != nil {
return nil, err
}
@@ -81,6 +81,13 @@ func GetCommitStaged(
if len(violatesConstraints) > 0 {
return nil, NewTblHasConstraintViolations(violatesConstraints)
}
if ws.MergeActive() {
schConflicts := ws.MergeState().TablesWithSchemaConflicts()
if len(schConflicts) > 0 {
return nil, NewTblSchemaConflictError(schConflicts)
}
}
}
if !props.Force {
+9 -4
View File
@@ -23,10 +23,11 @@ import (
type tblErrorType string
const (
tblErrInvalid tblErrorType = "invalid"
tblErrTypeNotExist tblErrorType = "do not exist"
tblErrTypeInConflict tblErrorType = "are in conflict"
tblErrTypeConstViols tblErrorType = "have constraint violations"
tblErrInvalid tblErrorType = "invalid"
tblErrTypeNotExist tblErrorType = "do not exist"
tblErrTypeInConflict tblErrorType = "are in conflict"
tblErrTypeSchConflict tblErrorType = "have schema conflicts"
tblErrTypeConstViols tblErrorType = "have constraint violations"
)
type TblError struct {
@@ -42,6 +43,10 @@ func NewTblInConflictError(tbls []string) TblError {
return TblError{tbls, tblErrTypeInConflict}
}
func NewTblSchemaConflictError(tbls []string) TblError {
return TblError{tbls, tblErrTypeSchConflict}
}
func NewTblHasConstraintViolations(tbls []string) TblError {
return TblError{tbls, tblErrTypeConstViols}
}
-51
View File
@@ -788,57 +788,6 @@ func (dEnv *DoltEnv) NewWorkingSetMeta(message string) *datas.WorkingSetMeta {
}
}
func (dEnv *DoltEnv) ClearMerge(ctx context.Context) error {
ws, err := dEnv.WorkingSet(ctx)
if err != nil {
return err
}
h, err := ws.HashOf()
if err != nil {
return err
}
return dEnv.DoltDB.UpdateWorkingSet(ctx, ws.Ref(), ws.ClearMerge(), h, dEnv.workingSetMeta())
}
// StartMerge updates the WorkingSet with merge information. |commit| is the
// source commit of the merge and |commitSpecStr| is how that |commit| was
// specified. Typically, |commitSpecStr| is specified by the user, but it could
// also be specified by a transaction merge.
func (dEnv *DoltEnv) StartMerge(ctx context.Context, commit *doltdb.Commit, commitSpecStr string) error {
ws, err := dEnv.WorkingSet(ctx)
if err != nil {
return err
}
h, err := ws.HashOf()
if err != nil {
return err
}
return dEnv.DoltDB.UpdateWorkingSet(ctx, ws.Ref(), ws.StartMerge(commit, commitSpecStr), h, dEnv.workingSetMeta())
}
func (dEnv *DoltEnv) IsMergeActive(ctx context.Context) (bool, error) {
ws, err := dEnv.WorkingSet(ctx)
if err != nil {
return false, err
}
return ws.MergeActive(), nil
}
func (dEnv *DoltEnv) GetTablesWithConflicts(ctx context.Context) ([]string, error) {
root, err := dEnv.WorkingRoot(ctx)
if err != nil {
return nil, err
}
return root.TablesInConflict(ctx)
}
func (dEnv *DoltEnv) CredsDir() (string, error) {
return getCredsDir(dEnv.hdp)
}
+28 -43
View File
@@ -24,7 +24,6 @@ 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/store/hash"
)
@@ -116,15 +115,14 @@ func NewMergeSpec(ctx context.Context, rsr env.RepoStateReader, ddb *doltdb.Dolt
func ExecNoFFMerge(ctx context.Context, dEnv *env.DoltEnv, spec *MergeSpec) (map[string]*MergeStats, error) {
mergedRoot, err := spec.MergeC.GetRootValue(ctx)
if err != nil {
return nil, ErrFailedToReadDatabase
}
result := &Result{Root: mergedRoot, Stats: make(map[string]*MergeStats)}
tblToStats := make(map[string]*MergeStats)
err = mergedRootToWorking(ctx, false, dEnv, mergedRoot, spec.WorkingDiffs, spec.MergeC, spec.MergeCSpecStr, tblToStats)
err = mergedRootToWorking(ctx, false, dEnv, result, spec.WorkingDiffs, spec.MergeC, spec.MergeCSpecStr)
return tblToStats, err
return result.Stats, err
}
func applyChanges(ctx context.Context, root *doltdb.RootValue, workingDiffs map[string]hash.Hash) (*doltdb.RootValue, error) {
@@ -182,74 +180,61 @@ func ExecuteMerge(ctx context.Context, dEnv *env.DoltEnv, spec *MergeSpec) (map[
return nil, err
}
opts := editor.Options{Deaf: dEnv.BulkDbEaFactory(), Tempdir: tmpDir}
mergedRoot, tblToStats, err := MergeCommits(ctx, spec.HeadC, spec.MergeC, opts)
result, err := MergeCommits(ctx, spec.HeadC, spec.MergeC, opts)
if err != nil {
switch err {
case doltdb.ErrUpToDate:
return tblToStats, fmt.Errorf("already up to date; %w", err)
return result.Stats, fmt.Errorf("already up to date; %w", err)
case ErrFastForward:
panic("fast forward merge")
}
return tblToStats, err
return nil, err
}
return tblToStats, mergedRootToWorking(ctx, spec.Squash, dEnv, mergedRoot, spec.WorkingDiffs, spec.MergeC, spec.MergeCSpecStr, tblToStats)
err = mergedRootToWorking(ctx, spec.Squash, dEnv, result, spec.WorkingDiffs, spec.MergeC, spec.MergeCSpecStr)
return result.Stats, nil
}
// TODO: change this to be functional and not write to repo state
func mergedRootToWorking(
ctx context.Context,
squash bool,
dEnv *env.DoltEnv,
mergedRoot *doltdb.RootValue,
result *Result,
workingDiffs map[string]hash.Hash,
cm2 *doltdb.Commit,
cm2SpecStr string,
tblToStats map[string]*MergeStats,
) error {
var err error
workingRoot := mergedRoot
) (err error) {
staged, working := result.Root, result.Root
if len(workingDiffs) > 0 {
workingRoot, err = applyChanges(ctx, mergedRoot, workingDiffs)
working, err = applyChanges(ctx, working, workingDiffs)
if err != nil {
return err
}
}
if !squash {
err = dEnv.StartMerge(ctx, cm2, cm2SpecStr)
if err != nil {
return actions.ErrFailedToSaveRepoState
}
}
err = dEnv.UpdateWorkingRoot(context.Background(), workingRoot)
ws, err := dEnv.WorkingSet(ctx)
if err != nil {
return err
}
conflicts, constraintViolations := conflictsAndViolations(tblToStats)
if len(conflicts) > 0 || len(constraintViolations) > 0 {
if !squash || result.HasSchemaConflicts() {
ws = ws.StartMerge(cm2, cm2SpecStr)
tt := SchemaConflictTableNames(result.SchemaConflicts)
ws = ws.WithUnmergableTables(tt)
}
ws = ws.WithWorkingRoot(working)
if !result.HasMergeArtifacts() {
ws = ws.WithStagedRoot(staged)
}
if err = dEnv.UpdateWorkingSet(ctx, ws); err != nil {
return err
}
return dEnv.UpdateStagedRoot(context.Background(), mergedRoot)
}
// conflictsAndViolations returns array of conflicts and constraintViolations
func conflictsAndViolations(tblToStats map[string]*MergeStats) (conflicts []string, constraintViolations []string) {
for tblName, stats := range tblToStats {
if stats.Operation == TableModified && (stats.Conflicts > 0 || stats.ConstraintViolations > 0) {
if stats.Conflicts > 0 {
conflicts = append(conflicts, tblName)
}
if stats.ConstraintViolations > 0 {
constraintViolations = append(constraintViolations, tblName)
}
}
if result.HasMergeArtifacts() {
// this error is recoverable in some contexts
return doltdb.ErrUnresolvedConflictsOrViolations
}
return
}
@@ -125,10 +125,12 @@ func TestMerge(t *testing.T) {
defer dEnv.DoltDB.Close()
for _, tc := range setupCommon {
tc.exec(t, ctx, dEnv)
exit := tc.exec(t, ctx, dEnv)
require.Equal(t, 0, exit)
}
for _, tc := range test.setup {
tc.exec(t, ctx, dEnv)
exit := tc.exec(t, ctx, dEnv)
require.Equal(t, 0, exit)
}
root, err := dEnv.WorkingRoot(ctx)
@@ -245,10 +247,18 @@ func TestMergeConflicts(t *testing.T) {
defer dEnv.DoltDB.Close()
for _, tc := range setupCommon {
tc.exec(t, ctx, dEnv)
exit := tc.exec(t, ctx, dEnv)
// allow merge to fail with conflicts
if _, ok := tc.cmd.(cmd.MergeCmd); !ok {
require.Equal(t, 0, exit)
}
}
for _, tc := range test.setup {
tc.exec(t, ctx, dEnv)
exit := tc.exec(t, ctx, dEnv)
// allow merge to fail with conflicts
if _, ok := tc.cmd.(cmd.MergeCmd); !ok {
require.Equal(t, 0, exit)
}
}
root, err := dEnv.WorkingRoot(ctx)
@@ -250,7 +250,10 @@ func TestKeylessMergeConflicts(t *testing.T) {
for _, c := range cc {
exitCode := c.cmd.Exec(ctx, c.cmd.Name(), c.args, dEnv, nil)
require.Equal(t, 0, exitCode)
// allow merge to fail with conflicts
if _, ok := c.cmd.(cmd.MergeCmd); !ok {
require.Equal(t, 0, exitCode)
}
}
}
+110 -67
View File
@@ -45,28 +45,62 @@ var ErrMultipleViolationsForRow = errors.New("multiple violations for row not su
var ErrSameTblAddedTwice = goerrors.NewKind("table with same name '%s' added in 2 commits can't be merged")
func MergeCommits(ctx context.Context, commit, mergeCommit *doltdb.Commit, opts editor.Options) (*doltdb.RootValue, map[string]*MergeStats, error) {
func MergeCommits(ctx context.Context, commit, mergeCommit *doltdb.Commit, opts editor.Options) (*Result, error) {
ancCommit, err := doltdb.GetCommitAncestor(ctx, commit, mergeCommit)
if err != nil {
return nil, nil, err
return nil, err
}
ourRoot, err := commit.GetRootValue(ctx)
if err != nil {
return nil, nil, err
return nil, err
}
theirRoot, err := mergeCommit.GetRootValue(ctx)
if err != nil {
return nil, nil, err
return nil, err
}
ancRoot, err := ancCommit.GetRootValue(ctx)
if err != nil {
return nil, nil, err
return nil, err
}
return MergeRoots(ctx, ourRoot, theirRoot, ancRoot, mergeCommit, ancCommit, opts, MergeOpts{IsCherryPick: false})
mo := MergeOpts{
IsCherryPick: false,
KeepSchemaConflicts: true,
}
return MergeRoots(ctx, ourRoot, theirRoot, ancRoot, mergeCommit, ancCommit, opts, mo)
}
type Result struct {
Root *doltdb.RootValue
SchemaConflicts []SchemaConflict
Stats map[string]*MergeStats
}
func (r Result) HasSchemaConflicts() bool {
return len(r.SchemaConflicts) > 0
}
func (r Result) HasMergeArtifacts() bool {
if r.HasSchemaConflicts() {
return true
}
for _, stats := range r.Stats {
if stats.HasArtifacts() {
return true
}
}
return false
}
func SchemaConflictTableNames(sc []SchemaConflict) (tables []string) {
tables = make([]string, len(sc))
for i := range sc {
tables[i] = sc[i].TableName
}
return
}
// MergeRoots three-way merges |ourRoot|, |theirRoot|, and |ancRoot| and returns
@@ -88,18 +122,23 @@ func MergeRoots(
theirs, ancestor doltdb.Rootish,
opts editor.Options,
mergeOpts MergeOpts,
) (*doltdb.RootValue, map[string]*MergeStats, error) {
var conflictStash *conflictStash
var violationStash *violationStash
var err error
if !types.IsFormat_DOLT(ourRoot.VRW().Format()) {
) (*Result, error) {
var (
conflictStash *conflictStash
violationStash *violationStash
nbf *types.NomsBinFormat
err error
)
nbf = ourRoot.VRW().Format()
if !types.IsFormat_DOLT(nbf) {
ourRoot, conflictStash, err = stashConflicts(ctx, ourRoot)
if err != nil {
return nil, nil, err
return nil, err
}
ancRoot, violationStash, err = stashViolations(ctx, ancRoot)
if err != nil {
return nil, nil, err
return nil, err
}
}
@@ -112,7 +151,7 @@ func MergeRoots(
tblNames, err := doltdb.UnionTableNames(ctx, ourRoot, theirRoot)
if err != nil {
return nil, nil, err
return nil, err
}
tblToStats := make(map[string]*MergeStats)
@@ -127,28 +166,37 @@ func MergeRoots(
// TODO: merge based on a more durable table identity that persists across renames
merger, err := NewMerger(ourRoot, theirRoot, ancRoot, theirs, ancestor, ourRoot.VRW(), ourRoot.NodeStore())
if err != nil {
return nil, nil, err
return nil, err
}
var schConflicts []SchemaConflict
for _, tblName := range tblNames {
mergedTable, stats, err := merger.MergeTable(ctx, tblName, opts, mergeOpts)
if err != nil {
return nil, nil, err
return nil, err
}
if mergedTable.conflict.Count() > 0 {
if types.IsFormat_DOLT(nbf) {
schConflicts = append(schConflicts, mergedTable.conflict)
} else {
// return schema conflict as error
return nil, mergedTable.conflict
}
}
if mergedTable != nil {
if mergedTable.table != nil {
tblToStats[tblName] = stats
mergedRoot, err = mergedRoot.PutTable(ctx, tblName, mergedTable)
mergedRoot, err = mergedRoot.PutTable(ctx, tblName, mergedTable.table)
if err != nil {
return nil, nil, err
return nil, err
}
continue
}
newRootHasTable, err := mergedRoot.HasTable(ctx, tblName)
if err != nil {
return nil, nil, err
return nil, err
}
if newRootHasTable {
@@ -157,7 +205,7 @@ func MergeRoots(
mergedRoot, err = mergedRoot.RemoveTables(ctx, false, false, tblName)
if err != nil {
return nil, nil, err
return nil, err
}
} else {
// This is a deleted table that the merge root still has
@@ -170,57 +218,65 @@ func MergeRoots(
mergedFKColl, conflicts, err := ForeignKeysMerge(ctx, mergedRoot, ourRoot, theirRoot, ancRoot)
if err != nil {
return nil, nil, err
return nil, err
}
if len(conflicts) > 0 {
return nil, nil, fmt.Errorf("foreign key conflicts")
return nil, fmt.Errorf("foreign key conflicts")
}
mergedRoot, err = mergedRoot.PutForeignKeyCollection(ctx, mergedFKColl)
if err != nil {
return nil, nil, err
return nil, err
}
h, err := merger.rightSrc.HashOf()
if err != nil {
return nil, nil, err
return nil, err
}
mergedRoot, _, err = AddForeignKeyViolations(ctx, mergedRoot, ancRoot, nil, h)
if err != nil {
return nil, nil, err
return nil, err
}
if types.IsFormat_DOLT(ourRoot.VRW().Format()) {
err = getConstraintViolationStats(ctx, mergedRoot, tblToStats)
if err != nil {
return nil, nil, err
return nil, err
}
return mergedRoot, tblToStats, nil
return &Result{
Root: mergedRoot,
SchemaConflicts: schConflicts,
Stats: tblToStats,
}, nil
}
mergedRoot, err = mergeCVsWithStash(ctx, mergedRoot, violationStash)
if err != nil {
return nil, nil, err
return nil, err
}
err = getConstraintViolationStats(ctx, mergedRoot, tblToStats)
if err != nil {
return nil, nil, err
return nil, err
}
mergedHasConflicts := checkForConflicts(tblToStats)
if !conflictStash.Empty() && mergedHasConflicts {
return nil, nil, ErrCantOverwriteConflicts
return nil, ErrCantOverwriteConflicts
} else if !conflictStash.Empty() {
mergedRoot, err = applyConflictStash(ctx, conflictStash.Stash, mergedRoot)
if err != nil {
return nil, nil, err
return nil, err
}
}
return mergedRoot, tblToStats, nil
return &Result{
Root: mergedRoot,
SchemaConflicts: schConflicts,
Stats: tblToStats,
}, nil
}
// mergeCVsWithStash merges the table constraint violations in |stash| with |root|.
@@ -264,7 +320,7 @@ func mergeCVsWithStash(ctx context.Context, root *doltdb.RootValue, stash *viola
// checks if a conflict occurred during the merge
func checkForConflicts(tblToStats map[string]*MergeStats) bool {
for _, stat := range tblToStats {
if stat.Conflicts > 0 {
if stat.HasConflicts() {
return true
}
}
@@ -320,48 +376,35 @@ func MayHaveConstraintViolations(ctx context.Context, ancestor, merged *doltdb.R
return false, nil
}
func GetTablesInConflict(ctx context.Context, roots doltdb.Roots) (
workingInConflict, stagedInConflict, headInConflict []string,
err error,
) {
headInConflict, err = roots.Head.TablesInConflict(ctx)
if err != nil {
return nil, nil, nil, err
}
stagedInConflict, err = roots.Staged.TablesInConflict(ctx)
if err != nil {
return nil, nil, nil, err
}
workingInConflict, err = roots.Working.TablesInConflict(ctx)
if err != nil {
return nil, nil, nil, err
}
return workingInConflict, stagedInConflict, headInConflict, err
type ArtifactStatus struct {
SchemaConflictsTables []string
DataConflictTables []string
ConstraintViolationsTables []string
}
func GetTablesWithConstraintViolations(ctx context.Context, roots doltdb.Roots) (
workingViolations, stagedViolations, headViolations []string,
err error,
) {
headViolations, err = roots.Head.TablesWithConstraintViolations(ctx)
if err != nil {
return nil, nil, nil, err
func (as ArtifactStatus) HasConflicts() bool {
return len(as.DataConflictTables) > 0 || len(as.SchemaConflictsTables) > 0
}
func (as ArtifactStatus) HasConstraintViolations() bool {
return len(as.ConstraintViolationsTables) > 0
}
func GetMergeArtifactStatus(ctx context.Context, working *doltdb.WorkingSet) (as ArtifactStatus, err error) {
if working.MergeActive() {
as.SchemaConflictsTables = working.MergeState().TablesWithSchemaConflicts()
}
stagedViolations, err = roots.Staged.TablesWithConstraintViolations(ctx)
as.DataConflictTables, err = working.WorkingRoot().TablesWithDataConflicts(ctx)
if err != nil {
return nil, nil, nil, err
return as, err
}
workingViolations, err = roots.Working.TablesWithConstraintViolations(ctx)
as.ConstraintViolationsTables, err = working.WorkingRoot().TablesWithConstraintViolations(ctx)
if err != nil {
return nil, nil, nil, err
return as, err
}
return workingViolations, stagedViolations, headViolations, err
return
}
// MergeWouldStompChanges returns list of table names that are stomped and the diffs map between head and working set.
@@ -101,7 +101,7 @@ func mergeNomsTable(ctx context.Context, tm *TableMerger, mergedSch schema.Schem
if err != nil {
return nil, nil, err
}
stats.Conflicts = int(cons.Len())
stats.DataConflicts = int(cons.Len())
}
resultTbl, err = mergeAutoIncrementValues(ctx, tm.leftTbl, tm.rightTbl, resultTbl)
@@ -91,7 +91,7 @@ func mergeProllyTable(ctx context.Context, tm *TableMerger, mergedSch schema.Sch
if err != nil {
return nil, nil, err
}
stats.Conflicts = int(n)
stats.DataConflicts = int(n)
mergeTbl, err = mergeAutoIncrementValues(ctx, tm.leftTbl, tm.rightTbl, mergeTbl)
if err != nil {
@@ -162,13 +162,13 @@ func mergeProllyTableData(ctx context.Context, tm *TableMerger, finalSch schema.
if err != nil {
return nil, nil, err
}
s.Conflicts += cnt
s.DataConflicts += cnt
switch diff.Op {
case tree.DiffOpDivergentModifyConflict, tree.DiffOpDivergentDeleteConflict:
// In this case, a modification or delete was made to one side, and a conflicting delete or modification
// was made to the other side, so these cannot be automatically resolved.
s.Conflicts++
s.DataConflicts++
err = conflicts.merge(ctx, diff, nil)
if err != nil {
return nil, nil, err
@@ -218,7 +218,7 @@ func mergeProllyTableData(ctx context.Context, tm *TableMerger, finalSch schema.
case tree.DiffOpConvergentAdd, tree.DiffOpConvergentModify, tree.DiffOpConvergentDelete:
// In this case, both sides of the merge have made the same change, so no additional changes are needed.
if keyless {
s.Conflicts++
s.DataConflicts++
err = conflicts.merge(ctx, diff, nil)
if err != nil {
return nil, nil, err
+32 -7
View File
@@ -34,7 +34,11 @@ import (
)
type MergeOpts struct {
// IsCherryPick is set for cherry-pick operations.
IsCherryPick bool
// KeepSchemaConflicts if schema conflicts should be
// stored, otherwise we end the merge with an error.
KeepSchemaConflicts bool
}
type TableMerger struct {
@@ -104,9 +108,14 @@ func NewMerger(
}, nil
}
type MergedTable struct {
table *doltdb.Table
conflict SchemaConflict
}
// MergeTable merges schema and table data for the table tblName.
// TODO: this code will loop infinitely when merging certain schema changes
func (rm *RootMerger) MergeTable(ctx context.Context, tblName string, opts editor.Options, mergeOpts MergeOpts) (*doltdb.Table, *MergeStats, error) {
func (rm *RootMerger) MergeTable(ctx context.Context, tblName string, opts editor.Options, mergeOpts MergeOpts) (*MergedTable, *MergeStats, error) {
tm, err := rm.makeTableMerger(ctx, tblName)
if err != nil {
return nil, nil, err
@@ -115,7 +124,7 @@ func (rm *RootMerger) MergeTable(ctx context.Context, tblName string, opts edito
// short-circuit here if we can
finished, stats, err := rm.maybeShortCircuit(ctx, tm, mergeOpts)
if finished != nil || stats != nil || err != nil {
return finished, stats, err
return &MergedTable{table: finished}, stats, err
}
if mergeOpts.IsCherryPick && !schema.SchemasAreEqual(tm.leftSch, tm.rightSch) {
@@ -127,16 +136,32 @@ func (rm *RootMerger) MergeTable(ctx context.Context, tblName string, opts edito
if err != nil {
return nil, nil, err
}
if schConflicts.Count() != 0 {
// error on any schema conflicts that we can't resolve
return nil, nil, ErrSchemaConflict.New(schConflicts.AsError().Error())
if schConflicts.Count() > 0 {
if !mergeOpts.KeepSchemaConflicts {
return nil, nil, schConflicts
}
// handle schema conflicts above
mt := &MergedTable{
table: tm.leftTbl,
conflict: schConflicts,
}
stats = &MergeStats{
Operation: TableModified,
SchemaConflicts: schConflicts.Count(),
}
return mt, stats, nil
}
var tbl *doltdb.Table
if types.IsFormat_DOLT(tm.vrw.Format()) {
return mergeProllyTable(ctx, tm, mergeSch)
tbl, stats, err = mergeProllyTable(ctx, tm, mergeSch)
} else {
return mergeNomsTable(ctx, tm, mergeSch, rm.vrw, opts)
tbl, stats, err = mergeNomsTable(ctx, tm, mergeSch, rm.vrw, opts)
}
if err != nil {
return nil, nil, err
}
return &MergedTable{table: tbl}, stats, nil
}
func (rm *RootMerger) makeTableMerger(ctx context.Context, tblName string) (*TableMerger, error) {
+20 -6
View File
@@ -38,6 +38,18 @@ const (
DeletedCheckCollision
)
// todo: link to docs explaining how to resolve schema conflicts.
func SchemaConflictErr(cc ...SchemaConflict) error {
var sb strings.Builder
sb.WriteString("merge aborted: schema conflict found for tables: \n")
for i := range cc {
sb.WriteRune('\t')
sb.WriteString(cc[i].TableName)
sb.WriteRune('\n')
}
return errors.New(sb.String())
}
type SchemaConflict struct {
TableName string
ColConflicts []ColConflict
@@ -45,15 +57,17 @@ type SchemaConflict struct {
ChkConflicts []ChkConflict
}
var EmptySchConflicts = SchemaConflict{}
var _ error = SchemaConflict{}
func (sc SchemaConflict) Count() int {
return len(sc.ColConflicts) + len(sc.IdxConflicts) + len(sc.ChkConflicts)
}
func (sc SchemaConflict) AsError() error {
func (sc SchemaConflict) Error() string {
var b strings.Builder
b.WriteString(fmt.Sprintf("schema conflicts for table %s:\n", sc.TableName))
b.WriteString("merge aborted: schema conflict found for table ")
b.WriteString(sc.TableName)
b.WriteString("\n please resolve schema conflicts before merging")
for _, c := range sc.ColConflicts {
b.WriteString(fmt.Sprintf("\t%s\n", c.String()))
}
@@ -63,7 +77,7 @@ func (sc SchemaConflict) AsError() error {
for _, c := range sc.ChkConflicts {
b.WriteString(fmt.Sprintf("\t%s\n", c.String()))
}
return fmt.Errorf(b.String())
return b.String()
}
type ColConflict struct {
@@ -136,7 +150,7 @@ func SchemaMerge(ctx context.Context, format *types.NomsBinFormat, ourSch, their
var mergedCC *schema.ColCollection
mergedCC, sc.ColConflicts, err = mergeColumns(ourSch.GetAllCols(), theirSch.GetAllCols(), ancSch.GetAllCols())
if err != nil {
return nil, EmptySchConflicts, err
return nil, SchemaConflict{}, err
}
if len(sc.ColConflicts) > 0 {
return nil, sc, nil
@@ -168,7 +182,7 @@ func SchemaMerge(ctx context.Context, format *types.NomsBinFormat, ourSch, their
var mergedChks []schema.Check
mergedChks, sc.ChkConflicts, err = mergeChecks(ctx, ourSch.Checks(), theirSch.Checks(), ancSch.Checks())
if err != nil {
return nil, EmptySchConflicts, err
return nil, SchemaConflict{}, err
}
if len(sc.ChkConflicts) > 0 {
return nil, sc, nil
+15 -1
View File
@@ -28,6 +28,20 @@ type MergeStats struct {
Adds int
Deletes int
Modifications int
Conflicts int
DataConflicts int
SchemaConflicts int
ConstraintViolations int
}
func (ms *MergeStats) HasConflicts() bool {
return ms.DataConflicts > 0 ||
ms.SchemaConflicts > 0
}
func (ms *MergeStats) HasConstraintViolations() bool {
return ms.ConstraintViolations > 0
}
func (ms *MergeStats) HasArtifacts() bool {
return ms.HasConflicts() || ms.HasConstraintViolations()
}
+9 -17
View File
@@ -58,14 +58,6 @@ var colColl = schema.NewColCollection(
)
var sch = schema.MustSchemaFromCols(colColl)
var indexSchema schema.Index
var compositeIndexSchema schema.Index
func init() {
indexSchema, _ = sch.Indexes().AddIndexByColTags("idx_col1", []uint64{col1Tag}, nil, schema.IndexProperties{IsUnique: false, Comment: ""})
compositeIndexSchema, _ = sch.Indexes().AddIndexByColTags("idx_col1_col2", []uint64{col1Tag, col2Tag}, nil, schema.IndexProperties{IsUnique: false, Comment: ""})
}
type rowV struct {
col1, col2 int
}
@@ -329,10 +321,10 @@ func TestMergeCommits(t *testing.T) {
expected, err = expected.SetArtifacts(context.Background(), durable.ArtifactIndexFromProllyMap(expectedArtifacts))
require.NoError(t, err)
mergedRows, err := merged.GetRowData(context.Background())
mergedRows, err := merged.table.GetRowData(context.Background())
assert.NoError(t, err)
artIdx, err := merged.GetArtifacts(context.Background())
artIdx, err := merged.table.GetArtifacts(context.Background())
require.NoError(t, err)
artifacts := durable.ProllyMapFromArtifactIndex(artIdx)
MustEqualArtifactMap(t, expectedArtifacts, artifacts)
@@ -340,14 +332,14 @@ func TestMergeCommits(t *testing.T) {
MustEqualProlly(t, tableName, durable.ProllyMapFromIndex(expectedRows), durable.ProllyMapFromIndex(mergedRows))
for _, index := range sch.Indexes().AllIndexes() {
mergedIndexRows, err := merged.GetIndexRowData(context.Background(), index.Name())
mergedIndexRows, err := merged.table.GetIndexRowData(context.Background(), index.Name())
require.NoError(t, err)
expectedIndexRows, err := expected.GetIndexRowData(context.Background(), index.Name())
require.NoError(t, err)
MustEqualProlly(t, index.Name(), durable.ProllyMapFromIndex(expectedIndexRows), durable.ProllyMapFromIndex(mergedIndexRows))
}
h, err := merged.HashOf()
h, err := merged.table.HashOf()
require.NoError(t, err)
eh, err := expected.HashOf()
require.NoError(t, err)
@@ -385,9 +377,9 @@ func TestNomsMergeCommits(t *testing.T) {
expected, err = expected.SetConflicts(context.Background(), conflictSchema, durable.ConflictIndexFromNomsMap(expectedConflicts, vrw))
assert.NoError(t, err)
mergedRows, err := merged.GetNomsRowData(context.Background())
mergedRows, err := merged.table.GetNomsRowData(context.Background())
assert.NoError(t, err)
_, confIdx, err := merged.GetConflicts(context.Background())
_, confIdx, err := merged.table.GetConflicts(context.Background())
assert.NoError(t, err)
conflicts := durable.NomsMapFromConflictIndex(confIdx)
@@ -399,7 +391,7 @@ func TestNomsMergeCommits(t *testing.T) {
}
for _, index := range sch.Indexes().AllIndexes() {
mergedIndexRows, err := merged.GetNomsIndexRowData(context.Background(), index.Name())
mergedIndexRows, err := merged.table.GetNomsIndexRowData(context.Background(), index.Name())
assert.NoError(t, err)
expectedIndexRows, err := expected.GetNomsIndexRowData(context.Background(), index.Name())
assert.NoError(t, err)
@@ -410,7 +402,7 @@ func TestNomsMergeCommits(t *testing.T) {
mustString(types.EncodedValue(context.Background(), mergedIndexRows)))
}
h, err := merged.HashOf()
h, err := merged.table.HashOf()
assert.NoError(t, err)
eh, err := expected.HashOf()
assert.NoError(t, err)
@@ -692,7 +684,7 @@ func calcExpectedStats(t *testing.T) *MergeStats {
// (DeleteAction, UpdateAction),
// (UpdateAction, UpdateAction) with conflict,
// (InsertAction, InsertAction) with conflict
s.Conflicts++
s.DataConflicts++
continue
}
+6 -3
View File
@@ -68,16 +68,19 @@ func Revert(ctx context.Context, ddb *doltdb.DoltDB, root *doltdb.RootValue, hea
return nil, "", err
}
root, _, err = MergeRoots(ctx, root, theirRoot, baseRoot, parentCM, baseCommit, opts, MergeOpts{IsCherryPick: false})
var result *Result
result, err = MergeRoots(ctx, root, theirRoot, baseRoot, parentCM, baseCommit, opts, MergeOpts{IsCherryPick: false})
if err != nil {
return nil, "", err
}
if ok, err := root.HasConflicts(ctx); err != nil {
root = result.Root
if ok, err := result.Root.HasConflicts(ctx); err != nil {
return nil, "", err
} else if ok {
return nil, "", fmt.Errorf("revert currently does not handle conflicts")
}
if ok, err := root.HasConstraintViolations(ctx); err != nil {
if ok, err := result.Root.HasConstraintViolations(ctx); err != nil {
return nil, "", err
} else if ok {
return nil, "", fmt.Errorf("revert currently does not handle constraint violations")
@@ -39,9 +39,8 @@ type testCommand struct {
args args
}
func (tc testCommand) exec(t *testing.T, ctx context.Context, dEnv *env.DoltEnv) {
exitCode := tc.cmd.Exec(ctx, tc.cmd.Name(), tc.args, dEnv, nil)
require.Equal(t, 0, exitCode)
func (tc testCommand) exec(t *testing.T, ctx context.Context, dEnv *env.DoltEnv) int {
return tc.cmd.Exec(ctx, tc.cmd.Name(), tc.args, dEnv, nil)
}
type args []string
@@ -562,10 +561,12 @@ func testMergeSchemas(t *testing.T, test mergeSchemaTest) {
ctx := context.Background()
for _, c := range setupCommon {
c.exec(t, ctx, dEnv)
exit := c.exec(t, ctx, dEnv)
require.Equal(t, 0, exit)
}
for _, c := range test.setup {
c.exec(t, ctx, dEnv)
exit := c.exec(t, ctx, dEnv)
require.Equal(t, 0, exit)
}
// assert that we're on main
@@ -605,13 +606,15 @@ func testMergeSchemasWithConflicts(t *testing.T, test mergeSchemaConflictTest) {
defer dEnv.DoltDB.Close()
ctx := context.Background()
for _, c := range setupCommon {
c.exec(t, ctx, dEnv)
exit := c.exec(t, ctx, dEnv)
require.Equal(t, 0, exit)
}
ancSch := getSchema(t, dEnv)
for _, c := range test.setup {
c.exec(t, ctx, dEnv)
exit := c.exec(t, ctx, dEnv)
require.Equal(t, 0, exit)
}
// assert that we're on main
@@ -660,14 +663,16 @@ func testMergeForeignKeys(t *testing.T, test mergeForeignKeyTest) {
defer dEnv.DoltDB.Close()
ctx := context.Background()
for _, c := range setupForeignKeyTests {
c.exec(t, ctx, dEnv)
exit := c.exec(t, ctx, dEnv)
require.Equal(t, 0, exit)
}
ancRoot, err := dEnv.WorkingRoot(ctx)
require.NoError(t, err)
for _, c := range test.setup {
c.exec(t, ctx, dEnv)
exit := c.exec(t, ctx, dEnv)
require.Equal(t, 0, exit)
}
// assert that we're on main
@@ -687,10 +692,10 @@ func testMergeForeignKeys(t *testing.T, test mergeForeignKeyTest) {
opts := editor.TestEditorOptions(dEnv.DoltDB.ValueReadWriter())
mo := merge.MergeOpts{IsCherryPick: false}
mergedRoot, _, err := merge.MergeRoots(ctx, mainRoot, otherRoot, ancRoot, mainWS, otherWS, opts, mo)
result, err := merge.MergeRoots(ctx, mainRoot, otherRoot, ancRoot, mainWS, otherWS, opts, mo)
assert.NoError(t, err)
fkc, err := mergedRoot.GetForeignKeyCollection(ctx)
fkc, err := result.Root.GetForeignKeyCollection(ctx)
assert.NoError(t, err)
assert.Equal(t, test.fkColl.Count(), fkc.Count())
@@ -494,7 +494,7 @@ func testSchemaMergeHelper(t *testing.T, tests []schemaMergeTest, flipSides bool
var eo editor.Options
eo = eo.WithDeaf(editor.NewInMemDeaf(a.VRW()))
// attempt merge before skipping to assert no panics
root, _, err := merge.MergeRoots(ctx, l, r, a, rootish{r}, rootish{a}, eo, mo)
result, err := merge.MergeRoots(ctx, l, r, a, rootish{r}, rootish{a}, eo, mo)
maybeSkip(t, a.VRW().Format(), test, flipSides)
if test.conflict {
@@ -504,7 +504,7 @@ func testSchemaMergeHelper(t *testing.T, tests []schemaMergeTest, flipSides bool
require.NoError(t, err)
exp, err := m.MapTableHashes(ctx)
assert.NoError(t, err)
act, err := root.MapTableHashes(ctx)
act, err := result.Root.MapTableHashes(ctx)
assert.NoError(t, err)
assert.Equal(t, len(exp), len(act))
+7 -1
View File
@@ -369,6 +369,8 @@ func (db Database) getTableInsensitive(ctx *sql.Context, head *doltdb.Commit, ds
dt, found = dtables.NewTableOfTablesInConflict(ctx, db.name, db.ddb), true
case doltdb.TableOfTablesWithViolationsName:
dt, found = dtables.NewTableOfTablesConstraintViolations(ctx, root), true
case doltdb.SchemaConflictsTableName:
dt, found = dtables.NewSchemaConflictsTable(ctx, db.name, db.ddb), true
case doltdb.BranchesTableName:
dt, found = dtables.NewBranchesTable(ctx, db.ddb), true
case doltdb.RemoteBranchesTableName:
@@ -386,7 +388,11 @@ func (db Database) getTableInsensitive(ctx *sql.Context, head *doltdb.Commit, ds
map[string]env.Remote{},
map[string]env.BranchConfig{},
map[string]env.Remote{})
dt, found = dtables.NewStatusTable(ctx, db.name, db.ddb, adapter), true
ws, err := sess.WorkingSet(ctx, db.name)
if err != nil {
return nil, false, err
}
dt, found = dtables.NewStatusTable(ctx, db.name, db.ddb, ws, adapter), true
case doltdb.MergeStatusTableName:
dt, found = dtables.NewMergeStatusTable(db.name), true
case doltdb.TagsTableName:
@@ -170,15 +170,19 @@ func cherryPick(ctx *sql.Context, dSess *dsess.DoltSession, roots doltdb.Roots,
}
// 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)
mo := merge.MergeOpts{
IsCherryPick: true,
KeepSchemaConflicts: false,
}
result, 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 {
for tbl, stats := range result.Stats {
if stats.HasConflicts() {
tablesWithConflict = append(tablesWithConflict, tbl)
}
}
@@ -188,7 +192,7 @@ func cherryPick(ctx *sql.Context, dSess *dsess.DoltSession, roots doltdb.Roots,
return nil, "", fmt.Errorf("conflicts in table {'%s'}", tblNames)
}
workingRootHash, err = mergedRoot.HashOf()
workingRootHash, err = result.Root.HashOf()
if err != nil {
return nil, "", err
}
@@ -202,5 +206,5 @@ func cherryPick(ctx *sql.Context, dSess *dsess.DoltSession, roots doltdb.Roots,
return nil, "", err
}
return mergedRoot, cherryCommitMeta.Description, nil
return result.Root, cherryCommitMeta.Description, nil
}

Some files were not shown because too many files have changed in this diff Show More