diff --git a/internal/homesick/core/commit_test.go b/internal/homesick/core/commit_test.go new file mode 100644 index 0000000..20064e5 --- /dev/null +++ b/internal/homesick/core/commit_test.go @@ -0,0 +1,112 @@ +package core_test + +import ( + "io" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + "time" + + "git.hrafn.xyz/aether/gosick/internal/homesick/core" + git "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +type CommitSuite struct { + suite.Suite + tmpDir string + homeDir string + reposDir string + app *core.App +} + +func TestCommitSuite(t *testing.T) { + suite.Run(t, new(CommitSuite)) +} + +func (s *CommitSuite) SetupTest() { + s.tmpDir = s.T().TempDir() + s.homeDir = filepath.Join(s.tmpDir, "home") + s.reposDir = filepath.Join(s.homeDir, ".homesick", "repos") + require.NoError(s.T(), os.MkdirAll(s.reposDir, 0o755)) + + s.app = &core.App{ + HomeDir: s.homeDir, + ReposDir: s.reposDir, + Stdout: io.Discard, + Stderr: io.Discard, + } +} + +func (s *CommitSuite) createCastleRepo(castle string) string { + castleRoot := filepath.Join(s.reposDir, castle) + repo, err := git.PlainInit(castleRoot, false) + require.NoError(s.T(), err) + + filePath := filepath.Join(castleRoot, "home", ".vimrc") + require.NoError(s.T(), os.MkdirAll(filepath.Dir(filePath), 0o755)) + require.NoError(s.T(), os.WriteFile(filePath, []byte("set number\n"), 0o644)) + + wt, err := repo.Worktree() + require.NoError(s.T(), err) + _, err = wt.Add("home/.vimrc") + require.NoError(s.T(), err) + _, err = wt.Commit("initial", &git.CommitOptions{Author: &object.Signature{ + Name: "Commit Test", + Email: "commit@test.local", + When: time.Now(), + }}) + require.NoError(s.T(), err) + + return castleRoot +} + +func gitOutputAt(dir string, args ...string) (string, error) { + cmd := exec.Command("git", args...) + cmd.Dir = dir + out, err := cmd.Output() + if err != nil { + return "", err + } + return string(out), nil +} + +func (s *CommitSuite) TestCommit_CreatesCommitWithMessage() { + castleRoot := s.createCastleRepo("dotfiles") + target := filepath.Join(castleRoot, "home", ".vimrc") + require.NoError(s.T(), os.WriteFile(target, []byte("set number\nsyntax on\n"), 0o644)) + + require.NoError(s.T(), s.app.Commit("dotfiles", "update vimrc")) + + subject, err := gitOutputAt(castleRoot, "log", "-1", "--pretty=%s") + require.NoError(s.T(), err) + require.Equal(s.T(), "update vimrc\n", subject) +} + +func (s *CommitSuite) TestCommit_MessageEscaping() { + castleRoot := s.createCastleRepo("dotfiles") + target := filepath.Join(castleRoot, "home", ".vimrc") + require.NoError(s.T(), os.WriteFile(target, []byte("set number\nset relativenumber\n"), 0o644)) + + msg := "fix \"quoted\" message: keep spaces" + require.NoError(s.T(), s.app.Commit("dotfiles", msg)) + + subject, err := gitOutputAt(castleRoot, "log", "-1", "--pretty=%s") + require.NoError(s.T(), err) + require.Equal(s.T(), msg+"\n", subject) +} + +func (s *CommitSuite) TestCommit_RequiresMessage() { + err := s.app.Commit("dotfiles", " ") + require.Error(s.T(), err) + require.Contains(s.T(), strings.ToLower(err.Error()), "message") +} + +func (s *CommitSuite) TestCommit_MissingCastleReturnsError() { + err := s.app.Commit("missing", "msg") + require.Error(s.T(), err) +}