From fbe3ca367d1b108d23a6879cdd3c806add62bee4 Mon Sep 17 00:00:00 2001 From: Tim Sehn Date: Wed, 7 Jan 2026 15:58:13 -0800 Subject: [PATCH 1/8] Consistently implement which commands require a repo and which do not. Add a test file to ensure behavior --- go/cmd/dolt/commands/add.go | 6 - go/cmd/dolt/commands/admin/archive_inspect.go | 4 - go/cmd/dolt/commands/admin/journal_inspect.go | 4 - go/cmd/dolt/commands/admin/zstd.go | 4 - go/cmd/dolt/commands/backup.go | 4 - go/cmd/dolt/commands/blame.go | 6 - go/cmd/dolt/commands/clean.go | 4 - go/cmd/dolt/commands/commit.go | 4 - go/cmd/dolt/commands/config.go | 6 - go/cmd/dolt/commands/debug.go | 8 - go/cmd/dolt/commands/diff.go | 4 - go/cmd/dolt/commands/fetch.go | 4 - go/cmd/dolt/commands/log.go | 4 - go/cmd/dolt/commands/merge.go | 4 - go/cmd/dolt/commands/read_tables.go | 6 - go/cmd/dolt/commands/reflog.go | 4 - go/cmd/dolt/commands/reset.go | 4 - go/cmd/dolt/commands/revert.go | 4 - go/cmd/dolt/commands/rm.go | 4 - go/cmd/dolt/commands/roots.go | 6 - go/cmd/dolt/commands/send_metrics.go | 6 - go/cmd/dolt/commands/show.go | 4 - go/cmd/dolt/commands/status.go | 5 - integration-tests/bats/requires-repo.bats | 188 ++++++++++++++++++ 24 files changed, 188 insertions(+), 109 deletions(-) create mode 100644 integration-tests/bats/requires-repo.bats diff --git a/go/cmd/dolt/commands/add.go b/go/cmd/dolt/commands/add.go index a84df2d9af..4066253944 100644 --- a/go/cmd/dolt/commands/add.go +++ b/go/cmd/dolt/commands/add.go @@ -53,12 +53,6 @@ The dolt status command can be used to obtain a summary of which tables have cha type AddCmd struct{} -var _ cli.RepoNotRequiredCommand = AddCmd{} - -func (cmd AddCmd) RequiresRepo() bool { - return false -} - // Name is returns the name of the Dolt cli command. This is what is used on the command line to invoke the command func (cmd AddCmd) Name() string { return "add" diff --git a/go/cmd/dolt/commands/admin/archive_inspect.go b/go/cmd/dolt/commands/admin/archive_inspect.go index d275787101..ab5df6213b 100644 --- a/go/cmd/dolt/commands/admin/archive_inspect.go +++ b/go/cmd/dolt/commands/admin/archive_inspect.go @@ -40,10 +40,6 @@ func (cmd ArchiveInspectCmd) Description() string { return "Inspect a Dolt archive (.darc) file and display basic information about it." } -func (cmd ArchiveInspectCmd) RequiresRepo() bool { - return false -} - func (cmd ArchiveInspectCmd) Docs() *cli.CommandDocumentation { return &cli.CommandDocumentation{ ShortDesc: "Inspect a Dolt archive (.darc) file and display information about it", diff --git a/go/cmd/dolt/commands/admin/journal_inspect.go b/go/cmd/dolt/commands/admin/journal_inspect.go index 0d7cb26d0f..6b5bb101fb 100644 --- a/go/cmd/dolt/commands/admin/journal_inspect.go +++ b/go/cmd/dolt/commands/admin/journal_inspect.go @@ -39,10 +39,6 @@ func (cmd JournalInspectCmd) Description() string { return "Inspect a Dolt journal file and display information about it." } -func (cmd JournalInspectCmd) RequiresRepo() bool { - return false -} - func (cmd JournalInspectCmd) Docs() *cli.CommandDocumentation { return &cli.CommandDocumentation{ ShortDesc: "Inspect a Dolt journal file and display information about it", diff --git a/go/cmd/dolt/commands/admin/zstd.go b/go/cmd/dolt/commands/admin/zstd.go index b9e31f231d..8dd1e9a1d8 100644 --- a/go/cmd/dolt/commands/admin/zstd.go +++ b/go/cmd/dolt/commands/admin/zstd.go @@ -37,10 +37,6 @@ func (cmd ZstdCmd) Description() string { return "A temporary admin command for taking a dependency on gozstd and working out tooling dependencies." } -func (cmd ZstdCmd) RequiresRepo() bool { - return false -} - func (cmd ZstdCmd) Docs() *cli.CommandDocumentation { return nil } diff --git a/go/cmd/dolt/commands/backup.go b/go/cmd/dolt/commands/backup.go index ca07699db9..710c15d81b 100644 --- a/go/cmd/dolt/commands/backup.go +++ b/go/cmd/dolt/commands/backup.go @@ -89,10 +89,6 @@ func (cmd BackupCmd) Description() string { return "Manage a set of server backups." } -func (cmd BackupCmd) RequiresRepo() bool { - return false -} - func (cmd BackupCmd) Docs() *cli.CommandDocumentation { ap := cmd.ArgParser() return cli.NewCommandDocumentation(backupDocs, ap) diff --git a/go/cmd/dolt/commands/blame.go b/go/cmd/dolt/commands/blame.go index 19e8ae8eb4..08d18a6b34 100644 --- a/go/cmd/dolt/commands/blame.go +++ b/go/cmd/dolt/commands/blame.go @@ -65,12 +65,6 @@ func (cmd BlameCmd) ArgParser() *argparser.ArgParser { return ap } -func (cmd BlameCmd) RequiresRepo() bool { - return false -} - -var _ cli.RepoNotRequiredCommand = BlameCmd{} - // EventType returns the type of the event to log func (cmd BlameCmd) EventType() eventsapi.ClientEventType { return eventsapi.ClientEventType_BLAME diff --git a/go/cmd/dolt/commands/clean.go b/go/cmd/dolt/commands/clean.go index fd53079f8a..73e0fd0291 100644 --- a/go/cmd/dolt/commands/clean.go +++ b/go/cmd/dolt/commands/clean.go @@ -66,10 +66,6 @@ func (cmd CleanCmd) ArgParser() *argparser.ArgParser { return cli.CreateCleanArgParser() } -func (cmd CleanCmd) RequiresRepo() bool { - return false -} - // Exec executes the command func (cmd CleanCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int { ap := cli.CreateCleanArgParser() diff --git a/go/cmd/dolt/commands/commit.go b/go/cmd/dolt/commands/commit.go index a473197c83..738bc54e62 100644 --- a/go/cmd/dolt/commands/commit.go +++ b/go/cmd/dolt/commands/commit.go @@ -80,10 +80,6 @@ func (cmd CommitCmd) ArgParser() *argparser.ArgParser { return cli.CreateCommitArgParser(false) } -func (cmd CommitCmd) RequiresRepo() bool { - return false -} - // Exec executes the command func (cmd CommitCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int { res, skipped := performCommit(ctx, commandStr, args, cliCtx, dEnv) diff --git a/go/cmd/dolt/commands/config.go b/go/cmd/dolt/commands/config.go index 3aa87d268b..7935809e8b 100644 --- a/go/cmd/dolt/commands/config.go +++ b/go/cmd/dolt/commands/config.go @@ -91,12 +91,6 @@ func (cmd ConfigCmd) Description() string { return "Dolt configuration." } -// RequiresRepo should return false if this interface is implemented, and the command does not have the requirement -// that it be run from within a data repository directory -func (cmd ConfigCmd) RequiresRepo() bool { - return false -} - func (cmd ConfigCmd) Docs() *cli.CommandDocumentation { ap := cmd.ArgParser() return cli.NewCommandDocumentation(cfgDocs, ap) diff --git a/go/cmd/dolt/commands/debug.go b/go/cmd/dolt/commands/debug.go index 803ed0759c..e6d928a938 100644 --- a/go/cmd/dolt/commands/debug.go +++ b/go/cmd/dolt/commands/debug.go @@ -89,14 +89,6 @@ func (cmd DebugCmd) EventType() eventsapi.ClientEventType { return eventsapi.ClientEventType_SQL } -// RequiresRepo indicates that this command does not have to be run from within a dolt data repository directory. -// In this case it is because this command supports the DataDirFlag which can pass in a directory. In the event that -// that parameter is not provided there is additional error handling within this command to make sure that this was in -// fact run from within a dolt data repository directory. -func (cmd DebugCmd) RequiresRepo() bool { - return false -} - // 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. diff --git a/go/cmd/dolt/commands/diff.go b/go/cmd/dolt/commands/diff.go index e26577ee89..44a5b3e891 100644 --- a/go/cmd/dolt/commands/diff.go +++ b/go/cmd/dolt/commands/diff.go @@ -294,10 +294,6 @@ func (cmd DiffCmd) ArgParser() *argparser.ArgParser { return cli.CreateDiffArgParser(false) } -func (cmd DiffCmd) RequiresRepo() bool { - return false -} - // Exec executes the command func (cmd DiffCmd) Exec(ctx context.Context, commandStr string, args []string, _ *env.DoltEnv, cliCtx cli.CliContext) int { ap := cmd.ArgParser() diff --git a/go/cmd/dolt/commands/fetch.go b/go/cmd/dolt/commands/fetch.go index 149f7467f8..32b4ce8cd4 100644 --- a/go/cmd/dolt/commands/fetch.go +++ b/go/cmd/dolt/commands/fetch.go @@ -70,10 +70,6 @@ func (cmd FetchCmd) ArgParser() *argparser.ArgParser { return cli.CreateFetchArgParser() } -func (cmd FetchCmd) RequiresRepo() bool { - return false -} - // Exec executes the command func (cmd FetchCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int { ap := cli.CreateFetchArgParser() diff --git a/go/cmd/dolt/commands/log.go b/go/cmd/dolt/commands/log.go index bf55328e80..4ff10c389f 100644 --- a/go/cmd/dolt/commands/log.go +++ b/go/cmd/dolt/commands/log.go @@ -89,10 +89,6 @@ func (cmd LogCmd) ArgParser() *argparser.ArgParser { return cli.CreateLogArgParser(false) } -func (cmd LogCmd) RequiresRepo() bool { - return false -} - // Exec executes the command 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, cliCtx) diff --git a/go/cmd/dolt/commands/merge.go b/go/cmd/dolt/commands/merge.go index 9c6a856ecb..d904657fe0 100644 --- a/go/cmd/dolt/commands/merge.go +++ b/go/cmd/dolt/commands/merge.go @@ -86,10 +86,6 @@ func (cmd MergeCmd) EventType() eventsapi.ClientEventType { return eventsapi.ClientEventType_MERGE } -func (cmd MergeCmd) RequiresRepo() bool { - return false -} - // Exec executes the command func (cmd MergeCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int { ap := cli.CreateMergeArgParser() diff --git a/go/cmd/dolt/commands/read_tables.go b/go/cmd/dolt/commands/read_tables.go index 9cd2dbb7be..4d047ecd0c 100644 --- a/go/cmd/dolt/commands/read_tables.go +++ b/go/cmd/dolt/commands/read_tables.go @@ -66,12 +66,6 @@ func (cmd ReadTablesCmd) Docs() *cli.CommandDocumentation { return cli.NewCommandDocumentation(readTablesDocs, ap) } -// RequiresRepo should return false if this interface is implemented, and the command does not have the requirement -// that it be run from within a data repository directory -func (cmd ReadTablesCmd) RequiresRepo() bool { - return false -} - func (cmd ReadTablesCmd) ArgParser() *argparser.ArgParser { ap := argparser.NewArgParserWithVariableArgs(cmd.Name()) ap.ArgListHelp = [][2]string{ diff --git a/go/cmd/dolt/commands/reflog.go b/go/cmd/dolt/commands/reflog.go index 9b3f2b22eb..15de6053d2 100644 --- a/go/cmd/dolt/commands/reflog.go +++ b/go/cmd/dolt/commands/reflog.go @@ -72,10 +72,6 @@ func (cmd ReflogCmd) ArgParser() *argparser.ArgParser { return cli.CreateReflogArgParser() } -func (cmd ReflogCmd) RequiresRepo() bool { - return false -} - // Exec executes the command func (cmd ReflogCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int { ap := cmd.ArgParser() diff --git a/go/cmd/dolt/commands/reset.go b/go/cmd/dolt/commands/reset.go index 052bc0632d..9e78dcde2e 100644 --- a/go/cmd/dolt/commands/reset.go +++ b/go/cmd/dolt/commands/reset.go @@ -84,10 +84,6 @@ func (cmd ResetCmd) ArgParser() *argparser.ArgParser { return cli.CreateResetArgParser() } -func (cmd ResetCmd) RequiresRepo() bool { - return false -} - // Exec executes the command func (cmd ResetCmd) Exec(ctx context.Context, commandStr string, args []string, _ *env.DoltEnv, cliCtx cli.CliContext) int { ap := cli.CreateResetArgParser() diff --git a/go/cmd/dolt/commands/revert.go b/go/cmd/dolt/commands/revert.go index cd74618446..77af547242 100644 --- a/go/cmd/dolt/commands/revert.go +++ b/go/cmd/dolt/commands/revert.go @@ -52,10 +52,6 @@ func (cmd RevertCmd) Name() string { return "revert" } -func (cmd RevertCmd) RequiresRepo() bool { - return false -} - // Description implements the interface cli.Command. func (cmd RevertCmd) Description() string { return "Undo the changes introduced in a commit." diff --git a/go/cmd/dolt/commands/rm.go b/go/cmd/dolt/commands/rm.go index 68d1f469c0..572ebed87b 100644 --- a/go/cmd/dolt/commands/rm.go +++ b/go/cmd/dolt/commands/rm.go @@ -43,10 +43,6 @@ The dolt status command can be used to obtain a summary of which tables have cha type RmCmd struct{} -func (cmd RmCmd) RequiresRepo() bool { - return false -} - // Name is returns the name of the Dolt cli command. This is what is used on the command line to invoke the command func (cmd RmCmd) Name() string { return "rm" diff --git a/go/cmd/dolt/commands/roots.go b/go/cmd/dolt/commands/roots.go index 4a46be8964..19960c4c3f 100644 --- a/go/cmd/dolt/commands/roots.go +++ b/go/cmd/dolt/commands/roots.go @@ -54,12 +54,6 @@ func (cmd RootsCmd) Hidden() bool { return true } -// RequiresRepo should return false if this interface is implemented, and the command does not have the requirement -// that it be run from within a data repository directory -func (cmd RootsCmd) RequiresRepo() bool { - return false -} - // Description returns a description of the command func (cmd RootsCmd) Description() string { return "Displays store root values (or potential store root values) that we find in the current database." diff --git a/go/cmd/dolt/commands/send_metrics.go b/go/cmd/dolt/commands/send_metrics.go index d79cdbc1f1..369496291d 100644 --- a/go/cmd/dolt/commands/send_metrics.go +++ b/go/cmd/dolt/commands/send_metrics.go @@ -54,12 +54,6 @@ func (cmd SendMetricsCmd) Description() string { return "Send events logs to server." } -// RequiresRepo should return false if this interface is implemented, and the command does not have the requirement -// that it be run from within a data repository directory -func (cmd SendMetricsCmd) RequiresRepo() bool { - return false -} - // Hidden should return true if this command should be hidden from the help text func (cmd SendMetricsCmd) Hidden() bool { return true diff --git a/go/cmd/dolt/commands/show.go b/go/cmd/dolt/commands/show.go index 858bef9740..979bc81da7 100644 --- a/go/cmd/dolt/commands/show.go +++ b/go/cmd/dolt/commands/show.go @@ -97,10 +97,6 @@ func (cmd ShowCmd) ArgParser() *argparser.ArgParser { return ap } -func (cmd ShowCmd) RequiresRepo() bool { - return false -} - // Exec executes the command func (cmd ShowCmd) Exec(ctx context.Context, commandStr string, args []string, dEnv *env.DoltEnv, cliCtx cli.CliContext) int { ap := cmd.ArgParser() diff --git a/go/cmd/dolt/commands/status.go b/go/cmd/dolt/commands/status.go index b22ecfad7c..0fd5b0500a 100644 --- a/go/cmd/dolt/commands/status.go +++ b/go/cmd/dolt/commands/status.go @@ -68,11 +68,6 @@ var statusDocs = cli.CommandDocumentationContent{ type StatusCmd struct{} -func (cmd StatusCmd) RequiresRepo() bool { - return false -} - -var _ cli.RepoNotRequiredCommand = StatusCmd{} var _ cli.EventMonitoredCommand = StatusCmd{} // Name is returns the name of the Dolt cli command. This is what is used on the command line to invoke the command diff --git a/integration-tests/bats/requires-repo.bats b/integration-tests/bats/requires-repo.bats new file mode 100644 index 0000000000..fa3d4d2c1f --- /dev/null +++ b/integration-tests/bats/requires-repo.bats @@ -0,0 +1,188 @@ +#!/usr/bin/env bats +# Tests for CLI behavior when running commands from a parent directory +# that contains a child dolt database directory. +# See https://github.com/dolthub/dolt/issues/10230 + +load $BATS_TEST_DIRNAME/helper/common.bash +load $BATS_TEST_DIRNAME/helper/query-server-common.bash + +setup() { + skiponwindows "tests are flaky on Windows" + if [ "$SQL_ENGINE" = "remote-engine" ]; then + skip "This test tests local CLI behavior, SQL_ENGINE is not needed." + fi + setup_no_dolt_init + # Create a child database directory + mkdir child_db + cd child_db + dolt init + dolt sql -q "CREATE TABLE test_table (pk INT PRIMARY KEY, value VARCHAR(100))" + dolt add . + dolt commit -m "Initial commit" + cd .. + # We are now in the parent directory with a child dolt database +} + +teardown() { + stop_sql_server 1 && sleep 0.5 + teardown_common +} + +NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." + +# ============================================================================= +# Tests WITHOUT a running SQL server +# All commands that require a repo should fail consistently from parent directory +# ============================================================================= + +@test "parent-directory: dolt status from parent dir without server fails" { + run dolt status + [ "$status" -ne 0 ] + [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] +} + +@test "parent-directory: dolt checkout from parent dir without server fails" { + run dolt checkout -b new_branch + [ "$status" -ne 0 ] + [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] +} + +@test "parent-directory: dolt branch from parent dir without server fails" { + run dolt branch + [ "$status" -ne 0 ] + [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] +} + +@test "parent-directory: dolt log from parent dir without server fails" { + run dolt log + [ "$status" -ne 0 ] + [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] +} + +@test "parent-directory: dolt diff from parent dir without server fails" { + run dolt diff + [ "$status" -ne 0 ] + [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] +} + +@test "parent-directory: dolt add from parent dir without server fails" { + run dolt add . + [ "$status" -ne 0 ] + [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] +} + +@test "parent-directory: dolt commit from parent dir without server fails" { + run dolt commit -m "test" + [ "$status" -ne 0 ] + [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] +} + +# ============================================================================= +# Tests WITH a running SQL server +# Commands should still fail from parent directory - they require a local repo +# ============================================================================= + +@test "parent-directory: dolt status from parent dir with running server fails" { + start_multi_db_server child_db + + # Status should fail - it requires being in a dolt repo directory + run dolt status + [ "$status" -ne 0 ] + [[ "$output" =~ "$NOT_VALID_REPO_ERROR" ]] || false +} + +@test "parent-directory: dolt checkout from parent dir with running server fails" { + start_multi_db_server child_db + + run dolt checkout -b new_branch + [ "$status" -ne 0 ] + [[ "$output" =~ "$NOT_VALID_REPO_ERROR" ]] || false +} + +@test "parent-directory: dolt branch from parent dir with running server fails" { + start_multi_db_server child_db + + run dolt branch + [ "$status" -ne 0 ] + [[ "$output" =~ "$NOT_VALID_REPO_ERROR" ]] || false +} + +@test "parent-directory: dolt log from parent dir with running server fails" { + start_multi_db_server child_db + + run dolt log + [ "$status" -ne 0 ] + [[ "$output" =~ "$NOT_VALID_REPO_ERROR" ]] || false +} + +@test "parent-directory: dolt diff from parent dir with running server fails" { + start_multi_db_server child_db + + run dolt diff + [ "$status" -ne 0 ] + [[ "$output" =~ "$NOT_VALID_REPO_ERROR" ]] || false +} + +# ============================================================================= +# Commands that do NOT require a repo should work from parent directory +# ============================================================================= + +@test "parent-directory: dolt sql from parent dir with running server succeeds" { + start_multi_db_server child_db + + # SQL commands should work by connecting to the running server + run dolt sql -q "SELECT * FROM child_db.test_table" + [ "$status" -eq 0 ] +} + +@test "parent-directory: dolt version from parent dir succeeds" { + run dolt version + [ "$status" -eq 0 ] + [[ "$output" =~ "dolt version" ]] || false +} + +@test "parent-directory: dolt init in parent dir succeeds" { + run dolt init + [ "$status" -eq 0 ] + [[ "$output" =~ "Successfully initialized dolt data repository" ]] || false +} + +# ============================================================================= +# Commands should work correctly when run from within the child database directory +# ============================================================================= + +@test "parent-directory: commands in child directory work normally" { + cd child_db + + run dolt status + [ "$status" -eq 0 ] + [[ "$output" =~ "On branch main" ]] || false + + run dolt checkout -b new_branch + [ "$status" -eq 0 ] + + run dolt branch + [ "$status" -eq 0 ] + [[ "$output" =~ "new_branch" ]] || false + [[ "$output" =~ "main" ]] || false + + run dolt log + [ "$status" -eq 0 ] + [[ "$output" =~ "Initial commit" ]] || false + + run dolt diff + [ "$status" -eq 0 ] +} + +# ============================================================================= +# Test consistent behavior - all repo-requiring commands should fail the same way +# ============================================================================= + +@test "parent-directory: all repo-requiring commands fail consistently" { + # All these commands should fail with the same error + for cmd in "status" "branch" "log" "diff" "add ." "commit -m test" "checkout -b test"; do + run dolt $cmd + [ "$status" -ne 0 ] + [[ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ]] || false + done +} From ed15f707a43f53243c549534689be1571c9929ef Mon Sep 17 00:00:00 2001 From: Tim Sehn Date: Wed, 7 Jan 2026 16:05:05 -0800 Subject: [PATCH 2/8] made config not require a repo --- go/cmd/dolt/commands/config.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/go/cmd/dolt/commands/config.go b/go/cmd/dolt/commands/config.go index 7935809e8b..9673b95f0a 100644 --- a/go/cmd/dolt/commands/config.go +++ b/go/cmd/dolt/commands/config.go @@ -91,6 +91,10 @@ func (cmd ConfigCmd) Description() string { return "Dolt configuration." } +func (cmd ConfigCmd) RequiresRepo() bool { + return false +} + func (cmd ConfigCmd) Docs() *cli.CommandDocumentation { ap := cmd.ArgParser() return cli.NewCommandDocumentation(cfgDocs, ap) From aeaee6be70cb2dbf18ecd97a36d8ebe91eb92917 Mon Sep 17 00:00:00 2001 From: Tim Sehn Date: Wed, 7 Jan 2026 16:55:39 -0800 Subject: [PATCH 3/8] Various fixes --- go/cmd/dolt/cli/command.go | 20 ++++++- go/cmd/dolt/commands/backup.go | 4 ++ go/cmd/dolt/commands/read_tables.go | 4 ++ integration-tests/bats/requires-repo.bats | 69 +++++++++++++++++------ 4 files changed, 79 insertions(+), 18 deletions(-) diff --git a/go/cmd/dolt/cli/command.go b/go/cmd/dolt/cli/command.go index 045018f0db..658e5254cc 100644 --- a/go/cmd/dolt/cli/command.go +++ b/go/cmd/dolt/cli/command.go @@ -60,6 +60,22 @@ func hasHelpFlag(args []string) bool { return false } +// globalArgsSpecifyDB checks if the global arguments contain --use-db or --host flags, +// which indicate that the user is manually specifying a database connection +// rather than relying on the current directory being a dolt repository. +func globalArgsSpecifyDB(cliCtx CliContext) bool { + if cliCtx == nil { + return false + } + globalArgs := cliCtx.GlobalArgs() + if globalArgs == nil { + return false + } + _, hasUseDb := globalArgs.GetValue("use-db") + _, hasHost := globalArgs.GetValue(HostFlag) + return hasUseDb || hasHost +} + // Command is the interface which defines a Dolt cli command type Command interface { // Name returns the name of the Dolt cli command. This is what is used on the command line to invoke the command @@ -220,7 +236,9 @@ func (hc SubCommandHandler) handleCommand(ctx context.Context, commandStr string cmdRequiresRepo = rnrCmd.RequiresRepo() } - if cmdRequiresRepo && !hasHelpFlag(args) { + // If --use-db or --host is specified, the user is manually specifying a database/server + // connection, so we don't require the current directory to be a valid dolt repository. + if cmdRequiresRepo && !hasHelpFlag(args) && !globalArgsSpecifyDB(cliCtx) { isValid := CheckEnvIsValid(dEnv) if !isValid { return 2 diff --git a/go/cmd/dolt/commands/backup.go b/go/cmd/dolt/commands/backup.go index 710c15d81b..ca07699db9 100644 --- a/go/cmd/dolt/commands/backup.go +++ b/go/cmd/dolt/commands/backup.go @@ -89,6 +89,10 @@ func (cmd BackupCmd) Description() string { return "Manage a set of server backups." } +func (cmd BackupCmd) RequiresRepo() bool { + return false +} + func (cmd BackupCmd) Docs() *cli.CommandDocumentation { ap := cmd.ArgParser() return cli.NewCommandDocumentation(backupDocs, ap) diff --git a/go/cmd/dolt/commands/read_tables.go b/go/cmd/dolt/commands/read_tables.go index 4d047ecd0c..80faa37599 100644 --- a/go/cmd/dolt/commands/read_tables.go +++ b/go/cmd/dolt/commands/read_tables.go @@ -66,6 +66,10 @@ func (cmd ReadTablesCmd) Docs() *cli.CommandDocumentation { return cli.NewCommandDocumentation(readTablesDocs, ap) } +func (cmd ReadTablesCmd) RequiresRepo() bool { + return false +} + func (cmd ReadTablesCmd) ArgParser() *argparser.ArgParser { ap := argparser.NewArgParserWithVariableArgs(cmd.Name()) ap.ArgListHelp = [][2]string{ diff --git a/integration-tests/bats/requires-repo.bats b/integration-tests/bats/requires-repo.bats index fa3d4d2c1f..db0b095b74 100644 --- a/integration-tests/bats/requires-repo.bats +++ b/integration-tests/bats/requires-repo.bats @@ -35,43 +35,43 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." # All commands that require a repo should fail consistently from parent directory # ============================================================================= -@test "parent-directory: dolt status from parent dir without server fails" { +@test "requires-repo: dolt status from parent dir without server fails" { run dolt status [ "$status" -ne 0 ] [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] } -@test "parent-directory: dolt checkout from parent dir without server fails" { +@test "requires-repo: dolt checkout from parent dir without server fails" { run dolt checkout -b new_branch [ "$status" -ne 0 ] [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] } -@test "parent-directory: dolt branch from parent dir without server fails" { +@test "requires-repo: dolt branch from parent dir without server fails" { run dolt branch [ "$status" -ne 0 ] [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] } -@test "parent-directory: dolt log from parent dir without server fails" { +@test "requires-repo: dolt log from parent dir without server fails" { run dolt log [ "$status" -ne 0 ] [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] } -@test "parent-directory: dolt diff from parent dir without server fails" { +@test "requires-repo: dolt diff from parent dir without server fails" { run dolt diff [ "$status" -ne 0 ] [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] } -@test "parent-directory: dolt add from parent dir without server fails" { +@test "requires-repo: dolt add from parent dir without server fails" { run dolt add . [ "$status" -ne 0 ] [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] } -@test "parent-directory: dolt commit from parent dir without server fails" { +@test "requires-repo: dolt commit from parent dir without server fails" { run dolt commit -m "test" [ "$status" -ne 0 ] [ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ] @@ -82,7 +82,7 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." # Commands should still fail from parent directory - they require a local repo # ============================================================================= -@test "parent-directory: dolt status from parent dir with running server fails" { +@test "requires-repo: dolt status from parent dir with running server fails" { start_multi_db_server child_db # Status should fail - it requires being in a dolt repo directory @@ -91,7 +91,7 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." [[ "$output" =~ "$NOT_VALID_REPO_ERROR" ]] || false } -@test "parent-directory: dolt checkout from parent dir with running server fails" { +@test "requires-repo: dolt checkout from parent dir with running server fails" { start_multi_db_server child_db run dolt checkout -b new_branch @@ -99,7 +99,7 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." [[ "$output" =~ "$NOT_VALID_REPO_ERROR" ]] || false } -@test "parent-directory: dolt branch from parent dir with running server fails" { +@test "requires-repo: dolt branch from parent dir with running server fails" { start_multi_db_server child_db run dolt branch @@ -107,7 +107,7 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." [[ "$output" =~ "$NOT_VALID_REPO_ERROR" ]] || false } -@test "parent-directory: dolt log from parent dir with running server fails" { +@test "requires-repo: dolt log from parent dir with running server fails" { start_multi_db_server child_db run dolt log @@ -115,7 +115,7 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." [[ "$output" =~ "$NOT_VALID_REPO_ERROR" ]] || false } -@test "parent-directory: dolt diff from parent dir with running server fails" { +@test "requires-repo: dolt diff from parent dir with running server fails" { start_multi_db_server child_db run dolt diff @@ -127,7 +127,7 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." # Commands that do NOT require a repo should work from parent directory # ============================================================================= -@test "parent-directory: dolt sql from parent dir with running server succeeds" { +@test "requires-repo: dolt sql from parent dir with running server succeeds" { start_multi_db_server child_db # SQL commands should work by connecting to the running server @@ -135,23 +135,28 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." [ "$status" -eq 0 ] } -@test "parent-directory: dolt version from parent dir succeeds" { +@test "requires-repo: dolt version from parent dir succeeds" { run dolt version [ "$status" -eq 0 ] [[ "$output" =~ "dolt version" ]] || false } -@test "parent-directory: dolt init in parent dir succeeds" { +@test "requires-repo: dolt init in new dir succeeds" { + # Test that dolt init works in a new directory (doesn't require existing repo) + mkdir new_init_test + cd new_init_test run dolt init [ "$status" -eq 0 ] [[ "$output" =~ "Successfully initialized dolt data repository" ]] || false + cd .. + rm -rf new_init_test } # ============================================================================= # Commands should work correctly when run from within the child database directory # ============================================================================= -@test "parent-directory: commands in child directory work normally" { +@test "requires-repo: commands in child directory work normally" { cd child_db run dolt status @@ -178,7 +183,7 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." # Test consistent behavior - all repo-requiring commands should fail the same way # ============================================================================= -@test "parent-directory: all repo-requiring commands fail consistently" { +@test "requires-repo: all repo-requiring commands fail consistently" { # All these commands should fail with the same error for cmd in "status" "branch" "log" "diff" "add ." "commit -m test" "checkout -b test"; do run dolt $cmd @@ -186,3 +191,33 @@ NOT_VALID_REPO_ERROR="The current directory is not a valid dolt repository." [[ "${lines[0]}" = "$NOT_VALID_REPO_ERROR" ]] || false done } + +# ============================================================================= +# Tests with --use-db or --host flags bypass repo requirement +# These flags indicate a manual database/server connection, so the local +# directory check should be bypassed. +# ============================================================================= + +@test "requires-repo: --host and --use-db flags bypass repo requirement for log" { + start_multi_db_server child_db + + # With --host and --use-db, log should work from parent directory + run dolt --host 127.0.0.1 --port $PORT --no-tls --use-db child_db log + [ "$status" -eq 0 ] + [[ "$output" =~ "Initial commit" ]] || false +} + +@test "requires-repo: --host and --use-db flags bypass repo requirement for branch" { + start_multi_db_server child_db + + run dolt --host 127.0.0.1 --port $PORT --no-tls --use-db child_db branch + [ "$status" -eq 0 ] + [[ "$output" =~ "main" ]] || false +} + +@test "requires-repo: --host and --use-db flags bypass repo requirement for diff" { + start_multi_db_server child_db + + run dolt --host 127.0.0.1 --port $PORT --no-tls --use-db child_db diff + [ "$status" -eq 0 ] +} From 13390f62c3d401b0fcb520a8c61303c68e1d8c7d Mon Sep 17 00:00:00 2001 From: Tim Sehn Date: Wed, 7 Jan 2026 17:41:00 -0800 Subject: [PATCH 4/8] Fix bats tests for repo requirement changes - init.bats: Use status != 0 instead of status == 1 for flexibility - shallow-clone.bats: Add cd into cloned directory after dolt_clone - sql-local-remote.bats: Run commands from within the dolt database directory These tests now properly cd into the dolt database directory before running commands that require a repository context. Co-Authored-By: Claude Opus 4.5 --- integration-tests/bats/init.bats | 2 +- integration-tests/bats/shallow-clone.bats | 3 +++ integration-tests/bats/sql-local-remote.bats | 26 +++++++++++++------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/integration-tests/bats/init.bats b/integration-tests/bats/init.bats index 799c62a429..106293954a 100644 --- a/integration-tests/bats/init.bats +++ b/integration-tests/bats/init.bats @@ -273,7 +273,7 @@ teardown() { # Assert that the current directory has NOT been initialized run dolt status - [ $status -eq 1 ] + [ $status -ne 0 ] [[ $output =~ "The current directory is not a valid dolt repository" ]] || false [ ! -d "$baseDir/not_a_repo/.dolt" ] diff --git a/integration-tests/bats/shallow-clone.bats b/integration-tests/bats/shallow-clone.bats index 8d29ef1275..51e20e4f6c 100644 --- a/integration-tests/bats/shallow-clone.bats +++ b/integration-tests/bats/shallow-clone.bats @@ -63,6 +63,7 @@ seed_and_start_serial_remote() { cd clones dolt sql -q "call dolt_clone('--depth', '1','http://localhost:50051/test-org/test-repo')" + cd test-repo run dolt log --oneline --decorate=no [ "$status" -eq 0 ] @@ -85,6 +86,7 @@ seed_and_start_serial_remote() { cd clones run dolt sql -q "call dolt_clone('--depth', '2','http://localhost:50051/test-org/test-repo')" [ "$status" -eq 0 ] + cd test-repo run dolt log --oneline --decorate=no [ "$status" -eq 0 ] @@ -111,6 +113,7 @@ seed_and_start_serial_remote() { cd clones run dolt sql -q "call dolt_clone('--depth', '1','file://../file-remote')" [ "$status" -eq 0 ] + cd file-remote run dolt log --oneline --decorate=no [ "$status" -eq 0 ] diff --git a/integration-tests/bats/sql-local-remote.bats b/integration-tests/bats/sql-local-remote.bats index 1fbb26bb9d..d9256da52d 100644 --- a/integration-tests/bats/sql-local-remote.bats +++ b/integration-tests/bats/sql-local-remote.bats @@ -199,9 +199,11 @@ get_commit_hash_at() { dolt sql -q "insert into test values (2), (3)" dolt add test dolt commit -m "insert more values into test" - cd .. + cd .. start_sql_server altDB + cd altDB + run dolt blame test [ "$status" -eq 0 ] export out="$output" @@ -269,6 +271,7 @@ get_commit_hash_at() { @test "sql-local-remote: test 'status' and switch between server/no server" { start_sql_server defaultDB + cd defaultDB run dolt status [ "$status" -eq 0 ] || false @@ -323,9 +326,10 @@ get_commit_hash_at() { dolt sql -q "create table test1 (pk int primary key)" dolt sql -q "create table test2 (pk int primary key)" dolt add test1 - cd .. + cd .. start_sql_server altDB + cd altDB run dolt --verbose-engine-setup commit -m "committing remotely" [ "$status" -eq 0 ] @@ -333,20 +337,16 @@ get_commit_hash_at() { stop_sql_server 1 - cd altDB run dolt log [ "$status" -eq 0 ] [[ "$output" =~ "committing remotely" ]] || false run dolt add test2 [ "$status" -eq 0 ] - cd .. run dolt --verbose-engine-setup commit -m "committing locally" [ "$status" -eq 0 ] [[ "$output" =~ "starting local mode" ]] || false - - cd altDB run dolt log [ "$status" -eq 0 ] [[ "$output" =~ "committing locally" ]] || false @@ -691,6 +691,8 @@ SQL @test "sql-local-remote: verify simple dolt reset behavior" { start_sql_server altDB + cd altDB + dolt sql -q "create table test1 (pk int primary key)" dolt add test1 dolt commit -m "create table test1" @@ -773,11 +775,14 @@ SQL } @test "sql-local-remote: ensure revert produces similar output for each mode" { - dolt --use-db altDB commit -A -m "Commit ABCDEF" + cd altDB + dolt commit -A -m "Commit ABCDEF" - start_sql_server altDb + cd .. + start_sql_server altDB + cd altDB - run dolt --use-db altDB revert HEAD + run dolt revert HEAD [ $status -eq 0 ] [[ "$output" =~ 'Revert "Commit ABCDEF"' ]] || false @@ -791,10 +796,13 @@ SQL } @test "sql-local-remote: Ensure that dolt clean works for each mode" { + cd altDB dolt reset --hard dolt sql -q "create table tbl (pk int primary key)" + cd .. start_sql_server altDB + cd altDB run dolt --verbose-engine-setup clean --dry-run [ $status -eq 0 ] From 5f1f4fcf7a1622fd619d4fbc1328fbcc039f38f2 Mon Sep 17 00:00:00 2001 From: Tim Sehn Date: Wed, 7 Jan 2026 17:48:17 -0800 Subject: [PATCH 5/8] Add RequiresRepo() = false to admin inspect commands archive-inspect and journal-inspect commands inspect external files and should not require being run from within a dolt repository. Co-Authored-By: Claude Opus 4.5 --- go/cmd/dolt/commands/admin/archive_inspect.go | 4 ++++ go/cmd/dolt/commands/admin/journal_inspect.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/go/cmd/dolt/commands/admin/archive_inspect.go b/go/cmd/dolt/commands/admin/archive_inspect.go index ab5df6213b..d275787101 100644 --- a/go/cmd/dolt/commands/admin/archive_inspect.go +++ b/go/cmd/dolt/commands/admin/archive_inspect.go @@ -40,6 +40,10 @@ func (cmd ArchiveInspectCmd) Description() string { return "Inspect a Dolt archive (.darc) file and display basic information about it." } +func (cmd ArchiveInspectCmd) RequiresRepo() bool { + return false +} + func (cmd ArchiveInspectCmd) Docs() *cli.CommandDocumentation { return &cli.CommandDocumentation{ ShortDesc: "Inspect a Dolt archive (.darc) file and display information about it", diff --git a/go/cmd/dolt/commands/admin/journal_inspect.go b/go/cmd/dolt/commands/admin/journal_inspect.go index 6b5bb101fb..0d7cb26d0f 100644 --- a/go/cmd/dolt/commands/admin/journal_inspect.go +++ b/go/cmd/dolt/commands/admin/journal_inspect.go @@ -39,6 +39,10 @@ func (cmd JournalInspectCmd) Description() string { return "Inspect a Dolt journal file and display information about it." } +func (cmd JournalInspectCmd) RequiresRepo() bool { + return false +} + func (cmd JournalInspectCmd) Docs() *cli.CommandDocumentation { return &cli.CommandDocumentation{ ShortDesc: "Inspect a Dolt journal file and display information about it", From 5313db0049744867fe0dff53949b9ae793760df5 Mon Sep 17 00:00:00 2001 From: Tim Sehn Date: Thu, 8 Jan 2026 09:43:44 -0800 Subject: [PATCH 6/8] Remove new test file from being executed with a server running --- integration-tests/bats/helper/local-remote.bash | 1 + 1 file changed, 1 insertion(+) diff --git a/integration-tests/bats/helper/local-remote.bash b/integration-tests/bats/helper/local-remote.bash index 5bdc40b32a..d990a879e4 100644 --- a/integration-tests/bats/helper/local-remote.bash +++ b/integration-tests/bats/helper/local-remote.bash @@ -143,6 +143,7 @@ SKIP_SERVER_TESTS=$(cat <<-EOM ~nonlocal.bats~ ~branch-activity.bats~ ~mutual-tls-auth.bats~ +~requires-repo.bats~ EOM ) From 8c3f5cdd4c4d1fa01d8a61482df9d3a064b916b8 Mon Sep 17 00:00:00 2001 From: Neil Macneale IV Date: Thu, 8 Jan 2026 12:26:15 -0800 Subject: [PATCH 7/8] fix the test a little more correctly --- integration-tests/bats/sql-local-remote.bats | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/integration-tests/bats/sql-local-remote.bats b/integration-tests/bats/sql-local-remote.bats index d9256da52d..8c1a50bb1e 100644 --- a/integration-tests/bats/sql-local-remote.bats +++ b/integration-tests/bats/sql-local-remote.bats @@ -775,22 +775,19 @@ SQL } @test "sql-local-remote: ensure revert produces similar output for each mode" { - cd altDB - dolt commit -A -m "Commit ABCDEF" + dolt --use-db altDB commit -A -m "Commit ABCDEF" - cd .. - start_sql_server altDB - cd altDB + start_sql_server altDb - run dolt revert HEAD + run dolt --use-db altDB revert HEAD [ $status -eq 0 ] [[ "$output" =~ 'Revert "Commit ABCDEF"' ]] || false - dolt reset --hard HEAD~1 + dolt --use-db altDB reset --hard HEAD~1 stop_sql_server 1 - run dolt revert HEAD + run dolt --use-db altDB revert HEAD [ $status -eq 0 ] [[ $output =~ 'Revert "Commit ABCDEF"' ]] || false } From 75f15a448be40884959e9ed6f88035a98c043214 Mon Sep 17 00:00:00 2001 From: Neil Macneale IV Date: Thu, 8 Jan 2026 12:37:14 -0800 Subject: [PATCH 8/8] pr feedback --- go/cmd/dolt/commands/admin/zstd.go | 4 ++++ integration-tests/bats/init.bats | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go/cmd/dolt/commands/admin/zstd.go b/go/cmd/dolt/commands/admin/zstd.go index 8dd1e9a1d8..b9e31f231d 100644 --- a/go/cmd/dolt/commands/admin/zstd.go +++ b/go/cmd/dolt/commands/admin/zstd.go @@ -37,6 +37,10 @@ func (cmd ZstdCmd) Description() string { return "A temporary admin command for taking a dependency on gozstd and working out tooling dependencies." } +func (cmd ZstdCmd) RequiresRepo() bool { + return false +} + func (cmd ZstdCmd) Docs() *cli.CommandDocumentation { return nil } diff --git a/integration-tests/bats/init.bats b/integration-tests/bats/init.bats index 106293954a..36ca2b6274 100644 --- a/integration-tests/bats/init.bats +++ b/integration-tests/bats/init.bats @@ -273,7 +273,7 @@ teardown() { # Assert that the current directory has NOT been initialized run dolt status - [ $status -ne 0 ] + [ $status -eq 2 ] [[ $output =~ "The current directory is not a valid dolt repository" ]] || false [ ! -d "$baseDir/not_a_repo/.dolt" ]