From 0a0f728dadacca523217020e78c13dbc36f74a53 Mon Sep 17 00:00:00 2001 From: Alexandre Ferrreira Date: Sat, 2 May 2026 06:49:32 +0100 Subject: [PATCH] chore: remove decorative comments for minimal style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove all decorative section banners (====, ----, ───) - Remove all phase headers (// Phase X:) - Remove redundant comments that repeat test/function names - Keep only comments that explain non-obvious context, safety rationale, or constraints - Update AGENTS.md with new 'Comments must be minimal' rule (rule #10) - Improves code readability by reducing noise in test files and implementation Test coverage: 406 passing with race detection, lint clean --- AGENTS.md | 7 +++ internal/cli/branch_test.go | 7 --- internal/cli/checkout_run_test.go | 7 --- internal/cli/checkout_test.go | 5 -- internal/cli/commit_run_test.go | 2 - internal/cli/commit_test.go | 6 -- internal/cli/discard_run_test.go | 8 --- internal/cli/discard_test.go | 7 --- internal/cli/repo_test.go | 67 ---------------------- internal/cli/reset.go | 5 -- internal/cli/reset_test.go | 12 ---- internal/cli/root_test.go | 5 -- internal/cli/stash.go | 8 --- internal/cli/stash_test.go | 6 -- internal/cli/status_test.go | 4 -- internal/cli/update_run_test.go | 2 - internal/cli/update_test.go | 5 -- internal/cli/upgrade_bundle_compat_test.go | 9 --- internal/cli/upgrade_test.go | 8 --- internal/config/config_test.go | 3 - internal/db/db_test.go | 25 -------- internal/e2e/branch_test.go | 12 ---- internal/e2e/checkout_test.go | 18 ------ internal/e2e/help_test.go | 12 ---- internal/e2e/helpers_test.go | 11 ---- internal/e2e/interactive_test.go | 18 ------ internal/e2e/repo_test.go | 19 ------ internal/e2e/status_test.go | 8 --- internal/e2e/track_test.go | 6 -- internal/e2e/update_test.go | 11 ---- internal/git/git_more_test.go | 9 --- internal/git/git_test.go | 29 ---------- internal/runner/parallel_test.go | 31 ---------- 33 files changed, 7 insertions(+), 385 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 222cc26..9ca110c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -92,6 +92,13 @@ Bad: Update files Every command gets a detailed `Long` explanation with examples. Users won't read code; the help text is their only guide. +### 10. **Comments must be minimal and non-decorative.** + +Do not add decorative section banners (`====`, `----`, `───`) or phase headers in Go files. + +Only keep comments that add non-obvious context (safety rationale, tricky edge cases, external constraints). +If a comment just repeats what the code/test name already says, remove it. + --- ## Development Workflow diff --git a/internal/cli/branch_test.go b/internal/cli/branch_test.go index 14ae2bc..7a1dd6d 100644 --- a/internal/cli/branch_test.go +++ b/internal/cli/branch_test.go @@ -4,7 +4,6 @@ import ( "testing" ) -// TestBranchCmdExists verifies the branch command is created. func TestBranchCmdExists(t *testing.T) { cmd := branchCmd() if cmd == nil { @@ -12,14 +11,12 @@ func TestBranchCmdExists(t *testing.T) { } } -// TestBranchCmdHasSubcommands verifies branch has subcommands. func TestBranchCmdHasSubcommands(t *testing.T) { cmd := branchCmd() if len(cmd.Commands()) == 0 { t.Error("branch command has no subcommands") } - // Verify specific subcommands exist expectedSubcommands := []string{"create", "rename"} actual := make(map[string]bool) for _, sc := range cmd.Commands() { @@ -33,7 +30,6 @@ func TestBranchCmdHasSubcommands(t *testing.T) { } } -// TestBranchCreateCmdExists verifies the create subcommand exists. func TestBranchCreateCmdExists(t *testing.T) { cmd := branchCreateCmd() if cmd == nil { @@ -45,7 +41,6 @@ func TestBranchCreateCmdExists(t *testing.T) { } } -// TestBranchCreateCmdFlags verifies all expected flags are registered on branch create. func TestBranchCreateCmdFlags(t *testing.T) { cmd := branchCreateCmd() @@ -70,7 +65,6 @@ func TestBranchCreateCmdFlags(t *testing.T) { } } -// TestBranchRenameCmdExists verifies the rename subcommand exists. func TestBranchRenameCmdExists(t *testing.T) { cmd := branchRenameCmd() if cmd == nil { @@ -82,7 +76,6 @@ func TestBranchRenameCmdExists(t *testing.T) { } } -// TestBranchRenameCmdFlags verifies all expected flags are registered on branch rename. func TestBranchRenameCmdFlags(t *testing.T) { cmd := branchRenameCmd() diff --git a/internal/cli/checkout_run_test.go b/internal/cli/checkout_run_test.go index 5792738..43827d4 100644 --- a/internal/cli/checkout_run_test.go +++ b/internal/cli/checkout_run_test.go @@ -184,7 +184,6 @@ func TestRunCheckoutWithUI_RepoFlag_SpecificBranch(t *testing.T) { t.Fatalf("AddRepository repo2: %v", err) } - // Create feature branch in both repos but we'll only checkout repo1. mustRunGit(t, dir1, "checkout", "-b", "feature/targeted") mustRunGit(t, dir1, "push", "--set-upstream", "origin", "feature/targeted") mustRunGit(t, dir1, "checkout", "main") @@ -243,9 +242,6 @@ func TestRunCheckoutWithUI_RepoFlag_EmptySlice(t *testing.T) { } func TestRunCheckoutBranch_RemoteOnly(t *testing.T) { - // Tests Finding #1: checkout a branch that only exists on the remote. - // The fix fetches the branch before running git checkout so git can - // create a local tracking branch. database = setupTestDB(t) dir, originDir, _ := initRepoWithRemote(t) repo, err := database.AddRepository("repo1", "repo1", dir, "main") @@ -253,7 +249,6 @@ func TestRunCheckoutBranch_RemoteOnly(t *testing.T) { t.Fatalf("AddRepository: %v", err) } - // Create a branch on origin via a second clone. clone2Dir := cloneRepo(t, originDir) mustRunGit(t, clone2Dir, "config", "user.email", "test@example.com") mustRunGit(t, clone2Dir, "config", "user.name", "Test User") @@ -274,10 +269,8 @@ func TestRunCheckoutBranch_RemoteOnly(t *testing.T) { } func TestRunCheckoutDefault_ReturnsErrorOnFailure(t *testing.T) { - // Tests Finding #4: checkout returns non-zero when repos fail. database = setupTestDB(t) - // Create a repo that points to a non-existent path. repo := &db.Repository{ ID: 1, Alias: "broken", diff --git a/internal/cli/checkout_test.go b/internal/cli/checkout_test.go index 802b0af..59cd157 100644 --- a/internal/cli/checkout_test.go +++ b/internal/cli/checkout_test.go @@ -4,7 +4,6 @@ import ( "testing" ) -// TestCheckoutCmdExists verifies the checkout command is created. func TestCheckoutCmdExists(t *testing.T) { cmd := checkoutCmd() if cmd == nil { @@ -12,7 +11,6 @@ func TestCheckoutCmdExists(t *testing.T) { } } -// TestCheckoutCmdHasUse verifies the command has the correct Use field. func TestCheckoutCmdHasUse(t *testing.T) { cmd := checkoutCmd() if cmd.Use == "" { @@ -20,7 +18,6 @@ func TestCheckoutCmdHasUse(t *testing.T) { } } -// TestCheckoutCmdHasShort verifies the command has a short description. func TestCheckoutCmdHasShort(t *testing.T) { cmd := checkoutCmd() if cmd.Short == "" { @@ -28,7 +25,6 @@ func TestCheckoutCmdHasShort(t *testing.T) { } } -// TestCheckoutCmdIsRunnable verifies the command is runnable. func TestCheckoutCmdIsRunnable(t *testing.T) { cmd := checkoutCmd() if cmd.RunE == nil { @@ -36,7 +32,6 @@ func TestCheckoutCmdIsRunnable(t *testing.T) { } } -// TestCheckoutCmdHasRepoFlag verifies the --repo flag exists with -r shorthand. func TestCheckoutCmdHasRepoFlag(t *testing.T) { cmd := checkoutCmd() f := cmd.Flags().Lookup("repo") diff --git a/internal/cli/commit_run_test.go b/internal/cli/commit_run_test.go index aab680a..52380b1 100644 --- a/internal/cli/commit_run_test.go +++ b/internal/cli/commit_run_test.go @@ -256,7 +256,6 @@ func TestRunCommit_RepoFlag_SkipsNonDirtyRepoSilently(t *testing.T) { } ui := fakeUI{commitMsg: "should not be called"} - // Should not error — clean repos are silently skipped. if err := runCommitWithUI(ui, true, []string{"repo1"}); err != nil { t.Fatalf("runCommitWithUI: %v", err) } @@ -279,7 +278,6 @@ func TestRunCommit_RepoFlag_AllDirtyProtected(t *testing.T) { } ui := fakeUI{commitMsg: "should not be called"} - // Should not error — protected repos are skipped gracefully. if err := runCommitWithUI(ui, true, []string{"repo1"}); err != nil { t.Fatalf("runCommitWithUI: %v", err) } diff --git a/internal/cli/commit_test.go b/internal/cli/commit_test.go index d59b1c6..4245037 100644 --- a/internal/cli/commit_test.go +++ b/internal/cli/commit_test.go @@ -4,7 +4,6 @@ import ( "testing" ) -// TestCommitCmdExists verifies the commit command is created. func TestCommitCmdExists(t *testing.T) { cmd := commitCmd() if cmd == nil { @@ -12,7 +11,6 @@ func TestCommitCmdExists(t *testing.T) { } } -// TestCommitCmdHasUse verifies the command has the correct Use field. func TestCommitCmdHasUse(t *testing.T) { cmd := commitCmd() if cmd.Use != "commit" { @@ -20,7 +18,6 @@ func TestCommitCmdHasUse(t *testing.T) { } } -// TestCommitCmdHasShort verifies the command has a short description. func TestCommitCmdHasShort(t *testing.T) { cmd := commitCmd() if cmd.Short == "" { @@ -28,7 +25,6 @@ func TestCommitCmdHasShort(t *testing.T) { } } -// TestCommitCmdHasLong verifies the command has detailed help text. func TestCommitCmdHasLong(t *testing.T) { cmd := commitCmd() if cmd.Long == "" { @@ -36,7 +32,6 @@ func TestCommitCmdHasLong(t *testing.T) { } } -// TestCommitCmdIsRunnable verifies the command has a RunE function. func TestCommitCmdIsRunnable(t *testing.T) { cmd := commitCmd() if cmd.RunE == nil { @@ -44,7 +39,6 @@ func TestCommitCmdIsRunnable(t *testing.T) { } } -// TestCommitCmdFlags verifies all expected flags are registered on commit. func TestCommitCmdFlags(t *testing.T) { cmd := commitCmd() diff --git a/internal/cli/discard_run_test.go b/internal/cli/discard_run_test.go index 5b8d44b..019f3f1 100644 --- a/internal/cli/discard_run_test.go +++ b/internal/cli/discard_run_test.go @@ -54,7 +54,6 @@ func TestRunDiscard_DirtyRepos(t *testing.T) { } } -// TestRunDiscard_FileSelection verifies that only selected files are discarded. func TestRunDiscard_FileSelection(t *testing.T) { database = setupTestDB(t) repoDir := initRepo(t) @@ -63,7 +62,6 @@ func TestRunDiscard_FileSelection(t *testing.T) { t.Fatalf("AddRepository: %v", err) } - // Create 3 dirty files: 1 tracked modification + 2 untracked. writeFile(t, repoDir, "README.md", "modified readme\n") // tracked writeFile(t, repoDir, "new1.txt", "new file 1\n") // untracked writeFile(t, repoDir, "new2.txt", "new file 2\n") // untracked (survivor) @@ -100,7 +98,6 @@ func TestRunDiscard_FileSelection(t *testing.T) { } } -// TestRunDiscard_RepoFlag verifies --repo bypasses MultiSelect. func TestRunDiscard_RepoFlag(t *testing.T) { database = setupTestDB(t) repoDir := initRepo(t) @@ -121,7 +118,6 @@ func TestRunDiscard_RepoFlag(t *testing.T) { } } -// TestRunDiscard_RepoFlagUnknownAlias verifies --repo with unknown alias returns error. func TestRunDiscard_RepoFlagUnknownAlias(t *testing.T) { database = setupTestDB(t) @@ -131,7 +127,6 @@ func TestRunDiscard_RepoFlagUnknownAlias(t *testing.T) { } } -// TestRunDiscard_CancelFileSelect verifies that canceling file selection skips the repo. func TestRunDiscard_CancelFileSelect(t *testing.T) { database = setupTestDB(t) repoDir := initRepo(t) @@ -145,7 +140,6 @@ func TestRunDiscard_CancelFileSelect(t *testing.T) { fileErr: errCanceled, } - // Should NOT return error — canceling is graceful. if err := runDiscardWithUI(ui, nil); err != nil { t.Fatalf("runDiscard: %v", err) } @@ -156,7 +150,6 @@ func TestRunDiscard_CancelFileSelect(t *testing.T) { } } -// TestRunDiscard_NoFilesSelected verifies that selecting no files skips the repo. func TestRunDiscard_NoFilesSelected(t *testing.T) { database = setupTestDB(t) repoDir := initRepo(t) @@ -180,7 +173,6 @@ func TestRunDiscard_NoFilesSelected(t *testing.T) { } } -// TestRunDiscard_MultipleRepos verifies discard works across multiple repos. func TestRunDiscard_MultipleRepos(t *testing.T) { database = setupTestDB(t) diff --git a/internal/cli/discard_test.go b/internal/cli/discard_test.go index 1815c6b..1e26628 100644 --- a/internal/cli/discard_test.go +++ b/internal/cli/discard_test.go @@ -4,7 +4,6 @@ import ( "testing" ) -// TestDiscardCmdExists verifies the discard command is created. func TestDiscardCmdExists(t *testing.T) { cmd := discardCmd() if cmd == nil { @@ -12,7 +11,6 @@ func TestDiscardCmdExists(t *testing.T) { } } -// TestDiscardCmdHasUse verifies the command has the correct Use field. func TestDiscardCmdHasUse(t *testing.T) { cmd := discardCmd() if cmd.Use != "discard" { @@ -20,7 +18,6 @@ func TestDiscardCmdHasUse(t *testing.T) { } } -// TestDiscardCmdHasShort verifies the command has a short description. func TestDiscardCmdHasShort(t *testing.T) { cmd := discardCmd() if cmd.Short == "" { @@ -28,7 +25,6 @@ func TestDiscardCmdHasShort(t *testing.T) { } } -// TestDiscardCmdHasLong verifies the command has detailed help text. func TestDiscardCmdHasLong(t *testing.T) { cmd := discardCmd() if cmd.Long == "" { @@ -36,7 +32,6 @@ func TestDiscardCmdHasLong(t *testing.T) { } } -// TestDiscardCmdIsRunnable verifies the command has a RunE function. func TestDiscardCmdIsRunnable(t *testing.T) { cmd := discardCmd() if cmd.RunE == nil { @@ -44,7 +39,6 @@ func TestDiscardCmdIsRunnable(t *testing.T) { } } -// TestDiscardCmdHasRepoFlag verifies the --repo / -r flag exists. func TestDiscardCmdHasRepoFlag(t *testing.T) { cmd := discardCmd() f := cmd.Flags().Lookup("repo") @@ -56,7 +50,6 @@ func TestDiscardCmdHasRepoFlag(t *testing.T) { } } -// TestDiscardCmdHasExample verifies the command has example text. func TestDiscardCmdHasExample(t *testing.T) { cmd := discardCmd() if cmd.Example == "" { diff --git a/internal/cli/repo_test.go b/internal/cli/repo_test.go index d4546b2..728f4ce 100644 --- a/internal/cli/repo_test.go +++ b/internal/cli/repo_test.go @@ -9,9 +9,6 @@ import ( "github.com/alexandreafj/gitm/internal/db" ) -// ─── TestPrintRepoTable ───────────────────────────────────────────────────── - -// TestPrintRepoTableHandlesEmpty verifies that printRepoTable doesn't panic with empty list. func TestPrintRepoTableHandlesEmpty(t *testing.T) { // This test ensures the function doesn't crash with an empty repository list. // We can't easily test the actual output without capturing stdout. @@ -25,7 +22,6 @@ func TestPrintRepoTableHandlesEmpty(t *testing.T) { printRepoTable(repos) } -// TestPrintRepoTableHandlesMultipleRepos verifies the function handles multiple repos. func TestPrintRepoTableHandlesMultipleRepos(t *testing.T) { defer func() { if r := recover(); r != nil { @@ -62,14 +58,9 @@ func TestRepoAddCmdAliasValidation(t *testing.T) { } } -// ─── TestRepoAddAutoDetect ────────────────────────────────────────────────── - -// TestRepoAddAutoDetect verifies that --auto-detect scans immediate children, -// registers git repos, and skips plain directories. func TestRepoAddAutoDetect(t *testing.T) { d := setupTestDB(t) - // Build a parent directory with: // parent/ // repo-a/ ← real git repo // repo-b/ ← real git repo @@ -113,7 +104,6 @@ func TestRepoAddAutoDetect(t *testing.T) { t.Fatalf("expected 2 registered repos, got %d", len(repos)) } - // Verify both repo-a and repo-b were registered by alias (directory name). aliases := map[string]bool{} for _, r := range repos { aliases[r.Alias] = true @@ -125,8 +115,6 @@ func TestRepoAddAutoDetect(t *testing.T) { } } -// TestRepoAddAutoDetectSkipsAlreadyRegistered verifies that repos already in -// the database are reported as skipped (⚠) and do not cause a hard failure. func TestRepoAddAutoDetectSkipsAlreadyRegistered(t *testing.T) { d := setupTestDB(t) @@ -156,7 +144,6 @@ func TestRepoAddAutoDetectSkipsAlreadyRegistered(t *testing.T) { if err := cmd.Flags().Set("auto-detect", "true"); err != nil { t.Fatalf("set flag: %v", err) } - // Should succeed (not return an error) even though repo-a is a duplicate. if err := cmd.RunE(cmd, []string{parent}); err != nil { t.Fatalf("RunE: %v", err) } @@ -165,14 +152,11 @@ func TestRepoAddAutoDetectSkipsAlreadyRegistered(t *testing.T) { if err != nil { t.Fatalf("ListRepositories: %v", err) } - // Both repos should be registered (repo-a was already there, repo-b is new). if len(repos) != 2 { t.Fatalf("expected 2 registered repos, got %d", len(repos)) } } -// TestRepoAddAutoDetectRejectsAlias verifies that combining --auto-detect with -// --alias returns an error, since a single alias cannot apply to many repos. func TestRepoAddAutoDetectRejectsAlias(t *testing.T) { cmd := repoAddCmd() if err := cmd.Flags().Set("auto-detect", "true"); err != nil { @@ -186,8 +170,6 @@ func TestRepoAddAutoDetectRejectsAlias(t *testing.T) { } } -// TestRepoAddAutoDetectRejectsMultiplePaths verifies that --auto-detect with -// more than one path argument returns an error. func TestRepoAddAutoDetectRejectsMultiplePaths(t *testing.T) { cmd := repoAddCmd() if err := cmd.Flags().Set("auto-detect", "true"); err != nil { @@ -198,10 +180,7 @@ func TestRepoAddAutoDetectRejectsMultiplePaths(t *testing.T) { } } -// TestRepoAddAutoDetectNotADirectory verifies that passing a file path (not a -// directory) to --auto-detect returns a descriptive error. func TestRepoAddAutoDetectNotADirectory(t *testing.T) { - // Create a real file to pass as the "parent" path. tmp := t.TempDir() filePath := filepath.Join(tmp, "not-a-dir.txt") if err := os.WriteFile(filePath, []byte("hello"), 0644); err != nil { @@ -219,8 +198,6 @@ func TestRepoAddAutoDetectNotADirectory(t *testing.T) { } } -// TestRepoAddAutoDetectSkipsHiddenDirs verifies that hidden directories -// (names starting with ".") are not scanned. func TestRepoAddAutoDetectSkipsHiddenDirs(t *testing.T) { d := setupTestDB(t) @@ -255,8 +232,6 @@ func TestRepoAddAutoDetectSkipsHiddenDirs(t *testing.T) { } } -// TestRepoAddDepthRejectsWithoutAutoDetect verifies that --depth without -// --auto-detect returns an error. func TestRepoAddDepthRejectsWithoutAutoDetect(t *testing.T) { setupTestDB(t) @@ -277,7 +252,6 @@ func TestRepoAddDepthRejectsWithoutAutoDetect(t *testing.T) { } } -// TestRepoAddDepthRejectsZero verifies that --depth=0 returns an error. func TestRepoAddDepthRejectsZero(t *testing.T) { setupTestDB(t) @@ -301,9 +275,6 @@ func TestRepoAddDepthRejectsZero(t *testing.T) { } } -// ─── TestDiscoverRepos ────────────────────────────────────────────────────── - -// TestDiscoverReposEmptyDir verifies that an empty directory returns no repos. func TestDiscoverReposEmptyDir(t *testing.T) { parent := t.TempDir() repos, err := discoverRepos(parent, 1) @@ -315,8 +286,6 @@ func TestDiscoverReposEmptyDir(t *testing.T) { } } -// TestDiscoverReposFindsGitRepos verifies that discoverRepos returns only git -// repo paths and ignores plain directories. func TestDiscoverReposFindsGitRepos(t *testing.T) { parent := t.TempDir() @@ -349,8 +318,6 @@ func TestDiscoverReposFindsGitRepos(t *testing.T) { } } -// TestDiscoverReposNonExistentPath verifies that a non-existent path returns -// a descriptive error. func TestDiscoverReposNonExistentPath(t *testing.T) { _, err := discoverRepos("/this/path/does/not/exist/at/all", 1) if err == nil { @@ -358,8 +325,6 @@ func TestDiscoverReposNonExistentPath(t *testing.T) { } } -// TestDiscoverReposFileNotDir verifies that passing a file (not a directory) -// returns a descriptive error. func TestDiscoverReposFileNotDir(t *testing.T) { tmp := t.TempDir() f := filepath.Join(tmp, "file.txt") @@ -372,10 +337,7 @@ func TestDiscoverReposFileNotDir(t *testing.T) { } } -// TestDiscoverReposFollowsSymlinks verifies that symlinked directories -// pointing to git repos are discovered (not skipped). func TestDiscoverReposFollowsSymlinks(t *testing.T) { - // Create the real repo outside the parent directory. realRepo := t.TempDir() mustRunGit(t, realRepo, "init", "-b", "main") mustRunGit(t, realRepo, "config", "user.email", "test@example.com") @@ -385,7 +347,6 @@ func TestDiscoverReposFollowsSymlinks(t *testing.T) { mustRunGit(t, realRepo, "add", ".") mustRunGit(t, realRepo, "commit", "-m", "init") - // Create a parent directory with a symlink to the real repo. parent := t.TempDir() link := filepath.Join(parent, "linked-repo") if err := os.Symlink(realRepo, link); err != nil { @@ -401,8 +362,6 @@ func TestDiscoverReposFollowsSymlinks(t *testing.T) { } } -// TestDiscoverReposDepthTwo verifies that discoverRepos with maxDepth=2 -// finds repos nested one level deeper than immediate children. func TestDiscoverReposDepthTwo(t *testing.T) { parent := t.TempDir() @@ -436,8 +395,6 @@ func TestDiscoverReposDepthTwo(t *testing.T) { } } -// TestDiscoverReposDoesNotDescendIntoGitRepos verifies that once a git repo -// is found, its subdirectories are not scanned (the repo is a leaf node). func TestDiscoverReposDoesNotDescendIntoGitRepos(t *testing.T) { parent := t.TempDir() @@ -472,8 +429,6 @@ func TestDiscoverReposDoesNotDescendIntoGitRepos(t *testing.T) { } } -// TestDiscoverReposSkipsHiddenDirsAtAllDepths verifies that hidden directories -// are skipped at every depth level, not just the first. func TestDiscoverReposSkipsHiddenDirsAtAllDepths(t *testing.T) { parent := t.TempDir() @@ -506,8 +461,6 @@ func TestDiscoverReposSkipsHiddenDirsAtAllDepths(t *testing.T) { } } -// TestDiscoverReposDepthOneIgnoresNestedRepos verifies that depth=1 (default) -// does not find repos at depth 2, preserving backwards compatibility. func TestDiscoverReposDepthOneIgnoresNestedRepos(t *testing.T) { parent := t.TempDir() @@ -535,8 +488,6 @@ func TestDiscoverReposDepthOneIgnoresNestedRepos(t *testing.T) { } } -// TestRepoAddAutoDetectWithDepth verifies that the full repo add command -// with --auto-detect --depth 2 discovers and registers nested repos. func TestRepoAddAutoDetectWithDepth(t *testing.T) { d := setupTestDB(t) @@ -579,28 +530,22 @@ func TestRepoAddAutoDetectWithDepth(t *testing.T) { } } -// TestRepoAddNormalizesSymlinkedPaths verifies that adding the same repo via -// two different paths (real path and symlink) does not create a duplicate. func TestRepoAddNormalizesSymlinkedPaths(t *testing.T) { d := setupTestDB(t) - // Create a real repo. realRepo := initRepo(t) - // Create a symlink to it. tmp := t.TempDir() link := filepath.Join(tmp, "linked") if err := os.Symlink(realRepo, link); err != nil { t.Skipf("cannot create symlink (OS restriction): %v", err) } - // Add via the real path first. cmd1 := repoAddCmd() if err := cmd1.RunE(cmd1, []string{realRepo}); err != nil { t.Fatalf("add real path: %v", err) } - // Add via the symlink — should NOT create a duplicate. cmd2 := repoAddCmd() if err := cmd2.RunE(cmd2, []string{link}); err != nil { t.Fatalf("add symlink path: %v", err) @@ -615,19 +560,12 @@ func TestRepoAddNormalizesSymlinkedPaths(t *testing.T) { } } -// ─── TestRepoAddAliasConflictReturnsError ─────────────────────────────────── - -// TestRepoAddAliasConflictReturnsError verifies that adding a repo with an -// alias that is already taken by a different repo returns a non-nil error -// (exit code != 0). Regression test for Finding #3. func TestRepoAddAliasConflictReturnsError(t *testing.T) { setupTestDB(t) - // Create two separate git repos. repo1Dir := initRepo(t) repo2Dir := initRepo(t) - // Register repo1 with alias "my-service". cmd1 := repoAddCmd() if err := cmd1.Flags().Set("alias", "my-service"); err != nil { t.Fatalf("set flag: %v", err) @@ -636,7 +574,6 @@ func TestRepoAddAliasConflictReturnsError(t *testing.T) { t.Fatalf("add repo1: %v", err) } - // Try to register repo2 with the SAME alias — should fail. cmd2 := repoAddCmd() if err := cmd2.Flags().Set("alias", "my-service"); err != nil { t.Fatalf("set flag: %v", err) @@ -650,20 +587,16 @@ func TestRepoAddAliasConflictReturnsError(t *testing.T) { } } -// TestRepoAddSamePathIdempotent verifies that re-adding the same repo path -// does NOT return an error (idempotent behavior). func TestRepoAddSamePathIdempotent(t *testing.T) { setupTestDB(t) repoDir := initRepo(t) - // First add. cmd1 := repoAddCmd() if err := cmd1.RunE(cmd1, []string{repoDir}); err != nil { t.Fatalf("first add: %v", err) } - // Second add of same path — should succeed (no error). cmd2 := repoAddCmd() if err := cmd2.RunE(cmd2, []string{repoDir}); err != nil { t.Fatalf("second add of same path should be idempotent, got: %v", err) diff --git a/internal/cli/reset.go b/internal/cli/reset.go index 9798cb3..02b67d3 100644 --- a/internal/cli/reset.go +++ b/internal/cli/reset.go @@ -143,7 +143,6 @@ func runResetWithUI(ui ui, mode resetMode, numCommits int) error { return nil } - // ── Phase 1: gather pre-flight info for every repo ────────────────────── resetRef := buildResetRef(numCommits) infos, skipped := gatherResetInfo(allRepos, numCommits, resetRef) @@ -155,10 +154,8 @@ func runResetWithUI(ui ui, mode resetMode, numCommits int) error { return nil } - // ── Phase 2: print preview ─────────────────────────────────────────────── printResetPreview(infos, mode, numCommits) - // ── Phase 3: interactive selection ────────────────────────────────────── repos := make([]*db.Repository, len(infos)) for i, info := range infos { repos[i] = info.repo @@ -179,7 +176,6 @@ func runResetWithUI(ui ui, mode resetMode, numCommits int) error { infoByPath[infos[i].repo.Path] = &infos[i] } - // ── Phase 4: run the reset ─────────────────────────────────────────────── modeName := resetModeName(mode) fmt.Printf("\nApplying %s reset (%s) to %d repository(ies)…\n\n", color.CyanString(modeName), resetRef, len(chosen)) @@ -207,7 +203,6 @@ func runResetWithUI(ui ui, mode resetMode, numCommits int) error { return msg, "", nil }) - // ── Phase 5: offer force-push for repos with pushed commits ───────────── var pushCandidates []*db.Repository for _, r := range results { if r.Status != runner.StatusSuccess { diff --git a/internal/cli/reset_test.go b/internal/cli/reset_test.go index 6b7fe11..c65300c 100644 --- a/internal/cli/reset_test.go +++ b/internal/cli/reset_test.go @@ -7,8 +7,6 @@ import ( "github.com/alexandreafj/gitm/internal/db" ) -// ─── determineResetMode ────────────────────────────────────────────────────── - func TestDetermineResetMode(t *testing.T) { tests := []struct { name string @@ -69,8 +67,6 @@ func TestDetermineResetMode(t *testing.T) { } } -// ─── resetModeName ─────────────────────────────────────────────────────────── - func TestResetModeName(t *testing.T) { tests := []struct { mode resetMode @@ -88,8 +84,6 @@ func TestResetModeName(t *testing.T) { } } -// ─── resetModeDescription ──────────────────────────────────────────────────── - func TestResetModeDescription(t *testing.T) { tests := []struct { mode resetMode @@ -109,8 +103,6 @@ func TestResetModeDescription(t *testing.T) { } } -// ─── buildResetRef ─────────────────────────────────────────────────────────── - func TestBuildResetRef(t *testing.T) { tests := []struct { n int @@ -128,8 +120,6 @@ func TestBuildResetRef(t *testing.T) { } } -// ─── buildResetResultMessage ───────────────────────────────────────────────── - func TestBuildResetResultMessage(t *testing.T) { info := &repoResetInfo{ repo: &db.Repository{Alias: "my-repo", Path: "/tmp/repo"}, @@ -187,8 +177,6 @@ func TestBuildResetResultMessage(t *testing.T) { }) } -// ─── gatherResetInfo ───────────────────────────────────────────────────────── - func TestGatherResetInfoSkipsReposWithTooFewCommits(t *testing.T) { // We inject a repo with a path that does not exist — git will fail, // which means CommitLog fails, which triggers the "skipped" path. diff --git a/internal/cli/root_test.go b/internal/cli/root_test.go index b3fd987..5c49e04 100644 --- a/internal/cli/root_test.go +++ b/internal/cli/root_test.go @@ -4,7 +4,6 @@ import ( "testing" ) -// TestRootCommandExists verifies that the root command is created without error. func TestRootCommandExists(t *testing.T) { cmd := Root("test") if cmd == nil { @@ -12,7 +11,6 @@ func TestRootCommandExists(t *testing.T) { } } -// TestRootCommandHasUse verifies the root command has the correct Use field. func TestRootCommandHasUse(t *testing.T) { cmd := Root("test") if cmd.Use != "gitm" { @@ -20,7 +18,6 @@ func TestRootCommandHasUse(t *testing.T) { } } -// TestRootCommandHasShort verifies the root command has a Short description. func TestRootCommandHasShort(t *testing.T) { cmd := Root("test") if cmd.Short == "" { @@ -28,7 +25,6 @@ func TestRootCommandHasShort(t *testing.T) { } } -// TestRootCommandHasSubcommands verifies the root command has subcommands registered. func TestRootCommandHasSubcommands(t *testing.T) { cmd := Root("test") if len(cmd.Commands()) == 0 { @@ -36,7 +32,6 @@ func TestRootCommandHasSubcommands(t *testing.T) { } } -// TestRootCommandSubcommandNames verifies expected subcommands exist. func TestRootCommandSubcommandNames(t *testing.T) { cmd := Root("test") expectedCommands := []string{"repo", "checkout", "branch", "status", "update", "discard", "commit", "stash", "reset", "track", "untrack", "upgrade"} diff --git a/internal/cli/stash.go b/internal/cli/stash.go index b833fc4..060640c 100644 --- a/internal/cli/stash.go +++ b/internal/cli/stash.go @@ -34,8 +34,6 @@ Subcommands: return cmd } -// ── push ────────────────────────────────────────────────────────────────────── - func runStashPush(cmd *cobra.Command, args []string) error { return runStashPushWithUI(liveUI{}) } @@ -88,8 +86,6 @@ func runStashPushWithUI(ui ui) error { return nil } -// ── apply ───────────────────────────────────────────────────────────────────── - func stashApplyCmd() *cobra.Command { return &cobra.Command{ Use: "apply", @@ -103,8 +99,6 @@ func runStashApply(cmd *cobra.Command, args []string) error { return runStashApplyOrPopWithUI(liveUI{}, false) } -// ── pop ─────────────────────────────────────────────────────────────────────── - func stashPopCmd() *cobra.Command { return &cobra.Command{ Use: "pop", @@ -173,8 +167,6 @@ func runStashApplyOrPopWithUI(ui ui, pop bool) error { return nil } -// ── list ────────────────────────────────────────────────────────────────────── - func stashListCmd() *cobra.Command { return &cobra.Command{ Use: "list", diff --git a/internal/cli/stash_test.go b/internal/cli/stash_test.go index 9dfc771..6d5b5a5 100644 --- a/internal/cli/stash_test.go +++ b/internal/cli/stash_test.go @@ -4,7 +4,6 @@ import ( "testing" ) -// TestStashCmdExists verifies the stash command is created. func TestStashCmdExists(t *testing.T) { cmd := stashCmd() if cmd == nil { @@ -12,14 +11,12 @@ func TestStashCmdExists(t *testing.T) { } } -// TestStashCmdHasSubcommands verifies stash has subcommands. func TestStashCmdHasSubcommands(t *testing.T) { cmd := stashCmd() if len(cmd.Commands()) == 0 { t.Error("stash command has no subcommands") } - // Verify specific subcommands exist // Note: "push" is the default action (RunE), not a subcommand expectedSubcommands := []string{"pop", "apply", "list"} actual := make(map[string]bool) @@ -37,7 +34,6 @@ func TestStashCmdHasSubcommands(t *testing.T) { // Note: stashPushCmd is not exported, only the subcommand runner is available. // This is by design in the CLI structure. -// TestStashPopCmdExists verifies the pop subcommand exists. func TestStashPopCmdExists(t *testing.T) { cmd := stashPopCmd() if cmd == nil { @@ -45,7 +41,6 @@ func TestStashPopCmdExists(t *testing.T) { } } -// TestStashApplyCmdExists verifies the apply subcommand exists. func TestStashApplyCmdExists(t *testing.T) { cmd := stashApplyCmd() if cmd == nil { @@ -53,7 +48,6 @@ func TestStashApplyCmdExists(t *testing.T) { } } -// TestStashListCmdExists verifies the list subcommand exists. func TestStashListCmdExists(t *testing.T) { cmd := stashListCmd() if cmd == nil { diff --git a/internal/cli/status_test.go b/internal/cli/status_test.go index 30411a8..62fe51d 100644 --- a/internal/cli/status_test.go +++ b/internal/cli/status_test.go @@ -4,7 +4,6 @@ import ( "testing" ) -// TestStatusCmdExists verifies the status command is created. func TestStatusCmdExists(t *testing.T) { cmd := statusCmd() if cmd == nil { @@ -12,7 +11,6 @@ func TestStatusCmdExists(t *testing.T) { } } -// TestStatusCmdHasUse verifies the command has the correct Use field. func TestStatusCmdHasUse(t *testing.T) { cmd := statusCmd() if cmd.Use != "status" { @@ -20,7 +18,6 @@ func TestStatusCmdHasUse(t *testing.T) { } } -// TestStatusCmdHasShort verifies the command has a short description. func TestStatusCmdHasShort(t *testing.T) { cmd := statusCmd() if cmd.Short == "" { @@ -28,7 +25,6 @@ func TestStatusCmdHasShort(t *testing.T) { } } -// TestStatusCmdIsRunnable verifies the command has a RunE function. func TestStatusCmdIsRunnable(t *testing.T) { cmd := statusCmd() if cmd.RunE == nil { diff --git a/internal/cli/update_run_test.go b/internal/cli/update_run_test.go index 7e892a0..f25a9fc 100644 --- a/internal/cli/update_run_test.go +++ b/internal/cli/update_run_test.go @@ -136,10 +136,8 @@ func TestRunUpdate_RepoFlag_EmptySlice(t *testing.T) { } func TestRunUpdate_ReturnsErrorOnFailure(t *testing.T) { - // Tests Finding #4: runUpdate should return a non-nil error when repos fail. database = setupTestDB(t) - // Register a repo with a non-existent path — git operations will fail. if _, err := database.AddRepository("broken", "broken", "/nonexistent/path/broken", "main"); err != nil { t.Fatalf("AddRepository: %v", err) } diff --git a/internal/cli/update_test.go b/internal/cli/update_test.go index 935d109..254aa06 100644 --- a/internal/cli/update_test.go +++ b/internal/cli/update_test.go @@ -4,7 +4,6 @@ import ( "testing" ) -// TestUpdateCmdExists verifies the update command is created. func TestUpdateCmdExists(t *testing.T) { cmd := updateCmd() if cmd == nil { @@ -12,7 +11,6 @@ func TestUpdateCmdExists(t *testing.T) { } } -// TestUpdateCmdHasUse verifies the command has the correct Use field. func TestUpdateCmdHasUse(t *testing.T) { cmd := updateCmd() if cmd.Use != "update" { @@ -20,7 +18,6 @@ func TestUpdateCmdHasUse(t *testing.T) { } } -// TestUpdateCmdHasShort verifies the command has a short description. func TestUpdateCmdHasShort(t *testing.T) { cmd := updateCmd() if cmd.Short == "" { @@ -28,7 +25,6 @@ func TestUpdateCmdHasShort(t *testing.T) { } } -// TestUpdateCmdIsRunnable verifies the command has a RunE function. func TestUpdateCmdIsRunnable(t *testing.T) { cmd := updateCmd() if cmd.RunE == nil { @@ -36,7 +32,6 @@ func TestUpdateCmdIsRunnable(t *testing.T) { } } -// TestUpdateCmdHasRepoFlag verifies the --repo flag is registered with shorthand -r. func TestUpdateCmdHasRepoFlag(t *testing.T) { cmd := updateCmd() f := cmd.Flags().Lookup("repo") diff --git a/internal/cli/upgrade_bundle_compat_test.go b/internal/cli/upgrade_bundle_compat_test.go index 7699eba..04694a7 100644 --- a/internal/cli/upgrade_bundle_compat_test.go +++ b/internal/cli/upgrade_bundle_compat_test.go @@ -144,12 +144,10 @@ func TestConvertLegacyBundle_Success(t *testing.T) { t.Fatalf("convertLegacyBundle: %v", err) } - // Verify the resulting bundle has the expected structure. if b == nil { t.Fatal("expected non-nil bundle") } - // Check media type. version, err := b.Version() if err != nil { t.Fatalf("bundle.Version: %v", err) @@ -158,7 +156,6 @@ func TestConvertLegacyBundle_Success(t *testing.T) { t.Errorf("expected bundle version v0.1, got %s", version) } - // Check that verification content (cert) is present. vc, err := b.VerificationContent() if err != nil { t.Fatalf("VerificationContent: %v", err) @@ -167,7 +164,6 @@ func TestConvertLegacyBundle_Success(t *testing.T) { t.Fatal("expected non-nil verification content") } - // Check tlog entries. entries, err := b.TlogEntries() if err != nil { t.Fatalf("TlogEntries: %v", err) @@ -176,7 +172,6 @@ func TestConvertLegacyBundle_Success(t *testing.T) { t.Fatalf("expected 1 tlog entry, got %d", len(entries)) } - // Check that HasInclusionPromise is true (required for v0.1). if !b.HasInclusionPromise() { t.Error("expected HasInclusionPromise() = true for v0.1 bundle") } @@ -281,10 +276,6 @@ func TestConvertLegacyBundle_ErrorCases(t *testing.T) { } } -// TestSigstoreVerifierLegacyBundleNoLongerFailsOnParse verifies that the -// "unknown field base64Signature" parse error no longer occurs. The verifier -// will still fail (at trust root fetch or identity verification) but the -// error message should NOT contain "unknown field". func TestSigstoreVerifierLegacyBundleNoLongerFailsOnParse(t *testing.T) { artifact := []byte("checksums content for regression test\n") bundleJSON := buildTestLegacyBundle(t, artifact) diff --git a/internal/cli/upgrade_test.go b/internal/cli/upgrade_test.go index 07313ba..3c84ec4 100644 --- a/internal/cli/upgrade_test.go +++ b/internal/cli/upgrade_test.go @@ -638,7 +638,6 @@ func TestRunUpgradeBundleMissingFallback(t *testing.T) { sv := &fakeSignatureVerifier{} opts := &upgradeOpts{execPath: testExecPath(t)} - // Should NOT fail — falls back to SHA-256 only with a warning. err = runUpgrade("v1.0.0", uc, sv, opts) if err != nil { t.Fatalf("expected successful fallback upgrade, got: %v", err) @@ -691,9 +690,6 @@ func newTestHTTPClient(srv *httptest.Server) *http.Client { return srv.Client() } -// TestHTTPDownloadBytesOversizedRejected verifies that httpUpgradeClient.downloadBytes -// rejects a response whose body exceeds maxBundleSize, exercising the real -// io.LimitReader + size-check path that fakeUpgradeClient bypasses. func TestHTTPDownloadBytesOversizedRejected(t *testing.T) { oversized := bytes.Repeat([]byte("x"), int(maxBundleSize)+1) @@ -716,8 +712,6 @@ func TestHTTPDownloadBytesOversizedRejected(t *testing.T) { } } -// TestHTTPDownloadBytesExactLimitAccepted verifies that a response whose body -// is exactly maxBundleSize bytes is accepted without error. func TestHTTPDownloadBytesExactLimitAccepted(t *testing.T) { exactPayload := bytes.Repeat([]byte("y"), int(maxBundleSize)) @@ -740,8 +734,6 @@ func TestHTTPDownloadBytesExactLimitAccepted(t *testing.T) { } } -// TestHTTPDownloadBytesNonOKStatusRejected verifies that a non-200 HTTP status -// is surfaced as an error rather than silently returning an empty body. func TestHTTPDownloadBytesNonOKStatusRejected(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.NotFound(w, r) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 6c493b5..de2a95f 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -33,7 +33,6 @@ func TestLoadCreatesDirIfMissing(t *testing.T) { t.Fatalf("Load failed: %v", err) } - // Verify the directory exists info, err := os.Stat(cfg.DataDir) if err != nil { t.Fatalf("DataDir does not exist: %v", err) @@ -50,7 +49,6 @@ func TestLoadDBPathFormat(t *testing.T) { t.Fatalf("Load failed: %v", err) } - // Verify DBPath contains the correct filename if !filepath.IsAbs(cfg.DBPath) { t.Errorf("DBPath is not absolute: %q", cfg.DBPath) } @@ -67,7 +65,6 @@ func TestLoadDBPathInDataDir(t *testing.T) { t.Fatalf("Load failed: %v", err) } - // Verify DBPath is inside DataDir expectedPath := filepath.Join(cfg.DataDir, config.DBName) if cfg.DBPath != expectedPath { t.Errorf("DBPath = %q, want %q", cfg.DBPath, expectedPath) diff --git a/internal/db/db_test.go b/internal/db/db_test.go index 6236453..429e93f 100644 --- a/internal/db/db_test.go +++ b/internal/db/db_test.go @@ -9,8 +9,6 @@ import ( "github.com/alexandreafj/gitm/internal/db" ) -// ─── helpers ──────────────────────────────────────────────────────────────── - // initDB creates a temporary SQLite database for testing. func initDB(t *testing.T) (*db.DB, string) { t.Helper() @@ -27,8 +25,6 @@ func initDB(t *testing.T) (*db.DB, string) { return d, dbPath } -// ─── TestOpen ─────────────────────────────────────────────────────────────── - func TestOpen(t *testing.T) { tmpDir := t.TempDir() dbPath := filepath.Join(tmpDir, "test.db") @@ -78,8 +74,6 @@ func TestOpenIdempotent(t *testing.T) { d2.Close() } -// ─── TestAddRepository ─────────────────────────────────────────────────────── - func TestAddRepository(t *testing.T) { d, _ := initDB(t) @@ -150,8 +144,6 @@ func TestAddRepositoryDuplicatePath(t *testing.T) { } } -// ─── TestGetRepository ─────────────────────────────────────────────────────── - func TestGetRepository(t *testing.T) { d, _ := initDB(t) @@ -185,8 +177,6 @@ func TestGetRepositoryNotFound(t *testing.T) { } } -// ─── TestGetRepositoryByPath ──────────────────────────────────────────────── - func TestGetRepositoryByPath(t *testing.T) { d, _ := initDB(t) @@ -214,8 +204,6 @@ func TestGetRepositoryByPathNotFound(t *testing.T) { } } -// ─── TestListRepositories ─────────────────────────────────────────────────── - func TestListRepositoriesEmpty(t *testing.T) { d, _ := initDB(t) @@ -271,7 +259,6 @@ func TestListRepositoriesOrdering(t *testing.T) { t.Fatalf("ListRepositories failed: %v", err) } - // Should be ordered by alias expected := []string{"apple", "banana", "zebra"} for i, exp := range expected { if repos[i].Alias != exp { @@ -280,8 +267,6 @@ func TestListRepositoriesOrdering(t *testing.T) { } } -// ─── TestRemoveRepository ─────────────────────────────────────────────────── - func TestRemoveRepository(t *testing.T) { d, _ := initDB(t) @@ -294,7 +279,6 @@ func TestRemoveRepository(t *testing.T) { t.Fatalf("RemoveRepository failed: %v", err) } - // Verify it's gone _, err = d.GetRepository("my-repo") if !errors.Is(err, db.ErrNotFound) { t.Errorf("expected repo to be removed, but found it or got unexpected error: %v", err) @@ -310,8 +294,6 @@ func TestRemoveRepositoryNotFound(t *testing.T) { } } -// ─── TestRenameRepository ─────────────────────────────────────────────────── - func TestRenameRepository(t *testing.T) { d, _ := initDB(t) @@ -324,13 +306,11 @@ func TestRenameRepository(t *testing.T) { t.Fatalf("RenameRepository failed: %v", err) } - // Verify the old alias is gone _, err = d.GetRepository("old-alias") if !errors.Is(err, db.ErrNotFound) { t.Errorf("expected old alias to not exist, got %v", err) } - // Verify the new alias works repo, err := d.GetRepository("new-alias") if err != nil { t.Errorf("expected to find repo with new alias, got %v", err) @@ -349,8 +329,6 @@ func TestRenameRepositoryNotFound(t *testing.T) { } } -// ─── TestUpdateDefaultBranch ──────────────────────────────────────────────── - func TestUpdateDefaultBranch(t *testing.T) { d, _ := initDB(t) @@ -363,7 +341,6 @@ func TestUpdateDefaultBranch(t *testing.T) { t.Fatalf("UpdateDefaultBranch failed: %v", err) } - // Verify the change repo, err := d.GetRepository("my-repo") if err != nil { t.Fatalf("GetRepository failed: %v", err) @@ -373,8 +350,6 @@ func TestUpdateDefaultBranch(t *testing.T) { } } -// ─── TestClose ─────────────────────────────────────────────────────────────── - func TestClose(t *testing.T) { tmpDir := t.TempDir() dbPath := filepath.Join(tmpDir, "test.db") diff --git a/internal/e2e/branch_test.go b/internal/e2e/branch_test.go index e87c478..56c5973 100644 --- a/internal/e2e/branch_test.go +++ b/internal/e2e/branch_test.go @@ -5,10 +5,6 @@ import ( "testing" ) -// ========================================================================== -// Phase 3: Branch Operations (gitm branch create/rename) -// ========================================================================== - func TestBranchCreate_WithRepo(t *testing.T) { e := newTestEnv(t) repo, _ := e.initRepoWithRemote("bc-repo") @@ -17,7 +13,6 @@ func TestBranchCreate_WithRepo(t *testing.T) { r := e.runGitm("branch", "create", "feat/test-branch", "--repo", "bc-repo") e.assertExitCode(r, 0) - // Verify branch was created and we're on it branch := e.currentBranch(repo) if branch != "feat/test-branch" { t.Errorf("expected to be on feat/test-branch, got %s", branch) @@ -34,7 +29,6 @@ func TestBranchCreate_WithAll(t *testing.T) { r := e.runGitm("branch", "create", "feat/all-branch", "--all") e.assertExitCode(r, 0) - // Both repos should have the branch if !e.branchExists(repo1, "feat/all-branch") { t.Error("branch not created in repo1") } @@ -48,7 +42,6 @@ func TestBranchCreate_FromSpecificBase(t *testing.T) { repo, _ := e.initRepoWithRemote("bc-from") e.runGitm("repo", "add", repo, "--alias", "bc-from") - // Create a develop branch first e.mustGit(repo, "checkout", "-b", "develop") e.writeFile(repo, "develop.txt", "develop content\n") e.mustGit(repo, "add", ".") @@ -59,7 +52,6 @@ func TestBranchCreate_FromSpecificBase(t *testing.T) { r := e.runGitm("branch", "create", "feat/from-develop", "--from", "develop", "--repo", "bc-from") e.assertExitCode(r, 0) - // Should have the develop.txt file (branched from develop) if !e.fileExists(filepath.Join(repo, "develop.txt")) { t.Error("branch was not created from develop — develop.txt missing") } @@ -70,7 +62,6 @@ func TestBranchCreate_ExistingBranch(t *testing.T) { repo, _ := e.initRepoWithRemote("bc-existing") e.runGitm("repo", "add", repo, "--alias", "bc-existing") - // Create the branch first e.mustGit(repo, "checkout", "-b", "feat/already-exists") e.mustGit(repo, "checkout", "main") @@ -114,7 +105,6 @@ func TestBranchCreate_DirtyRepo(t *testing.T) { repo, _ := e.initRepoWithRemote("bc-dirty") e.runGitm("repo", "add", repo, "--alias", "bc-dirty") - // Make repo dirty e.writeFile(repo, "README.md", "# dirty\n") r := e.runGitm("branch", "create", "feat/dirty-test", "--repo", "bc-dirty") @@ -128,7 +118,6 @@ func TestBranchRename_WithRepo(t *testing.T) { repo, _ := e.initRepoWithRemote("br-repo") e.runGitm("repo", "add", repo, "--alias", "br-repo") - // Create a branch to rename e.mustGit(repo, "checkout", "-b", "old-name") e.mustGit(repo, "push", "--set-upstream", "origin", "old-name") @@ -151,7 +140,6 @@ func TestBranchRename_WithAll(t *testing.T) { e.runGitm("repo", "add", repo1, "--alias", "br-all-1") e.runGitm("repo", "add", repo2, "--alias", "br-all-2") - // Create the same branch in both repos e.mustGit(repo1, "checkout", "-b", "shared-old") e.mustGit(repo1, "push", "--set-upstream", "origin", "shared-old") e.mustGit(repo2, "checkout", "-b", "shared-old") diff --git a/internal/e2e/checkout_test.go b/internal/e2e/checkout_test.go index c765987..237f35a 100644 --- a/internal/e2e/checkout_test.go +++ b/internal/e2e/checkout_test.go @@ -5,22 +5,16 @@ import ( "testing" ) -// ========================================================================== -// Phase 4: Checkout (gitm checkout) -// ========================================================================== - func TestCheckout_DefaultBranch_Master(t *testing.T) { e := newTestEnv(t) repo, _ := e.initRepoWithRemote("co-master") e.runGitm("repo", "add", repo, "--alias", "co-master") - // Create and switch to a feature branch e.mustGit(repo, "checkout", "-b", "feat/something") r := e.runGitm("checkout", "master") e.assertExitCode(r, 0) - // Should be back on the default branch (main in our test setup) branch := e.currentBranch(repo) if branch != "main" { t.Errorf("expected to be on main (default), got %s", branch) @@ -32,7 +26,6 @@ func TestCheckout_DefaultBranch_Main(t *testing.T) { repo, _ := e.initRepoWithRemote("co-main") e.runGitm("repo", "add", repo, "--alias", "co-main") - // Create and switch to a feature branch e.mustGit(repo, "checkout", "-b", "feat/other") r := e.runGitm("checkout", "main") @@ -49,7 +42,6 @@ func TestCheckout_ExistingBranch_WithRepo(t *testing.T) { repo, _ := e.initRepoWithRemote("co-existing") e.runGitm("repo", "add", repo, "--alias", "co-existing") - // Create a feature branch e.mustGit(repo, "checkout", "-b", "feat/target") e.mustGit(repo, "push", "--set-upstream", "origin", "feat/target") e.mustGit(repo, "checkout", "main") @@ -69,9 +61,7 @@ func TestCheckout_NonExistentBranch(t *testing.T) { e.runGitm("repo", "add", repo, "--alias", "co-ghost") r := e.runGitm("checkout", "branch-that-does-not-exist", "--repo", "co-ghost") - // Should succeed (exit 0) but skip the repo with a message e.assertExitCode(r, 0) - // Should NOT have switched branches branch := e.currentBranch(repo) if branch != "main" { t.Errorf("checkout of non-existent branch should not change current branch, but now on %s", branch) @@ -83,19 +73,15 @@ func TestCheckout_DirtyRepo_Skips(t *testing.T) { repo, _ := e.initRepoWithRemote("co-dirty") e.runGitm("repo", "add", repo, "--alias", "co-dirty") - // Create target branch e.mustGit(repo, "checkout", "-b", "feat/dirty-target") e.mustGit(repo, "push", "--set-upstream", "origin", "feat/dirty-target") e.mustGit(repo, "checkout", "main") - // Make repo dirty e.writeFile(repo, "README.md", "# dirty content\n") r := e.runGitm("checkout", "feat/dirty-target", "--repo", "co-dirty") - // Should skip with warning e.assertExitCode(r, 0) - // Should still be on main (not switched) branch := e.currentBranch(repo) if branch != "main" { t.Errorf("dirty repo should not switch branches, but now on %s", branch) @@ -108,7 +94,6 @@ func TestCheckout_UntrackedFiles_ShouldNotSkip(t *testing.T) { repo, _ := e.initRepoWithRemote("co-untracked") e.runGitm("repo", "add", repo, "--alias", "co-untracked") - // Create target branch e.mustGit(repo, "checkout", "-b", "feat/untracked-test") e.mustGit(repo, "push", "--set-upstream", "origin", "feat/untracked-test") e.mustGit(repo, "checkout", "main") @@ -131,7 +116,6 @@ func TestCheckout_RemoteOnlyBranch(t *testing.T) { repo, origin := e.initRepoWithRemote("co-remote") e.runGitm("repo", "add", repo, "--alias", "co-remote") - // Create a branch on remote only (via another clone) other := e.cloneRepo(origin, "co-remote-other") e.mustGit(other, "checkout", "-b", "feat/remote-only") e.writeFile(other, "remote.txt", "from remote\n") @@ -155,7 +139,6 @@ func TestCheckout_PullsAfterSwitch(t *testing.T) { repo, origin := e.initRepoWithRemote("co-pulls") e.runGitm("repo", "add", repo, "--alias", "co-pulls") - // Create a branch, push it, then push more commits from another clone e.mustGit(repo, "checkout", "-b", "feat/pull-test") e.writeFile(repo, "first.txt", "first\n") e.mustGit(repo, "add", ".") @@ -175,7 +158,6 @@ func TestCheckout_PullsAfterSwitch(t *testing.T) { r := e.runGitm("checkout", "feat/pull-test", "--repo", "co-pulls") e.assertExitCode(r, 0) - // Should have the latest file from the other clone if !e.fileExists(filepath.Join(repo, "second.txt")) { t.Error("checkout did not pull latest — second.txt missing") } diff --git a/internal/e2e/help_test.go b/internal/e2e/help_test.go index 4a6cdf7..8a5b227 100644 --- a/internal/e2e/help_test.go +++ b/internal/e2e/help_test.go @@ -5,20 +5,14 @@ import ( "testing" ) -// ========================================================================== -// Phase 12: Help & Version (gitm --help, --version, unknown commands) -// ========================================================================== - func TestVersion(t *testing.T) { e := newTestEnv(t) r := e.runGitm("--version") e.assertExitCode(r, 0) - // Should contain "gitm version" if !strings.Contains(r.Stdout, "gitm version") { t.Errorf("expected 'gitm version' in output, got: %s", r.Stdout) } - // Our test build uses "e2e-test" as version e.assertStdoutContains(r, "e2e-test") } @@ -28,7 +22,6 @@ func TestHelp_RootCommand(t *testing.T) { r := e.runGitm("--help") e.assertExitCode(r, 0) - // Should list all main commands expectedCommands := []string{ "branch", "checkout", "commit", "discard", "repo", "reset", "stash", "status", @@ -66,24 +59,19 @@ func TestUnknownCommand(t *testing.T) { e := newTestEnv(t) r := e.runGitm("foobar-unknown") - // Should exit non-zero with error about unknown command if r.ExitCode == 0 { t.Error("expected non-zero exit code for unknown command") } e.assertContains(r, "unknown") } -// ========================================================================== -// Phase 13: Upgrade (gitm upgrade) // Only test that it runs without crashing. Don't actually upgrade. -// ========================================================================== func TestUpgrade_SkipsDBInit(t *testing.T) { e := newTestEnv(t) // Upgrade should work even without any DB initialization // (it's in the skip list for PersistentPreRunE). - // Use --help to validate without making network requests. r := e.runGitm("upgrade", "--help") e.assertExitCode(r, 0) diff --git a/internal/e2e/helpers_test.go b/internal/e2e/helpers_test.go index f35891b..6a68d3e 100644 --- a/internal/e2e/helpers_test.go +++ b/internal/e2e/helpers_test.go @@ -17,7 +17,6 @@ import ( var gitmBinary string func TestMain(m *testing.M) { - // Build the binary once for all e2e tests. binary, err := buildGitm() if err != nil { fmt.Fprintf(os.Stderr, "failed to build gitm: %v\n", err) @@ -60,9 +59,7 @@ func buildGitm() (string, error) { return binary, nil } -// -------------------------------------------------------------------------- // Test environment helpers -// -------------------------------------------------------------------------- // testEnv represents an isolated test environment with its own HOME dir. type testEnv struct { @@ -85,9 +82,7 @@ func newTestEnv(t *testing.T) *testEnv { } } -// -------------------------------------------------------------------------- // Running gitm -// -------------------------------------------------------------------------- // result holds the output of a gitm invocation. type result struct { @@ -147,9 +142,7 @@ func (e *testEnv) runGitmInDir(dir string, args ...string) result { } } -// -------------------------------------------------------------------------- // Git repo setup helpers -// -------------------------------------------------------------------------- // initRepo creates a new git repository in a temp directory with an initial commit. // Returns the repo path. @@ -173,14 +166,12 @@ func (e *testEnv) initRepo(name string) string { // Returns (repoDir, bareOriginDir). func (e *testEnv) initRepoWithRemote(name string) (string, string) { e.t.Helper() - // Create bare remote origin := filepath.Join(e.t.TempDir(), name+"-origin.git") if err := os.MkdirAll(origin, 0o755); err != nil { e.t.Fatalf("MkdirAll: %v", err) } e.mustGit(origin, "init", "--bare", "--initial-branch=main") - // Create working repo repo := e.initRepo(name) e.mustGit(repo, "remote", "add", "origin", origin) e.mustGit(repo, "push", "--set-upstream", "origin", "main") @@ -252,9 +243,7 @@ func (e *testEnv) branchExists(dir, branch string) bool { return cmd.Run() == nil } -// -------------------------------------------------------------------------- // Assertion helpers -// -------------------------------------------------------------------------- // assertExitCode checks the exit code of a result. func (e *testEnv) assertExitCode(r result, expected int) { diff --git a/internal/e2e/interactive_test.go b/internal/e2e/interactive_test.go index 852051b..18e9845 100644 --- a/internal/e2e/interactive_test.go +++ b/internal/e2e/interactive_test.go @@ -4,11 +4,8 @@ import ( "testing" ) -// ========================================================================== -// Phase 8: Commit (gitm commit) // Note: Commit is heavily TUI-dependent (file selection + message input). // We can only test edge cases that exit before TUI interaction. -// ========================================================================== func TestCommit_NoDirtyRepos(t *testing.T) { e := newTestEnv(t) @@ -17,7 +14,6 @@ func TestCommit_NoDirtyRepos(t *testing.T) { r := e.runGitm("commit", "--repo", "commit-clean") e.assertExitCode(r, 0) - // Should indicate no dirty repos e.assertContains(r, "No dirty repositories found") } @@ -27,11 +23,8 @@ func TestCommit_ProtectedDefaultBranch(t *testing.T) { t.Skip("commit protection behavior is non-deterministic in non-TTY environments") } -// ========================================================================== -// Phase 9: Discard (gitm discard) // Note: Discard is TUI-dependent for file selection. // We can only test the "all clean" edge case automatically. -// ========================================================================== func TestDiscard_AllReposClean(t *testing.T) { e := newTestEnv(t) @@ -40,15 +33,11 @@ func TestDiscard_AllReposClean(t *testing.T) { r := e.runGitm("discard", "--repo", "discard-clean") e.assertExitCode(r, 0) - // Should indicate all clean e.assertContains(r, "clean") } -// ========================================================================== -// Phase 10: Stash (gitm stash) // Note: stash has no --repo flag, fully TUI-dependent. // We test stash list (non-interactive) and edge cases. -// ========================================================================== func TestStashList_NoStashes(t *testing.T) { e := newTestEnv(t) @@ -57,7 +46,6 @@ func TestStashList_NoStashes(t *testing.T) { r := e.runGitm("stash", "list") e.assertExitCode(r, 0) - // Should indicate no stashes e.assertContains(r, "No repositories have stash entries") } @@ -66,7 +54,6 @@ func TestStashList_WithStashes(t *testing.T) { repo, _ := e.initRepoWithRemote("stash-has") e.runGitm("repo", "add", repo, "--alias", "stash-has") - // Create a stash manually via git e.writeFile(repo, "stashme.txt", "stash this\n") e.mustGit(repo, "add", ".") e.mustGit(repo, "stash", "push", "-m", "manual stash for test") @@ -76,14 +63,9 @@ func TestStashList_WithStashes(t *testing.T) { e.assertStdoutContains(r, "stash-has") } -// ========================================================================== -// Phase 11: Reset (gitm reset) // Note: Reset is TUI-dependent (repo selection). No --repo flag. // We document expectations but cannot fully automate. -// ========================================================================== -// TestReset_Behavior documents what reset does when invoked non-interactively. -// Since there's no --repo flag and reset requires TTY for repo selection, we skip. func TestReset_NoReposToReset(t *testing.T) { t.Skip("reset requires TTY for repo selection — cannot test non-interactively") } diff --git a/internal/e2e/repo_test.go b/internal/e2e/repo_test.go index 4e0c8cd..4d0d141 100644 --- a/internal/e2e/repo_test.go +++ b/internal/e2e/repo_test.go @@ -7,10 +7,6 @@ import ( "testing" ) -// ========================================================================== -// Phase 1: Repo Management (gitm repo add/list/remove/rename) -// ========================================================================== - func TestRepoAdd_ValidRepo(t *testing.T) { e := newTestEnv(t) repo := e.initRepo("myrepo") @@ -19,7 +15,6 @@ func TestRepoAdd_ValidRepo(t *testing.T) { e.assertExitCode(r, 0) e.assertContains(r, "myrepo") - // Verify it's listed list := e.runGitm("repo", "list") e.assertExitCode(list, 0) e.assertStdoutContains(list, "myrepo") @@ -41,11 +36,9 @@ func TestRepoAdd_DuplicatePath(t *testing.T) { e := newTestEnv(t) repo := e.initRepo("dup") - // First add should succeed r1 := e.runGitm("repo", "add", repo) e.assertExitCode(r1, 0) - // Second add is idempotent: warns and still succeeds r2 := e.runGitm("repo", "add", repo) e.assertExitCode(r2, 0) e.assertContains(r2, "already") @@ -56,7 +49,6 @@ func TestRepoAdd_NonGitDirectory(t *testing.T) { dir := t.TempDir() // Just a directory, not a git repo r := e.runGitm("repo", "add", dir) - // Should error — not a git repo if r.ExitCode == 0 { t.Errorf("expected non-zero exit code for non-git dir, got 0\nstdout: %s\nstderr: %s", r.Stdout, r.Stderr) @@ -97,7 +89,6 @@ func TestRepoAdd_CurrentDirectory(t *testing.T) { r := e.runGitmInDir(repo, "repo", "add", ".") e.assertExitCode(r, 0) - // Verify the absolute path is stored, not "." list := e.runGitm("repo", "list") e.assertNotContains(list, " . ") } @@ -132,11 +123,9 @@ func TestRepoRemove_Valid(t *testing.T) { r := e.runGitm("repo", "remove", "to-remove") e.assertExitCode(r, 0) - // Verify gone from list list := e.runGitm("repo", "list") e.assertNotContains(list, "to-remove") - // Verify files still exist on disk if !e.fileExists(filepath.Join(repo, "README.md")) { t.Error("repo files were deleted from disk — remove should only affect DB") } @@ -173,7 +162,6 @@ func TestRepoRename_Valid(t *testing.T) { list := e.runGitm("repo", "list") e.assertStdoutContains(list, "after-rename") - // Check the alias column changed — the path may still contain the old dir name // so we check the ALIAS column specifically by looking for the alias field alignment if strings.Contains(list.Stdout, "before-rename") { // The alias "before-rename" should no longer appear as an alias @@ -207,7 +195,6 @@ func TestRepoRename_NonExistentSource(t *testing.T) { func TestRepoAdd_AutoDetect(t *testing.T) { e := newTestEnv(t) - // Create a parent dir with multiple git repos parent := t.TempDir() repo1 := filepath.Join(parent, "project-a") repo2 := filepath.Join(parent, "project-b") @@ -250,7 +237,6 @@ func TestRepoAdd_AutoDetect(t *testing.T) { func TestRepoAdd_AutoDetectWithDepth(t *testing.T) { e := newTestEnv(t) - // Create nested structure: parent/sub/deep-repo parent := t.TempDir() deepRepo := filepath.Join(parent, "sub", "deep-repo") if err := os.MkdirAll(deepRepo, 0o755); err != nil { @@ -265,7 +251,6 @@ func TestRepoAdd_AutoDetectWithDepth(t *testing.T) { e.mustGit(deepRepo, "add", ".") e.mustGit(deepRepo, "commit", "-m", "init") - // Depth 1 should NOT find it r1 := e.runGitm("repo", "add", parent, "--auto-detect", "--depth", "1") e.assertExitCode(r1, 0) list1 := e.runGitm("repo", "list") @@ -273,7 +258,6 @@ func TestRepoAdd_AutoDetectWithDepth(t *testing.T) { t.Log("Depth 1 found deep-repo — might be expected depending on implementation") } - // Depth 2 should find it r2 := e.runGitm("repo", "add", parent, "--auto-detect", "--depth", "2") e.assertExitCode(r2, 0) list2 := e.runGitm("repo", "list") @@ -318,12 +302,9 @@ func TestRepoAdd_AutoDetectSkipsRegistered(t *testing.T) { e.mustGit(repo1, "add", ".") e.mustGit(repo1, "commit", "-m", "init") - // Register it first e.runGitm("repo", "add", repo1) - // Auto-detect should show warning but not fail r := e.runGitm("repo", "add", parent, "--auto-detect") e.assertExitCode(r, 0) - // Should mention it's already registered (warning) e.assertContains(r, "already") } diff --git a/internal/e2e/status_test.go b/internal/e2e/status_test.go index cbb3104..0b2a3cf 100644 --- a/internal/e2e/status_test.go +++ b/internal/e2e/status_test.go @@ -5,10 +5,6 @@ import ( "testing" ) -// ========================================================================== -// Phase 2: Status (gitm status) -// ========================================================================== - func TestStatus_CleanRepo(t *testing.T) { e := newTestEnv(t) repo, _ := e.initRepoWithRemote("status-clean") @@ -31,7 +27,6 @@ func TestStatus_DirtyModified(t *testing.T) { r := e.runGitm("status") e.assertExitCode(r, 0) e.assertStdoutContains(r, "status-dirty") - // Should show something indicating dirty (not "clean") if containsAll(r.Stdout, "status-dirty", "clean") && !containsAny(r.Stdout, "modified", "dirty", "changed") { t.Error("dirty repo shown as clean") } @@ -65,7 +60,6 @@ func TestStatus_AheadOfRemote(t *testing.T) { repo, _ := e.initRepoWithRemote("status-ahead") e.runGitm("repo", "add", repo, "--alias", "status-ahead") - // Make a local commit without pushing e.writeFile(repo, "new.txt", "ahead\n") e.mustGit(repo, "add", ".") e.mustGit(repo, "commit", "-m", "unpushed commit") @@ -130,9 +124,7 @@ func TestStatus_MultipleRepos(t *testing.T) { e.assertStdoutContains(r, "multi-status-2") } -// -------------------------------------------------------------------------- // Helpers for this file -// -------------------------------------------------------------------------- func containsAll(s string, substrs ...string) bool { for _, sub := range substrs { diff --git a/internal/e2e/track_test.go b/internal/e2e/track_test.go index df49986..5da1d9f 100644 --- a/internal/e2e/track_test.go +++ b/internal/e2e/track_test.go @@ -4,12 +4,9 @@ import ( "testing" ) -// ========================================================================== -// Phase 6 & 7: Track and Untrack (gitm track / gitm untrack) // Note: These commands use TUI for file selection. // We can only test edge cases (no files to track/untrack) automatically. // The --repo flag bypasses repo selection but file picker is still TUI-based. -// ========================================================================== func TestTrack_NoUntrackedFiles(t *testing.T) { e := newTestEnv(t) @@ -17,7 +14,6 @@ func TestTrack_NoUntrackedFiles(t *testing.T) { e.runGitm("repo", "add", repo, "--alias", "track-none") r := e.runGitm("track", "--repo", "track-none") - // Should exit gracefully with a "no untracked" message e.assertExitCode(r, 0) e.assertContains(r, "No untracked files found") } @@ -32,9 +28,7 @@ func TestUntrack_NoMatchingFiles(t *testing.T) { repo, _ := e.initRepoWithRemote("untrack-none") e.runGitm("repo", "add", repo, "--alias", "untrack-none") - // Use a path filter that matches nothing r := e.runGitm("untrack", "--repo", "untrack-none", "--path", "*.nonexistent") - // Should exit gracefully with a specific "no matching files" message e.assertExitCode(r, 0) e.assertContains(r, "No files matching") } diff --git a/internal/e2e/update_test.go b/internal/e2e/update_test.go index 3d88df3..efae79f 100644 --- a/internal/e2e/update_test.go +++ b/internal/e2e/update_test.go @@ -5,10 +5,6 @@ import ( "testing" ) -// ========================================================================== -// Phase 5: Update (gitm update) -// ========================================================================== - func TestUpdate_AlreadyUpToDate(t *testing.T) { e := newTestEnv(t) repo, _ := e.initRepoWithRemote("up-current") @@ -16,7 +12,6 @@ func TestUpdate_AlreadyUpToDate(t *testing.T) { r := e.runGitm("update", "--repo", "up-current") e.assertExitCode(r, 0) - // Should indicate already up-to-date or show success e.assertContains(r, "up-current") } @@ -35,7 +30,6 @@ func TestUpdate_RemoteAhead(t *testing.T) { r := e.runGitm("update", "--repo", "up-behind") e.assertExitCode(r, 0) - // Should have the new file if !e.fileExists(filepath.Join(repo, "new-from-remote.txt")) { t.Error("update did not pull — new-from-remote.txt missing") } @@ -46,12 +40,10 @@ func TestUpdate_DirtyRepo_Skips(t *testing.T) { repo, _ := e.initRepoWithRemote("up-dirty") e.runGitm("repo", "add", repo, "--alias", "up-dirty") - // Make dirty e.writeFile(repo, "README.md", "# dirty\n") r := e.runGitm("update", "--repo", "up-dirty") e.assertExitCode(r, 0) - // Should skip/warn about dirty e.assertContains(r, "up-dirty") } @@ -59,7 +51,6 @@ func TestUpdate_NonExistentRepo(t *testing.T) { e := newTestEnv(t) r := e.runGitm("update", "--repo", "ghost-repo") - // Should error — alias doesn't match any registered repo if r.ExitCode == 0 { t.Fatalf("expected non-zero exit for non-existent --repo alias, but got exit=%d stdout=%s stderr=%s", r.ExitCode, r.Stdout, r.Stderr) @@ -78,7 +69,6 @@ func TestUpdate_DoesNotSwitchBranch(t *testing.T) { r := e.runGitm("update", "--repo", "up-nosw") e.assertExitCode(r, 0) - // Should still be on feat/stay-here branch := e.currentBranch(repo) if branch != "feat/stay-here" { t.Errorf("update should not switch branches, but now on %s", branch) @@ -97,7 +87,6 @@ func TestUpdate_DivergedBranch(t *testing.T) { e.mustGit(other, "commit", "-m", "remote commit") e.mustGit(other, "push") - // Make a local commit (local ahead too — diverged) e.writeFile(repo, "local.txt", "local\n") e.mustGit(repo, "add", ".") e.mustGit(repo, "commit", "-m", "local commit") diff --git a/internal/git/git_more_test.go b/internal/git/git_more_test.go index 1d4dbfc..d48c0f6 100644 --- a/internal/git/git_more_test.go +++ b/internal/git/git_more_test.go @@ -503,12 +503,9 @@ func TestUntrackFilesNotTracked(t *testing.T) { } } -// ─── DiscardFiles ─────────────────────────────────────────────────────────── - func TestDiscardFiles_TrackedOnly(t *testing.T) { dir := initRepo(t) - // Create a tracked file, commit it, then modify it. writeFile(t, dir, "tracked.txt", "original\n") mustRunGit(t, dir, "add", "tracked.txt") mustRunGit(t, dir, "commit", "-m", "add tracked.txt") @@ -537,7 +534,6 @@ func TestDiscardFiles_TrackedOnly(t *testing.T) { func TestDiscardFiles_UntrackedOnly(t *testing.T) { dir := initRepo(t) - // Create an untracked file and a tracked modification. writeFile(t, dir, "untracked.txt", "new file\n") writeFile(t, dir, "README.md", "modified readme\n") @@ -599,7 +595,6 @@ func TestDiscardFiles_Mixed(t *testing.T) { func TestDiscardFiles_StagedNewFile(t *testing.T) { dir := initRepo(t) - // Create and stage a new file. writeFile(t, dir, "staged.txt", "staged content\n") mustRunGit(t, dir, "add", "staged.txt") @@ -656,13 +651,9 @@ func TestDiscardFiles_Empty(t *testing.T) { } } -// TestDiscardFiles_UntrackedDirectory verifies that untracked directories -// (reported as "?? dir/" by git status --porcelain) are removed. -// This requires the -d flag on git clean. func TestDiscardFiles_UntrackedDirectory(t *testing.T) { dir := initRepo(t) - // Create an untracked directory with files inside. subdir := filepath.Join(dir, "newdir") if err := os.MkdirAll(subdir, 0755); err != nil { t.Fatalf("MkdirAll: %v", err) diff --git a/internal/git/git_test.go b/internal/git/git_test.go index 18250bd..c381c14 100644 --- a/internal/git/git_test.go +++ b/internal/git/git_test.go @@ -10,8 +10,6 @@ import ( "github.com/alexandreafj/gitm/internal/git" ) -// ─── helpers ──────────────────────────────────────────────────────────────── - // initRepo creates a temporary, fully-initialized git repo with an initial // commit so that HEAD exists and all operations are valid. func initRepo(t *testing.T) string { @@ -134,15 +132,11 @@ func unstagedModifiedFiles(t *testing.T, dir string) []string { return files } -// ─── ResetSoft ────────────────────────────────────────────────────────────── - func TestResetSoft(t *testing.T) { dir := initRepo(t) - // Make a commit on top of the initial one. makeCommit(t, dir, "feature.go", "package main\n", "add feature") - // Verify we have 2 commits. log, err := git.CommitLog(dir, 5) if err != nil { t.Fatalf("CommitLog: %v", err) @@ -176,8 +170,6 @@ func TestResetSoft(t *testing.T) { } } -// ─── ResetMixed ───────────────────────────────────────────────────────────── - func TestResetMixed(t *testing.T) { dir := initRepo(t) @@ -209,8 +201,6 @@ func TestResetMixed(t *testing.T) { } } -// ─── ResetHard ────────────────────────────────────────────────────────────── - func TestResetHard(t *testing.T) { dir := initRepo(t) @@ -238,8 +228,6 @@ func TestResetHard(t *testing.T) { } } -// ─── ResetHard multi-commit ───────────────────────────────────────────────── - func TestResetHardMultipleCommits(t *testing.T) { dir := initRepo(t) @@ -258,8 +246,6 @@ func TestResetHardMultipleCommits(t *testing.T) { } } -// ─── CommitLog ────────────────────────────────────────────────────────────── - func TestCommitLog(t *testing.T) { dir := initRepo(t) @@ -332,8 +318,6 @@ func TestCommitLog(t *testing.T) { }) } -// ─── ResetSoft preserves content through multiple commits ──────────────────── - func TestResetSoftMultipleCommits(t *testing.T) { dir := initRepo(t) @@ -344,7 +328,6 @@ func TestResetSoftMultipleCommits(t *testing.T) { t.Fatalf("ResetSoft HEAD~2: %v", err) } - // Both files should be staged. staged := stagedFiles(t, dir) stagedSet := make(map[string]bool) for _, f := range staged { @@ -359,16 +342,10 @@ func TestResetSoftMultipleCommits(t *testing.T) { } } -// ─── ForcePush (local bare remote) ────────────────────────────────────────── - -// TestForcePush sets up a local bare repository as "origin" to exercise the -// ForcePush code path without requiring network access. func TestForcePush(t *testing.T) { - // Create a bare repo to act as origin. bareDir := t.TempDir() mustRunGit(t, bareDir, "init", "--bare", "--initial-branch=main") - // Create a working repo and push an initial commit. workDir := initRepo(t) mustRunGit(t, workDir, "config", "user.email", "test@example.com") mustRunGit(t, workDir, "config", "user.name", "Test User") @@ -382,7 +359,6 @@ func TestForcePush(t *testing.T) { mustRunGit(t, workDir, "push", "--set-upstream", "origin", branch) - // Make a new local commit then push it. makeCommit(t, workDir, "pushed.go", "pushed\n", "pushed commit") mustRunGit(t, workDir, "push", "origin", branch) @@ -399,7 +375,6 @@ func TestForcePush(t *testing.T) { t.Fatalf("ForcePush: %v", pushErr) } - // Verify origin now has the rewritten commit by cloning the bare repo. cloneDir := t.TempDir() mustRunGit(t, cloneDir, "clone", bareDir, ".") log, logErr := git.CommitLog(cloneDir, 1) @@ -414,10 +389,7 @@ func TestForcePush(t *testing.T) { } } -// ─── FetchBranch ──────────────────────────────────────────────────────────── - func TestFetchBranch(t *testing.T) { - // Create a bare origin and a working clone. bareDir := t.TempDir() mustRunGit(t, bareDir, "init", "--bare", "--initial-branch=main") @@ -425,7 +397,6 @@ func TestFetchBranch(t *testing.T) { mustRunGit(t, workDir, "remote", "add", "origin", bareDir) mustRunGit(t, workDir, "push", "--set-upstream", "origin", "main") - // Create a feature branch on origin via a second clone. clone2 := t.TempDir() mustRunGit(t, clone2, "clone", bareDir, ".") mustRunGit(t, clone2, "config", "user.email", "test@example.com") diff --git a/internal/runner/parallel_test.go b/internal/runner/parallel_test.go index 3174508..2e7b389 100644 --- a/internal/runner/parallel_test.go +++ b/internal/runner/parallel_test.go @@ -10,8 +10,6 @@ import ( "github.com/alexandreafj/gitm/internal/runner" ) -// ─── helpers ──────────────────────────────────────────────────────────────── - // newTestRepo creates a test repository with a given alias. func newTestRepo(alias string) *db.Repository { return &db.Repository{ @@ -23,8 +21,6 @@ func newTestRepo(alias string) *db.Repository { } } -// ─── TestRunSuccess ───────────────────────────────────────────────────────── - func TestRunSuccess(t *testing.T) { repos := []*db.Repository{ newTestRepo("repo1"), @@ -39,7 +35,6 @@ func TestRunSuccess(t *testing.T) { results := runner.Run(repos, op) - // Verify all repos completed successfully if len(results) != 3 { t.Errorf("expected 3 results, got %d", len(results)) } @@ -62,8 +57,6 @@ func TestRunSuccess(t *testing.T) { } } -// ─── TestRunWithError ─────────────────────────────────────────────────────── - func TestRunWithError(t *testing.T) { repos := []*db.Repository{ newTestRepo("repo1"), @@ -80,7 +73,6 @@ func TestRunWithError(t *testing.T) { results := runner.Run(repos, op) - // Verify error was captured errorFound := false for i, r := range results { if r.Repo.Alias == "repo2_error" { @@ -103,8 +95,6 @@ func TestRunWithError(t *testing.T) { } } -// ─── TestRunSkipped ───────────────────────────────────────────────────────── - func TestRunSkipped(t *testing.T) { repos := []*db.Repository{ newTestRepo("repo1"), @@ -121,7 +111,6 @@ func TestRunSkipped(t *testing.T) { results := runner.Run(repos, op) - // Verify skip was captured skipFound := false for i, r := range results { if r.Repo.Alias == "repo2_skip" { @@ -144,8 +133,6 @@ func TestRunSkipped(t *testing.T) { } } -// ─── TestRunParallelExecution ─────────────────────────────────────────────── - func TestRunParallelExecution(t *testing.T) { repos := []*db.Repository{ newTestRepo("repo1"), @@ -181,16 +168,12 @@ func TestRunParallelExecution(t *testing.T) { _ = runner.Run(repos, op) - // With parallelism, maxConcurrent should be > 1 if maxConcur < 2 { t.Errorf("expected parallel execution (maxConcur > 1), got %d", maxConcur) } } -// ─── TestRunMaxConcurrency ────────────────────────────────────────────────── - func TestRunMaxConcurrency(t *testing.T) { - // Create more repos than the concurrency limit (10) repos := make([]*db.Repository, 20) for i := 0; i < 20; i++ { repos[i] = newTestRepo(fmt.Sprintf("repo%d", i)) @@ -222,15 +205,12 @@ func TestRunMaxConcurrency(t *testing.T) { _ = runner.Run(repos, op) - // Max concurrency should be <= 10 (the hardcoded limit) // We allow a small margin for timing issues if maxConcur > 12 { t.Errorf("expected max concurrency <= 10, got %d", maxConcur) } } -// ─── TestRunEmptyRepos ────────────────────────────────────────────────────── - func TestRunEmptyRepos(t *testing.T) { repos := []*db.Repository{} @@ -251,8 +231,6 @@ func TestRunEmptyRepos(t *testing.T) { } } -// ─── TestRunResultOrder ───────────────────────────────────────────────────── - func TestRunResultOrder(t *testing.T) { repos := []*db.Repository{ newTestRepo("first"), @@ -266,7 +244,6 @@ func TestRunResultOrder(t *testing.T) { results := runner.Run(repos, op) - // Results should be in the same order as input repos expectedAliases := []string{"first", "second", "third"} for i, alias := range expectedAliases { if results[i].Repo.Alias != alias { @@ -275,8 +252,6 @@ func TestRunResultOrder(t *testing.T) { } } -// ─── TestRunMixedStatuses ─────────────────────────────────────────────────── - func TestRunMixedStatuses(t *testing.T) { repos := []*db.Repository{ newTestRepo("success"), @@ -315,8 +290,6 @@ func TestRunMixedStatuses(t *testing.T) { } } -// ─── TestRunMessagePreservation ───────────────────────────────────────────── - func TestRunMessagePreservation(t *testing.T) { repos := []*db.Repository{ newTestRepo("repo1"), @@ -338,8 +311,6 @@ func TestRunMessagePreservation(t *testing.T) { } } -// ─── TestHasErrors ────────────────────────────────────────────────────────── - func TestHasErrors(t *testing.T) { tests := []struct { name string @@ -400,8 +371,6 @@ func TestHasErrors(t *testing.T) { } } -// ─── TestErrorCount ───────────────────────────────────────────────────────── - func TestErrorCount(t *testing.T) { tests := []struct { name string