From ac780231a8e6a06a77cc80e8f9a84419b945b439 Mon Sep 17 00:00:00 2001 From: sid Date: Mon, 23 Mar 2026 12:50:49 -0600 Subject: [PATCH] feat: support ~ (tilde) expansion in match_dirs paths --- internal/config/config.go | 14 +++++++++ internal/config/config_test.go | 52 ++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/internal/config/config.go b/internal/config/config.go index bc42159..8fec3fa 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -151,6 +151,8 @@ func (c *Config) ResolveHostByPath(cwd string) string { if dir == "" { continue } + // Expand ~ to home directory + dir = expandHome(dir) // Resolve symlinks in the configured dir as well if resolved, err := filepath.EvalSymlinks(dir); err == nil { dir = resolved @@ -173,6 +175,18 @@ func (c *Config) ResolveHostByPath(cwd string) string { return bestHost } +// expandHome replaces a leading ~ with the user's home directory. +func expandHome(path string) string { + if path == "~" || strings.HasPrefix(path, "~/") { + home, err := os.UserHomeDir() + if err != nil { + return path + } + return filepath.Join(home, path[1:]) + } + return path +} + func (c *Config) SetHost(hostname string, host HostConfig) { if c.Hosts == nil { c.Hosts = make(map[string]HostConfig) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 95282f2..af2d79e 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -539,3 +539,55 @@ func TestGetHost_MatchDirsIntegration(t *testing.T) { t.Errorf("expected codeberg.org, got %s", host.Hostname) } } + +func TestResolveHostByPath_TildeExpansion(t *testing.T) { + home, err := os.UserHomeDir() + if err != nil { + t.Skip("cannot determine home directory") + } + + cfg := &Config{ + Hosts: map[string]HostConfig{ + "tilde.org": { + Hostname: "tilde.org", + Token: "t1", + MatchDirs: []string{"~/repos"}, + }, + }, + } + + got := cfg.ResolveHostByPath(filepath.Join(home, "repos", "myproject")) + if got != "tilde.org" { + t.Errorf("expected tilde.org, got %q", got) + } + + got = cfg.ResolveHostByPath(filepath.Join(home, "other")) + if got != "" { + t.Errorf("expected empty, got %q", got) + } +} + +func TestExpandHome(t *testing.T) { + home, err := os.UserHomeDir() + if err != nil { + t.Skip("cannot determine home directory") + } + + tests := []struct { + input string + want string + }{ + {"~/repos", filepath.Join(home, "repos")}, + {"~", home}, + {"/absolute/path", "/absolute/path"}, + {"relative/path", "relative/path"}, + {"~other", "~other"}, // only ~/... is expanded, not ~user + } + + for _, tt := range tests { + got := expandHome(tt.input) + if got != tt.want { + t.Errorf("expandHome(%q) = %q, want %q", tt.input, got, tt.want) + } + } +}