diff --git a/internal/daemon/hooks.go b/internal/daemon/hooks.go index e3004f4..fce5aea 100644 --- a/internal/daemon/hooks.go +++ b/internal/daemon/hooks.go @@ -170,8 +170,8 @@ func interpolate(cmd string, event Event) string { } // shellEscape quotes a value for safe interpolation into a shell command. -// On Unix, wraps in single quotes with embedded single quotes escaped. -// On Windows, wraps in double quotes with embedded double quotes escaped. +// Wraps in single quotes on all platforms, with embedded single quotes escaped. +// On Windows (PowerShell), '' escapes a literal '. On Unix, uses '"'"'. func shellEscape(s string) string { if runtime.GOOS == "windows" { // PowerShell single-quoted strings: only escape is '' for literal '. diff --git a/internal/daemon/hooks_test.go b/internal/daemon/hooks_test.go index fd0d374..5a67208 100644 --- a/internal/daemon/hooks_test.go +++ b/internal/daemon/hooks_test.go @@ -40,7 +40,7 @@ func touchCmd(path string) string { // pwdCmd returns a platform-appropriate shell command to write the cwd to a file. func pwdCmd(path string) string { if runtime.GOOS == "windows" { - return "(Get-Location).Path | Set-Content -NoNewline '" + filepath.ToSlash(path) + "'" + return "[IO.File]::WriteAllText('" + filepath.ToSlash(path) + "', (Get-Location).Path)" } return "pwd > " + path } @@ -407,7 +407,11 @@ func TestHookRunnerWorkingDirectory(t *testing.T) { want = w } } - if !strings.EqualFold(got, want) { + equal := got == want + if runtime.GOOS == "windows" { + equal = strings.EqualFold(got, want) + } + if !equal { t.Errorf("hook ran in %q, want %q", got, want) } return @@ -674,6 +678,7 @@ func TestHandleEventLogsWhenHooksFired(t *testing.T) { var buf bytes.Buffer prevOut := log.Writer() log.SetOutput(&buf) + t.Cleanup(func() { log.SetOutput(prevOut) }) cfg := &config.Config{ Hooks: []config.HookConfig{ @@ -710,6 +715,7 @@ func TestHandleEventNoLogWhenNoHooksMatch(t *testing.T) { var buf bytes.Buffer prevOut := log.Writer() log.SetOutput(&buf) + t.Cleanup(func() { log.SetOutput(prevOut) }) cfg := &config.Config{ Hooks: []config.HookConfig{