fix(enable): default repo-init and GitHub-create prompts to No · Entire

fix(enable): default repo-init and GitHub-create prompts to No

b6b0b4f→main· computermode·1w ago·2 files·+89 added/-9 removed

entire enable in a non-git directory offered to git init, create a GitHub repo, and push — but the interactive confirms defaulted to Yes, so reflexively pressing Enter blew through the whole cascade and published the directory's contents on the user's behalf (issue #1717).

Flip both confirms to default No so a bare Enter declines: the init prompt halts the cascade before git init, and the GitHub prompt never creates or pushes a remote unless the user explicitly opts in. Both prompts now show the absolute path in the title so a wrong-directory mistake is obvious in interactive and accessible modes. Non-interactive behavior is unchanged: without -y/--init-repo it already declines; those flags still bypass the prompts.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

Sessions

01KX71H0Y109M9JJDG8V0C576AView transcript

Changes

2

180 unmodified lines

181
182
183
184
184
185
186
187
120 unmodified lines

308
309
310
311
312
313
314
311
312
313
314
315
316
317
318
319
320
321
322
318
323
324
325
326
22 unmodified lines

349
350
351
347
348
352
353
354
355
356
357
358
359
360
352
361
362
363
364

180 unmodified lines

// implies intent) or when we're non-interactive (keep the documented
// happy path: default to yes).
if useGitHub && !opts.Yes && !ghFlagsProvided(opts) && interactive.CanPromptInteractively() {
    confirmed, err := confirmCreateGitHubRepo()
    confirmed, err := confirmCreateGitHubRepo(cwd)
    if err != nil {
        return nil, err
    }
120 unmodified lines

// confirmCreateGitHubRepo asks the user whether they want to also create
// a matching GitHub repository. Interactive-only; callers gate on
// interactive.CanPromptInteractively.
func confirmCreateGitHubRepo() (bool, error) {
    confirmed := true
// a matching GitHub repository and push to it. Interactive-only; callers
// gate on interactive.CanPromptInteractively.

// Defaults to No: creating and pushing a remote repository publishes the
// directory's contents on the user's behalf, so it must never happen just
// because the user pressed Enter. The absolute path is in the title so it's
// clear which directory would be published.
func confirmCreateGitHubRepo(cwd string) (bool, error) {
    confirmed := false
    form := NewAccessibleForm(
        huh.NewGroup(
            huh.NewConfirm().
                Title("Create a matching repository on GitHub?").
                Title(fmt.Sprintf("Create a GitHub repository and push the contents of %s?", cwd)).
                Value(&confirmed),
            ),
        )
22 unmodified lines

return false, nil
}

folder := filepath.Base(cwd)
confirmed := true
// Default to No: `entire enable` is often run reflexively inside an
// existing project, so a stray run in the wrong (non-repo) directory
// must not initialize a repo just because the user pressed Enter. The
// absolute path is in the title so a wrong-directory mistake is obvious
// in both interactive and accessible modes.
confirmed := false
form := NewAccessibleForm(
    huh.NewGroup(
        huh.NewConfirm().
            Title(fmt.Sprintf("No git repository in %q. Initialize one here?", folder)).
            Title(fmt.Sprintf("Not a git repository. Initialize a new one in %s?", cwd)).
            Value(&confirmed),
        ),
    )

Mcmd/entire/cli/setup_github.go+18/-9

1009 unmodified lines

1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086

1009 unmodified lines

}

// withPipedStdin redirects os.Stdin to a pipe carrying input for the
// duration of the test, so interactive (accessible) prompts read a
// scripted answer instead of blocking on a real terminal.
func withPipedStdin(t *testing.T, input string) {
    t.Helper()
    pr, pw, err := os.Pipe()
    if err != nil {
        t.Fatal(err)
    }
    t.Cleanup(func() { pr.Close() })
    go func() {
        pw.WriteString(input) //nolint:errcheck // test helper
        pw.Close()
    }()
    old := os.Stdin
    os.Stdin = pr
    t.Cleanup(func() { os.Stdin = old })
}

// TestConfirmInitRepo_DefaultsToNo verifies that pressing Enter (empty
// input) at the init-repo prompt declines. `entire enable` is often run
// reflexively, so a stray run in a non-repo directory must not initialize
// a repo on the user's behalf. Regression guard for issue #1717.
func TestConfirmInitRepo_DefaultsToNo(t *testing.T) {
    t.Setenv("ENTIRE_TEST_TTY", "1")
    t.Setenv("ACCESSIBLE", "1")
    withPipedStdin(t, "\n")

proceed, err := confirmInitRepo(io.Discard, t.TempDir(), GitHubBootstrapOptions{})
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
    if proceed {
        t.Fatal("confirmInitRepo should default to No (decline) on empty input")
    }
}

// TestConfirmInitRepo_ExplicitYesProceeds verifies an explicit "y" still
// opts in, so the safer default doesn't block intentional use.
func TestConfirmInitRepo_ExplicitYesProceeds(t *testing.T) {
    t.Setenv("ENTIRE_TEST_TTY", "1")
    t.Setenv("ACCESSIBLE", "1")
    withPipedStdin(t, "y\n")

proceed, err := confirmInitRepo(io.Discard, t.TempDir(), GitHubBootstrapOptions{})
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
    if !proceed {
        t.Fatal("confirmInitRepo should proceed when the user explicitly answers yes")
    }
}

// TestConfirmCreateGitHubRepo_DefaultsToNo verifies that pressing Enter at
// the GitHub-repo prompt declines. Creating and pushing a remote repository
// publishes the directory's contents, so it must never happen just because
// the user pressed Enter. Regression guard for issue #1717.
func TestConfirmCreateGitHubRepo_DefaultsToNo(t *testing.T) {
    t.Setenv("ENTIRE_TEST_TTY", "1")
    t.Setenv("ACCESSIBLE", "1")
    withPipedStdin(t, "\n")

confirmed, err := confirmCreateGitHubRepo(t.TempDir())
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
    if confirmed {
        t.Fatal("confirmCreateGitHubRepo should default to No on empty input")
    }
}

// restoreCwd chdirs into dir for the duration of the test.
func restoreCwd(t *testing.T, dir string) {
    t.Helper()