gosick #1

Merged
DelphicOkami merged 162 commits from gosick into main 2026-03-21 23:08:00 +00:00
7 changed files with 66 additions and 66 deletions
Showing only changes of commit d642870a66 - Show all commits

View File

@@ -8,10 +8,11 @@ import (
) )
func main() { func main() {
exitCode := run(os.Args[1:], os.Stdout, os.Stderr) _ = os.Setenv("GIT_TERMINAL_PROMPT", "0")
exitCode := run(os.Args[1:], os.Stdin, os.Stdout, os.Stderr)
os.Exit(exitCode) os.Exit(exitCode)
} }
func run(args []string, stdout io.Writer, stderr io.Writer) int { func run(args []string, stdin io.Reader, stdout io.Writer, stderr io.Writer) int {
return cli.Run(args, stdout, stderr) return cli.Run(args, stdin, stdout, stderr)
} }

View File

@@ -13,7 +13,7 @@ func TestRunVersionCommand(t *testing.T) {
stdout := &bytes.Buffer{} stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{} stderr := &bytes.Buffer{}
exitCode := run([]string{"version"}, stdout, stderr) exitCode := run([]string{"version"}, bytes.NewBuffer(nil), stdout, stderr)
if exitCode != 0 { if exitCode != 0 {
t.Fatalf("run(version) exit code = %d, want 0", exitCode) t.Fatalf("run(version) exit code = %d, want 0", exitCode)
} }

View File

@@ -13,10 +13,10 @@ import (
"github.com/alecthomas/kong" "github.com/alecthomas/kong"
) )
func Run(args []string, stdout io.Writer, stderr io.Writer) int { func Run(args []string, stdin io.Reader, stdout io.Writer, stderr io.Writer) int {
model := &cliModel{} model := &cliModel{}
app, err := core.New(stdout, stderr) app, err := core.NewApp(stdin, stdout, stderr)
if err != nil { if err != nil {
_, _ = fmt.Fprintf(stderr, "error: %v\n", err) _, _ = fmt.Fprintf(stderr, "error: %v\n", err)
return 1 return 1
@@ -227,11 +227,7 @@ func (c *openCmd) Run(app *core.App) error { return app.Open(defaultCastle(c.
func (c *execCmd) Run(app *core.App) error { return app.Exec(c.Castle, c.Command) } func (c *execCmd) Run(app *core.App) error { return app.Exec(c.Castle, c.Command) }
func (c *execAllCmd) Run(app *core.App) error { return app.ExecAll(c.Command) } func (c *execAllCmd) Run(app *core.App) error { return app.ExecAll(c.Command) }
func (c *rcCmd) Run(app *core.App) error { func (c *rcCmd) Run(app *core.App) error {
originalForce := app.Force return app.Rc(defaultCastle(c.Castle), c.Force)
app.Force = c.Force
err := app.Rc(defaultCastle(c.Castle))
app.Force = originalForce
return err
} }
func (c *generateCmd) Run(app *core.App) error { return app.Generate(c.Path) } func (c *generateCmd) Run(app *core.App) error { return app.Generate(c.Path) }
@@ -329,11 +325,3 @@ type cliExitError struct {
func (e *cliExitError) Error() string { func (e *cliExitError) Error() string {
return e.err.Error() return e.err.Error()
} }
func notImplemented(command string) error {
return &cliExitError{code: 2, err: fmt.Errorf("%s is not implemented in Go yet", command)}
}
func init() {
_ = os.Setenv("GIT_TERMINAL_PROMPT", "0")
}

View File

@@ -67,7 +67,7 @@ func (s *CLISuite) TestRun_VersionAliases() {
s.stdout.Reset() s.stdout.Reset()
s.stderr.Reset() s.stderr.Reset()
exitCode := cli.Run(args, s.stdout, s.stderr) exitCode := cli.Run(args, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Equal(s.T(), version.String+"\n", s.stdout.String()) require.Equal(s.T(), version.String+"\n", s.stdout.String())
require.Empty(s.T(), s.stderr.String()) require.Empty(s.T(), s.stderr.String())
@@ -75,7 +75,7 @@ func (s *CLISuite) TestRun_VersionAliases() {
} }
func (s *CLISuite) TestRun_ShowPath_DefaultCastle() { func (s *CLISuite) TestRun_ShowPath_DefaultCastle() {
exitCode := cli.Run([]string{"show_path"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"show_path"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Equal(s.T(), filepath.Join(s.homeDir, ".homesick", "repos", "dotfiles")+"\n", s.stdout.String()) require.Equal(s.T(), filepath.Join(s.homeDir, ".homesick", "repos", "dotfiles")+"\n", s.stdout.String())
@@ -83,7 +83,7 @@ func (s *CLISuite) TestRun_ShowPath_DefaultCastle() {
} }
func (s *CLISuite) TestRun_Cd_DefaultCastle() { func (s *CLISuite) TestRun_Cd_DefaultCastle() {
exitCode := cli.Run([]string{"cd"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"cd"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Equal(s.T(), filepath.Join(s.homeDir, ".homesick", "repos", "dotfiles")+"\n", s.stdout.String()) require.Equal(s.T(), filepath.Join(s.homeDir, ".homesick", "repos", "dotfiles")+"\n", s.stdout.String())
@@ -91,7 +91,7 @@ func (s *CLISuite) TestRun_Cd_DefaultCastle() {
} }
func (s *CLISuite) TestRun_Cd_ExplicitCastle() { func (s *CLISuite) TestRun_Cd_ExplicitCastle() {
exitCode := cli.Run([]string{"cd", "work"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"cd", "work"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Equal(s.T(), filepath.Join(s.homeDir, ".homesick", "repos", "work")+"\n", s.stdout.String()) require.Equal(s.T(), filepath.Join(s.homeDir, ".homesick", "repos", "work")+"\n", s.stdout.String())
@@ -102,7 +102,7 @@ func (s *CLISuite) TestRun_Exec_RunsCommandInCastleRoot() {
castleRoot := filepath.Join(s.homeDir, ".homesick", "repos", "dotfiles") castleRoot := filepath.Join(s.homeDir, ".homesick", "repos", "dotfiles")
require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755)) require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755))
exitCode := cli.Run([]string{"exec", "dotfiles", "pwd"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"exec", "dotfiles", "pwd"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Contains(s.T(), s.stdout.String(), castleRoot) require.Contains(s.T(), s.stdout.String(), castleRoot)
@@ -114,7 +114,7 @@ func (s *CLISuite) TestRun_Exec_WithPretend_DoesNotExecute() {
require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755)) require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755))
target := filepath.Join(castleRoot, "should-not-exist") target := filepath.Join(castleRoot, "should-not-exist")
exitCode := cli.Run([]string{"--pretend", "exec", "dotfiles", "touch should-not-exist"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"--pretend", "exec", "dotfiles", "touch should-not-exist"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.NoFileExists(s.T(), target) require.NoFileExists(s.T(), target)
@@ -127,7 +127,7 @@ func (s *CLISuite) TestRun_Exec_WithDryRunAlias_DoesNotExecute() {
require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755)) require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755))
target := filepath.Join(castleRoot, "should-not-exist") target := filepath.Join(castleRoot, "should-not-exist")
exitCode := cli.Run([]string{"--dry-run", "exec", "dotfiles", "touch should-not-exist"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"--dry-run", "exec", "dotfiles", "touch should-not-exist"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.NoFileExists(s.T(), target) require.NoFileExists(s.T(), target)
@@ -139,7 +139,7 @@ func (s *CLISuite) TestRun_Exec_WithQuiet_SuppressesStatusOutput() {
castleRoot := filepath.Join(s.homeDir, ".homesick", "repos", "dotfiles") castleRoot := filepath.Join(s.homeDir, ".homesick", "repos", "dotfiles")
require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755)) require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755))
exitCode := cli.Run([]string{"--quiet", "exec", "dotfiles", "true"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"--quiet", "exec", "dotfiles", "true"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Empty(s.T(), s.stdout.String()) require.Empty(s.T(), s.stdout.String())
@@ -147,7 +147,7 @@ func (s *CLISuite) TestRun_Exec_WithQuiet_SuppressesStatusOutput() {
} }
func (s *CLISuite) TestRun_PullAll_NoCastlesIsNoop() { func (s *CLISuite) TestRun_PullAll_NoCastlesIsNoop() {
exitCode := cli.Run([]string{"pull", "--all"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"pull", "--all"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Empty(s.T(), s.stderr.String()) require.Empty(s.T(), s.stderr.String())
@@ -158,7 +158,7 @@ func (s *CLISuite) TestRun_Rc_HomesickrcRequiresForce() {
require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755)) require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755))
require.NoError(s.T(), os.WriteFile(filepath.Join(castleRoot, ".homesickrc"), []byte("# ruby\n"), 0o644)) require.NoError(s.T(), os.WriteFile(filepath.Join(castleRoot, ".homesickrc"), []byte("# ruby\n"), 0o644))
exitCode := cli.Run([]string{"rc", "dotfiles"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"rc", "dotfiles"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.NotEqual(s.T(), 0, exitCode) require.NotEqual(s.T(), 0, exitCode)
require.Contains(s.T(), s.stderr.String(), "--force") require.Contains(s.T(), s.stderr.String(), "--force")
@@ -169,14 +169,14 @@ func (s *CLISuite) TestRun_Rc_WithForceRuns() {
require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755)) require.NoError(s.T(), os.MkdirAll(castleRoot, 0o755))
require.NoError(s.T(), os.WriteFile(filepath.Join(castleRoot, ".homesickrc"), []byte("# ruby\n"), 0o644)) require.NoError(s.T(), os.WriteFile(filepath.Join(castleRoot, ".homesickrc"), []byte("# ruby\n"), 0o644))
exitCode := cli.Run([]string{"rc", "--force", "dotfiles"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"rc", "--force", "dotfiles"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Empty(s.T(), s.stderr.String()) require.Empty(s.T(), s.stderr.String())
} }
func (s *CLISuite) TestRun_CloneSubcommandHelp() { func (s *CLISuite) TestRun_CloneSubcommandHelp() {
exitCode := cli.Run([]string{"clone", "--help"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"clone", "--help"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Contains(s.T(), s.stdout.String(), "clone") require.Contains(s.T(), s.stdout.String(), "clone")
@@ -189,7 +189,7 @@ func (s *CLISuite) TestRun_Help_UsesProgramNameAndDescription() {
s.T().Cleanup(func() { os.Args = originalArgs }) s.T().Cleanup(func() { os.Args = originalArgs })
os.Args = []string{"gosick"} os.Args = []string{"gosick"}
exitCode := cli.Run([]string{"--help"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"--help"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Contains(s.T(), s.stdout.String(), "Usage: gosick") require.Contains(s.T(), s.stdout.String(), "Usage: gosick")
@@ -204,7 +204,7 @@ func (s *CLISuite) TestRun_SymlinkAlias_MatchesLinkCommand() {
require.NoError(s.T(), os.MkdirAll(castleHome, 0o755)) require.NoError(s.T(), os.MkdirAll(castleHome, 0o755))
require.NoError(s.T(), os.WriteFile(filepath.Join(castleHome, ".vimrc"), []byte("set number\n"), 0o644)) require.NoError(s.T(), os.WriteFile(filepath.Join(castleHome, ".vimrc"), []byte("set number\n"), 0o644))
exitCode := cli.Run([]string{"symlink", "dotfiles"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"symlink", "dotfiles"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
target := filepath.Join(s.homeDir, ".vimrc") target := filepath.Join(s.homeDir, ".vimrc")
@@ -215,7 +215,7 @@ func (s *CLISuite) TestRun_SymlinkAlias_MatchesLinkCommand() {
} }
func (s *CLISuite) TestRun_Commit_PositionalMessageCompatibility() { func (s *CLISuite) TestRun_Commit_PositionalMessageCompatibility() {
exitCode := cli.Run([]string{"--pretend", "commit", "dotfiles", "behavior-suite-commit"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"--pretend", "commit", "dotfiles", "behavior-suite-commit"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Contains(s.T(), s.stdout.String(), "git commit -m behavior-suite-commit") require.Contains(s.T(), s.stdout.String(), "git commit -m behavior-suite-commit")
@@ -225,7 +225,7 @@ func (s *CLISuite) TestRun_Commit_PositionalMessageCompatibility() {
func (s *CLISuite) TestRun_List_NoArguments() { func (s *CLISuite) TestRun_List_NoArguments() {
s.createCastleRepo("dotfiles") s.createCastleRepo("dotfiles")
exitCode := cli.Run([]string{"list"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"list"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Contains(s.T(), s.stdout.String(), "dotfiles") require.Contains(s.T(), s.stdout.String(), "dotfiles")
@@ -235,7 +235,7 @@ func (s *CLISuite) TestRun_List_NoArguments() {
func (s *CLISuite) TestRun_Generate_CreatesNewCastle() { func (s *CLISuite) TestRun_Generate_CreatesNewCastle() {
castlePath := filepath.Join(s.T().TempDir(), "my-castle") castlePath := filepath.Join(s.T().TempDir(), "my-castle")
exitCode := cli.Run([]string{"generate", castlePath}, s.stdout, s.stderr) exitCode := cli.Run([]string{"generate", castlePath}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.DirExists(s.T(), filepath.Join(castlePath, ".git")) require.DirExists(s.T(), filepath.Join(castlePath, ".git"))
@@ -243,7 +243,7 @@ func (s *CLISuite) TestRun_Generate_CreatesNewCastle() {
} }
func (s *CLISuite) TestRun_Clone_WithoutArgs() { func (s *CLISuite) TestRun_Clone_WithoutArgs() {
exitCode := cli.Run([]string{"clone"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"clone"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
// Clone requires arguments, should fail // Clone requires arguments, should fail
require.NotEqual(s.T(), 0, exitCode) require.NotEqual(s.T(), 0, exitCode)
@@ -253,7 +253,7 @@ func (s *CLISuite) TestRun_Status_DefaultCastle() {
castleRoot := s.createCastleRepo("dotfiles") castleRoot := s.createCastleRepo("dotfiles")
require.NoError(s.T(), os.WriteFile(filepath.Join(castleRoot, "home", ".vimrc"), []byte("changed\n"), 0o644)) require.NoError(s.T(), os.WriteFile(filepath.Join(castleRoot, "home", ".vimrc"), []byte("changed\n"), 0o644))
exitCode := cli.Run([]string{"status"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"status"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Contains(s.T(), s.stdout.String(), "modified:") require.Contains(s.T(), s.stdout.String(), "modified:")
@@ -264,7 +264,7 @@ func (s *CLISuite) TestRun_Diff_DefaultCastle() {
castleRoot := s.createCastleRepo("dotfiles") castleRoot := s.createCastleRepo("dotfiles")
require.NoError(s.T(), os.WriteFile(filepath.Join(castleRoot, "home", ".vimrc"), []byte("changed\n"), 0o644)) require.NoError(s.T(), os.WriteFile(filepath.Join(castleRoot, "home", ".vimrc"), []byte("changed\n"), 0o644))
exitCode := cli.Run([]string{"diff"}, s.stdout, s.stderr) exitCode := cli.Run([]string{"diff"}, bytes.NewBuffer(nil), s.stdout, s.stderr)
require.Equal(s.T(), 0, exitCode) require.Equal(s.T(), 0, exitCode)
require.Contains(s.T(), s.stdout.String(), "diff --git") require.Contains(s.T(), s.stdout.String(), "diff --git")

View File

@@ -21,13 +21,15 @@ type App struct {
Stdin io.Reader Stdin io.Reader
Stdout io.Writer Stdout io.Writer
Stderr io.Writer Stderr io.Writer
Verbose bool
Force bool Force bool
Quiet bool Quiet bool
Pretend bool Pretend bool
} }
func New(stdout io.Writer, stderr io.Writer) (*App, error) { func NewApp(stdin io.Reader, stdout io.Writer, stderr io.Writer) (*App, error) {
if stdin == nil {
return nil, errors.New("stdin reader cannot be nil")
}
if stdout == nil { if stdout == nil {
return nil, errors.New("stdout writer cannot be nil") return nil, errors.New("stdout writer cannot be nil")
} }
@@ -43,7 +45,7 @@ func New(stdout io.Writer, stderr io.Writer) (*App, error) {
return &App{ return &App{
HomeDir: home, HomeDir: home,
ReposDir: filepath.Join(home, ".homesick", "repos"), ReposDir: filepath.Join(home, ".homesick", "repos"),
Stdin: os.Stdin, Stdin: stdin,
Stdout: stdout, Stdout: stdout,
Stderr: stderr, Stderr: stderr,
}, nil }, nil
@@ -845,7 +847,7 @@ func gitOutput(dir string, args ...string) (string, error) {
// If a .homesickrc file exists in the castle root and no parity.rb wrapper // If a .homesickrc file exists in the castle root and no parity.rb wrapper
// already exists in .homesick.d, a Ruby wrapper script named parity.rb is // already exists in .homesick.d, a Ruby wrapper script named parity.rb is
// written there before execution so that it sorts first. // written there before execution so that it sorts first.
func (a *App) Rc(castle string) error { func (a *App) Rc(castle string, force bool) error {
castleRoot := filepath.Join(a.ReposDir, castle) castleRoot := filepath.Join(a.ReposDir, castle)
if _, err := os.Stat(castleRoot); err != nil { if _, err := os.Stat(castleRoot); err != nil {
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
@@ -857,7 +859,7 @@ func (a *App) Rc(castle string) error {
homesickD := filepath.Join(castleRoot, ".homesick.d") homesickD := filepath.Join(castleRoot, ".homesick.d")
homesickRc := filepath.Join(castleRoot, ".homesickrc") homesickRc := filepath.Join(castleRoot, ".homesickrc")
if _, err := os.Stat(homesickRc); err == nil && !a.Force { if _, err := os.Stat(homesickRc); err == nil && !force {
return errors.New("refusing to run legacy .homesickrc without --force") return errors.New("refusing to run legacy .homesickrc without --force")
} }

View File

@@ -6,9 +6,19 @@ import (
"testing" "testing"
) )
func TestNewRejectsNilWriters(t *testing.T) { func TestNewAppRejectsNilReaders(t *testing.T) {
t.Run("nil stdin", func(t *testing.T) {
app, err := NewApp(nil, &bytes.Buffer{}, &bytes.Buffer{})
if err == nil {
t.Fatal("expected error for nil stdin")
}
if app != nil {
t.Fatal("expected nil app for nil stdin")
}
})
t.Run("nil stdout", func(t *testing.T) { t.Run("nil stdout", func(t *testing.T) {
app, err := New(nil, &bytes.Buffer{}) app, err := NewApp(new(bytes.Buffer), nil, &bytes.Buffer{})
if err == nil { if err == nil {
t.Fatal("expected error for nil stdout") t.Fatal("expected error for nil stdout")
} }
@@ -18,7 +28,7 @@ func TestNewRejectsNilWriters(t *testing.T) {
}) })
t.Run("nil stderr", func(t *testing.T) { t.Run("nil stderr", func(t *testing.T) {
app, err := New(&bytes.Buffer{}, nil) app, err := NewApp(new(bytes.Buffer), &bytes.Buffer{}, nil)
if err == nil { if err == nil {
t.Fatal("expected error for nil stderr") t.Fatal("expected error for nil stderr")
} }
@@ -49,11 +59,12 @@ func TestDeriveDestination(t *testing.T) {
} }
} }
func TestNewInitializesApp(t *testing.T) { func TestNewAppInitializesApp(t *testing.T) {
stdin := new(bytes.Buffer)
stdout := &bytes.Buffer{} stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{} stderr := &bytes.Buffer{}
app, err := New(stdout, stderr) app, err := NewApp(stdin, stdout, stderr)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@@ -61,6 +72,9 @@ func TestNewInitializesApp(t *testing.T) {
t.Fatal("expected app instance") t.Fatal("expected app instance")
} }
if app.Stdin != stdin {
t.Fatal("expected stdin reader to be assigned")
}
if app.Stdout != stdout { if app.Stdout != stdout {
t.Fatal("expected stdout writer to be assigned") t.Fatal("expected stdout writer to be assigned")
} }

View File

@@ -53,7 +53,7 @@ var _ io.Writer
// TestRc_UnknownCastleReturnsError ensures Rc returns an error when the // TestRc_UnknownCastleReturnsError ensures Rc returns an error when the
// castle directory does not exist. // castle directory does not exist.
func (s *RcSuite) TestRc_UnknownCastleReturnsError() { func (s *RcSuite) TestRc_UnknownCastleReturnsError() {
err := s.app.Rc("nonexistent") err := s.app.Rc("nonexistent", false)
require.Error(s.T(), err) require.Error(s.T(), err)
} }
@@ -61,7 +61,7 @@ func (s *RcSuite) TestRc_UnknownCastleReturnsError() {
// .homesickrc are present. // .homesickrc are present.
func (s *RcSuite) TestRc_NoScriptsAndNoHomesickrcIsNoop() { func (s *RcSuite) TestRc_NoScriptsAndNoHomesickrcIsNoop() {
s.createCastle("dotfiles") s.createCastle("dotfiles")
require.NoError(s.T(), s.app.Rc("dotfiles")) require.NoError(s.T(), s.app.Rc("dotfiles", false))
} }
// TestRc_HomesickrcRequiresForce ensures legacy .homesickrc does not run // TestRc_HomesickrcRequiresForce ensures legacy .homesickrc does not run
@@ -71,7 +71,7 @@ func (s *RcSuite) TestRc_HomesickrcRequiresForce() {
homesickRc := filepath.Join(castleRoot, ".homesickrc") homesickRc := filepath.Join(castleRoot, ".homesickrc")
require.NoError(s.T(), os.WriteFile(homesickRc, []byte("# ruby setup code\n"), 0o644)) require.NoError(s.T(), os.WriteFile(homesickRc, []byte("# ruby setup code\n"), 0o644))
err := s.app.Rc("dotfiles") err := s.app.Rc("dotfiles", false)
require.Error(s.T(), err) require.Error(s.T(), err)
require.Contains(s.T(), err.Error(), "--force") require.Contains(s.T(), err.Error(), "--force")
require.NoFileExists(s.T(), filepath.Join(castleRoot, ".homesick.d", "parity.rb")) require.NoFileExists(s.T(), filepath.Join(castleRoot, ".homesick.d", "parity.rb"))
@@ -84,8 +84,7 @@ func (s *RcSuite) TestRc_HomesickrcRunsWithForce() {
homesickRc := filepath.Join(castleRoot, ".homesickrc") homesickRc := filepath.Join(castleRoot, ".homesickrc")
require.NoError(s.T(), os.WriteFile(homesickRc, []byte("# ruby setup code\n"), 0o644)) require.NoError(s.T(), os.WriteFile(homesickRc, []byte("# ruby setup code\n"), 0o644))
s.app.Force = true require.NoError(s.T(), s.app.Rc("dotfiles", true))
require.NoError(s.T(), s.app.Rc("dotfiles"))
require.FileExists(s.T(), filepath.Join(castleRoot, ".homesick.d", "parity.rb")) require.FileExists(s.T(), filepath.Join(castleRoot, ".homesick.d", "parity.rb"))
} }
@@ -103,7 +102,7 @@ func (s *RcSuite) TestRc_ExecutesScriptsInSortedOrder() {
require.NoError(s.T(), os.WriteFile(scriptA, []byte("#!/bin/sh\necho a >> "+orderFile+"\n"), 0o755)) require.NoError(s.T(), os.WriteFile(scriptA, []byte("#!/bin/sh\necho a >> "+orderFile+"\n"), 0o755))
require.NoError(s.T(), os.WriteFile(scriptB, []byte("#!/bin/sh\necho b >> "+orderFile+"\n"), 0o755)) require.NoError(s.T(), os.WriteFile(scriptB, []byte("#!/bin/sh\necho b >> "+orderFile+"\n"), 0o755))
require.NoError(s.T(), s.app.Rc("dotfiles")) require.NoError(s.T(), s.app.Rc("dotfiles", false))
content, err := os.ReadFile(orderFile) content, err := os.ReadFile(orderFile)
require.NoError(s.T(), err) require.NoError(s.T(), err)
@@ -121,7 +120,7 @@ func (s *RcSuite) TestRc_SkipsNonExecutableFiles() {
// Write a script that would exit 1 if actually run — verify it is skipped. // Write a script that would exit 1 if actually run — verify it is skipped.
require.NoError(s.T(), os.WriteFile(notExec, []byte("#!/bin/sh\nexit 1\n"), 0o644)) require.NoError(s.T(), os.WriteFile(notExec, []byte("#!/bin/sh\nexit 1\n"), 0o644))
require.NoError(s.T(), s.app.Rc("dotfiles")) require.NoError(s.T(), s.app.Rc("dotfiles", false))
} }
// TestRc_HomesickrcCreatesRubyWrapper verifies that a .homesickrc file causes // TestRc_HomesickrcCreatesRubyWrapper verifies that a .homesickrc file causes
@@ -130,9 +129,7 @@ func (s *RcSuite) TestRc_HomesickrcCreatesRubyWrapper() {
castleRoot := s.createCastle("dotfiles") castleRoot := s.createCastle("dotfiles")
homesickRc := filepath.Join(castleRoot, ".homesickrc") homesickRc := filepath.Join(castleRoot, ".homesickrc")
require.NoError(s.T(), os.WriteFile(homesickRc, []byte("# ruby setup code\n"), 0o644)) require.NoError(s.T(), os.WriteFile(homesickRc, []byte("# ruby setup code\n"), 0o644))
s.app.Force = true require.NoError(s.T(), s.app.Rc("dotfiles", true))
require.NoError(s.T(), s.app.Rc("dotfiles"))
wrapperPath := filepath.Join(castleRoot, ".homesick.d", "parity.rb") wrapperPath := filepath.Join(castleRoot, ".homesick.d", "parity.rb")
require.FileExists(s.T(), wrapperPath) require.FileExists(s.T(), wrapperPath)
@@ -152,7 +149,6 @@ func (s *RcSuite) TestRc_HomesickrcWrapperNotOverwrittenIfExists() {
castleRoot := s.createCastle("dotfiles") castleRoot := s.createCastle("dotfiles")
homesickRc := filepath.Join(castleRoot, ".homesickrc") homesickRc := filepath.Join(castleRoot, ".homesickrc")
require.NoError(s.T(), os.WriteFile(homesickRc, []byte("# ruby setup code\n"), 0o644)) require.NoError(s.T(), os.WriteFile(homesickRc, []byte("# ruby setup code\n"), 0o644))
s.app.Force = true
homesickD := filepath.Join(castleRoot, ".homesick.d") homesickD := filepath.Join(castleRoot, ".homesick.d")
require.NoError(s.T(), os.MkdirAll(homesickD, 0o755)) require.NoError(s.T(), os.MkdirAll(homesickD, 0o755))
@@ -160,7 +156,7 @@ func (s *RcSuite) TestRc_HomesickrcWrapperNotOverwrittenIfExists() {
originalContent := []byte("#!/bin/sh\n# pre-existing wrapper\n") originalContent := []byte("#!/bin/sh\n# pre-existing wrapper\n")
require.NoError(s.T(), os.WriteFile(wrapperPath, originalContent, 0o755)) require.NoError(s.T(), os.WriteFile(wrapperPath, originalContent, 0o755))
require.NoError(s.T(), s.app.Rc("dotfiles")) require.NoError(s.T(), s.app.Rc("dotfiles", true))
content, err := os.ReadFile(wrapperPath) content, err := os.ReadFile(wrapperPath)
require.NoError(s.T(), err) require.NoError(s.T(), err)
@@ -173,7 +169,6 @@ func (s *RcSuite) TestRc_HomesickrcWrapperCreatedBeforeExecution() {
castleRoot := s.createCastle("dotfiles") castleRoot := s.createCastle("dotfiles")
homesickRc := filepath.Join(castleRoot, ".homesickrc") homesickRc := filepath.Join(castleRoot, ".homesickrc")
require.NoError(s.T(), os.WriteFile(homesickRc, []byte("# ruby setup code\n"), 0o644)) require.NoError(s.T(), os.WriteFile(homesickRc, []byte("# ruby setup code\n"), 0o644))
s.app.Force = true
homesickD := filepath.Join(castleRoot, ".homesick.d") homesickD := filepath.Join(castleRoot, ".homesick.d")
require.NoError(s.T(), os.MkdirAll(homesickD, 0o755)) require.NoError(s.T(), os.MkdirAll(homesickD, 0o755))
@@ -186,7 +181,7 @@ func (s *RcSuite) TestRc_HomesickrcWrapperCreatedBeforeExecution() {
"#!/bin/sh\n[ -f "+wrapperPath+" ] && echo present >> "+orderFile+"\n", "#!/bin/sh\n[ -f "+wrapperPath+" ] && echo present >> "+orderFile+"\n",
), 0o755)) ), 0o755))
require.NoError(s.T(), s.app.Rc("dotfiles")) require.NoError(s.T(), s.app.Rc("dotfiles", true))
content, err := os.ReadFile(orderFile) content, err := os.ReadFile(orderFile)
require.NoError(s.T(), err) require.NoError(s.T(), err)
@@ -203,7 +198,7 @@ func (s *RcSuite) TestRc_FailingScriptReturnsError() {
failing := filepath.Join(homesickD, "10_fail.sh") failing := filepath.Join(homesickD, "10_fail.sh")
require.NoError(s.T(), os.WriteFile(failing, []byte("#!/bin/sh\nexit 42\n"), 0o755)) require.NoError(s.T(), os.WriteFile(failing, []byte("#!/bin/sh\nexit 42\n"), 0o755))
err := s.app.Rc("dotfiles") err := s.app.Rc("dotfiles", false)
require.Error(s.T(), err) require.Error(s.T(), err)
} }
@@ -217,7 +212,7 @@ func (s *RcSuite) TestRc_ScriptOutputForwarded() {
script := filepath.Join(homesickD, "10_output.sh") script := filepath.Join(homesickD, "10_output.sh")
require.NoError(s.T(), os.WriteFile(script, []byte("#!/bin/sh\necho hello\necho world >&2\n"), 0o755)) require.NoError(s.T(), os.WriteFile(script, []byte("#!/bin/sh\necho hello\necho world >&2\n"), 0o755))
require.NoError(s.T(), s.app.Rc("dotfiles")) require.NoError(s.T(), s.app.Rc("dotfiles", false))
require.Contains(s.T(), s.stdout.String(), "hello") require.Contains(s.T(), s.stdout.String(), "hello")
require.Contains(s.T(), s.stderr.String(), "world") require.Contains(s.T(), s.stderr.String(), "world")
} }
@@ -232,6 +227,6 @@ func (s *RcSuite) TestRc_ScriptsRunWithCwdSetToCastleRoot() {
script := filepath.Join(homesickD, "10_pwd.sh") script := filepath.Join(homesickD, "10_pwd.sh")
require.NoError(s.T(), os.WriteFile(script, []byte("#!/bin/sh\npwd\n"), 0o755)) require.NoError(s.T(), os.WriteFile(script, []byte("#!/bin/sh\npwd\n"), 0o755))
require.NoError(s.T(), s.app.Rc("dotfiles")) require.NoError(s.T(), s.app.Rc("dotfiles", false))
require.Contains(s.T(), s.stdout.String(), castleRoot) require.Contains(s.T(), s.stdout.String(), castleRoot)
} }