diff --git a/go/cmd/dolt/commands/merge.go b/go/cmd/dolt/commands/merge.go index 04eeb7a71c3..470472d81ba 100644 --- a/go/cmd/dolt/commands/merge.go +++ b/go/cmd/dolt/commands/merge.go @@ -144,24 +144,34 @@ func (cmd MergeCmd) Exec(ctx context.Context, commandStr string, args []string, cli.Println(err.Error()) return 1 } - // if merge is called with '--no-commit', we need to commit the sql transaction or the staged changes will be lost - _, _, err = queryist.Query(sqlCtx, "COMMIT") + rows, err := sql.RowIterToRows(sqlCtx, rowIter) if err != nil { cli.Println(err.Error()) + return 0 + } + if len(rows) != 1 { + cli.Println("Runtime error: merge operation returned unexpected number of rows: ", len(rows)) return 1 } - rows, err := sql.RowIterToRows(sqlCtx, rowIter) + mergeResultRow := rows[0] + + upToDate, err := everythingUpToDate(mergeResultRow) if err != nil { - cli.Println("merge finished, but failed to check for fast-forward") cli.Println(err.Error()) + return 1 + } + if upToDate { + // Git CLI language. + cli.Println("Already up to date.") return 0 } - if len(rows) != 1 { - cli.Println("Runtime error: merge operation returned unexpected number of rows: ", len(rows)) + // if merge is called with '--no-commit', we need to commit the sql transaction or the staged changes will be lost + _, _, err = queryist.Query(sqlCtx, "COMMIT") + if err != nil { + cli.Println(err.Error()) return 1 } - row := rows[0] if !apr.Contains(cli.AbortParam) { //todo: refs with the `remotes/` prefix will fail to get a hash @@ -176,7 +186,7 @@ func (cmd MergeCmd) Exec(ctx context.Context, commandStr string, args []string, cli.Println(mergeHashErr.Error()) } - fastFwd := getFastforward(row, dprocedures.MergeProcFFIndex) + fastFwd := getFastforward(mergeResultRow, dprocedures.MergeProcFFIndex) if apr.Contains(cli.NoCommitFlag) { return printMergeStats(fastFwd, apr, queryist, sqlCtx, usage, headHash, mergeHash, "HEAD", "STAGED") @@ -706,3 +716,28 @@ func handleMergeErr(sqlCtx *sql.Context, queryist cli.Queryist, mergeErr error, return 0 } + +func everythingUpToDate(row sql.Row) (bool, error) { + if row == nil { + return false, fmt.Errorf("Runtime error: nil row returned from merge operation") + } + + // We don't currently define these in a readily accessible way, so we'll just hard-code the column indexes. + // Confident we'll never change these. + hashColumn := 0 + msgColumn := 3 + + if hash, ok := row[hashColumn].(string); ok { + if msg, ok := row[msgColumn].(string); ok { + if hash == "" && msg == "Everything up-to-date" { + return true, nil + } + } else { + return false, fmt.Errorf("Runtime error: merge operation returned unexpected message column type: %v", row[msgColumn]) + } + } else { + return false, fmt.Errorf("Runtime error: merge operation returned unexpected hash column type: %v", row[hashColumn]) + } + + return false, nil +} diff --git a/integration-tests/bats/shallow-clone.bats b/integration-tests/bats/shallow-clone.bats index 48fb61fcae9..a957b6958d4 100644 --- a/integration-tests/bats/shallow-clone.bats +++ b/integration-tests/bats/shallow-clone.bats @@ -204,11 +204,12 @@ seed_and_start_serial_remote() { [ "$status" -eq 0 ] cd file-remote - dolt checkout -b branch + dolt branch other HEAD dolt checkout main - - dolt merge branch + run dolt merge other + [ "$status" -eq 0 ] + [[ "$output" =~ "Already up to date" ]] || false } @test "shallow-clone: push to a new remote should error" {