From 8f424c7989947f009748b17e38c9cd677a15ebc1 Mon Sep 17 00:00:00 2001 From: Will Howard Date: Wed, 29 Jul 2026 18:10:57 +0000 Subject: [PATCH 1/2] Resolve relative paths in rm, pause and resume like add does configMatches only compared the needle as a tilde path, a folder name or the stored path, so `gitwatchd rm .` inside a watched repo matched nothing while `add .` had stored the resolved path. Lookup now runs the needle through normalizePath, the same helper add uses; folder-name matching is unchanged. Ports the macOS fix in PR #12 (issue #11) to Linux. Co-Authored-By: Claude Fable 5 --- linux/cli.go | 13 +++++++---- linux/cli_test.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/linux/cli.go b/linux/cli.go index 8b0da31..ef24da3 100644 --- a/linux/cli.go +++ b/linux/cli.go @@ -645,8 +645,12 @@ func configAppend(line string) { os.WriteFile(configPath(), []byte(text), 0o644) } +// True if `spec` is the repo the user means by `nameOrPath`: its folder name, +// or its path in any form add accepts (absolute, tilde, or relative to the +// working directory); the literal comparison also serves hand-edited configs, +// whose stored path need not be one normalizePath would produce. func configMatches(spec *RepoSpec, nameOrPath string) bool { - return spec.Path == expandTilde(nameOrPath) || spec.Name() == nameOrPath || spec.Path == nameOrPath + return spec.Name() == nameOrPath || spec.Path == nameOrPath || spec.Path == normalizePath(nameOrPath) } func configRemove(nameOrPath string) int { @@ -673,10 +677,9 @@ func configRemove(nameOrPath string) int { return removed } -// Flip the --paused token on config lines matching `nameOrPath` (by full -// path or repo name, like remove). Pause lives in the config, not daemon -// state, so it survives daemon and machine restarts. Returns the number -// of lines changed. +// Flip the --paused token on config lines matching `nameOrPath` (as remove +// matches). Pause lives in the config, not daemon state, so it survives +// daemon and machine restarts. Returns the number of lines changed. func configSetPaused(nameOrPath string, paused bool) int { raw, err := os.ReadFile(configPath()) if err != nil { diff --git a/linux/cli_test.go b/linux/cli_test.go index 898ee96..a18c054 100644 --- a/linux/cli_test.go +++ b/linux/cli_test.go @@ -123,6 +123,45 @@ func TestRmMatchesByFullPath(t *testing.T) { } } +func TestRmMatchesTheRepoItRunsIn(t *testing.T) { + withTemporaryConfig(t) + repo := newTestRepo(t) + cliRun([]string{repo.path}) + t.Chdir(repo.path) + if cliRun([]string{"rm", "."}) != 0 { + t.Error("rm . failed") + } + if len(configSpecs()) != 0 { + t.Error("the entry should be gone") + } +} + +func TestRmMatchesARelativePath(t *testing.T) { + withTemporaryConfig(t) + repo := newTestRepo(t) + cliRun([]string{repo.path}) + t.Chdir(filepath.Dir(repo.path)) + if cliRun([]string{"rm", "./" + repo.spec().Name()}) != 0 { + t.Error("rm by relative path failed") + } + if len(configSpecs()) != 0 { + t.Error("the entry should be gone") + } +} + +func TestRmMatchesByNameFromAnUnrelatedDirectory(t *testing.T) { + withTemporaryConfig(t) + repo := newTestRepo(t) + cliRun([]string{repo.path}) + t.Chdir(t.TempDir()) + if cliRun([]string{"rm", repo.spec().Name()}) != 0 { + t.Error("rm by name failed") + } + if len(configSpecs()) != 0 { + t.Error("the entry should be gone") + } +} + func TestRmUnknownFailsAndLeavesConfigAlone(t *testing.T) { withTemporaryConfig(t) repo := newTestRepo(t) @@ -171,6 +210,25 @@ func TestPauseByFullPath(t *testing.T) { } } +func TestPauseAndResumeTakeARelativeTarget(t *testing.T) { + withTemporaryConfig(t) + repo := newTestRepo(t) + cliRun([]string{repo.path}) + t.Chdir(repo.path) + if cliRun([]string{"pause", "."}) != 0 { + t.Fatal("pause . failed") + } + if !configSpecs()[0].Paused { + t.Error("spec should be paused") + } + if cliRun([]string{"resume", "."}) != 0 { + t.Fatal("resume . failed") + } + if configSpecs()[0].Paused { + t.Error("spec should be resumed") + } +} + func TestPausingTwiceFailsPolitely(t *testing.T) { withTemporaryConfig(t) repo := newTestRepo(t) From 0a1d3e9695bf8c2411ed5064172338f823633bc4 Mon Sep 17 00:00:00 2001 From: Will Howard Date: Wed, 29 Jul 2026 18:15:47 +0000 Subject: [PATCH 2/2] Cut the configMatches doc comment Co-Authored-By: Claude Fable 5 --- linux/cli.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/linux/cli.go b/linux/cli.go index ef24da3..32e3791 100644 --- a/linux/cli.go +++ b/linux/cli.go @@ -645,10 +645,6 @@ func configAppend(line string) { os.WriteFile(configPath(), []byte(text), 0o644) } -// True if `spec` is the repo the user means by `nameOrPath`: its folder name, -// or its path in any form add accepts (absolute, tilde, or relative to the -// working directory); the literal comparison also serves hand-edited configs, -// whose stored path need not be one normalizePath would produce. func configMatches(spec *RepoSpec, nameOrPath string) bool { return spec.Name() == nameOrPath || spec.Path == nameOrPath || spec.Path == normalizePath(nameOrPath) }