Skip to content

Commit a6504ce

Browse files
committed
fix: dedupe socket aliases to stop duplicate panes
1 parent f4eed91 commit a6504ce

3 files changed

Lines changed: 77 additions & 3 deletions

File tree

docs/changelog/260305.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Changelog - 260305
2+
3+
## 260305-01:36:39 - Prevent duplicate pane rendering from socket alias paths
4+
5+
### Summary
6+
Canonicalized socket identity so the same tmux server is not discovered twice via symlinked path aliases.
7+
8+
### Changed
9+
- Added symlink-aware socket path canonicalization for socket identity keys.
10+
- Updated socket discovery dedupe to compare canonical path keys instead of raw path strings.
11+
- Added regression test covering two alias paths pointing to the same socket file.
12+
13+
### Fixed
14+
- Fixed duplicate pane/session rendering when both `/tmp/...sock` and `/private/tmp/...sock` resolve to the same socket.
15+
16+
### Files
17+
- `src/sockets.go`
18+
- `src/socket_test.go`
19+
20+
### QA Notes
21+
- Verify panes are shown once when Lisa socket exists under both `/tmp` and `/private/tmp`.
22+
- Verify socket discovery still includes distinct sockets.
23+
- Verify regression suite passes: `go test ./src/...`.

src/socket_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,37 @@ func TestLisaSocketGlobsCustomOverridesFallbacks(t *testing.T) {
506506
}
507507
}
508508

509+
func TestDiscoverSocketTargetsDedupesSymlinkedSocketAliases(t *testing.T) {
510+
t.Setenv("TMUX", "")
511+
stubLisaSockets(t, []string{}, nil)
512+
513+
realDir := t.TempDir()
514+
linkDir := filepath.Join(t.TempDir(), "alias")
515+
if err := os.Symlink(realDir, linkDir); err != nil {
516+
t.Skipf("symlink unsupported: %v", err)
517+
}
518+
519+
socketName := "same.sock"
520+
realSocket := filepath.Join(realDir, socketName)
521+
aliasSocket := filepath.Join(linkDir, socketName)
522+
if err := os.WriteFile(realSocket, []byte("x"), 0o600); err != nil {
523+
t.Fatalf("write real socket: %v", err)
524+
}
525+
526+
cfg := config{
527+
includeDefaultSocket: false,
528+
includeLisaSockets: false,
529+
explicitSockets: []string{realSocket, aliasSocket},
530+
}
531+
targets, discoveryErrors := discoverSocketTargets(cfg)
532+
if len(discoveryErrors) != 0 {
533+
t.Fatalf("unexpected discoveryErrors: %v", discoveryErrors)
534+
}
535+
if len(targets) != 1 {
536+
t.Fatalf("targets len = %d, targets=%v", len(targets), targets)
537+
}
538+
}
539+
509540
func containsString(items []string, needle string) bool {
510541
for _, item := range items {
511542
if item == needle {

src/sockets.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,35 @@ func dedupePaths(paths []string) []string {
179179
if clean == "" || clean == "." {
180180
continue
181181
}
182-
if _, ok := seen[clean]; ok {
182+
key := canonicalSocketPathKey(clean)
183+
if key == "" {
184+
key = clean
185+
}
186+
if _, ok := seen[key]; ok {
183187
continue
184188
}
185-
seen[clean] = struct{}{}
189+
seen[key] = struct{}{}
186190
out = append(out, clean)
187191
}
188192
return out
189193
}
190194

195+
func canonicalSocketPathKey(path string) string {
196+
clean := filepath.Clean(strings.TrimSpace(path))
197+
if clean == "" || clean == "." {
198+
return ""
199+
}
200+
resolved, err := filepath.EvalSymlinks(clean)
201+
if err != nil {
202+
return clean
203+
}
204+
resolved = filepath.Clean(strings.TrimSpace(resolved))
205+
if resolved == "" || resolved == "." {
206+
return clean
207+
}
208+
return resolved
209+
}
210+
191211
func listLisaSocketPathsFromProcessTable() ([]string, error) {
192212
commands, err := listProcessCommandsFn()
193213
if err != nil {
@@ -415,7 +435,7 @@ func socketKey(path string) string {
415435
if strings.TrimSpace(path) == "" {
416436
return defaultSocketKey
417437
}
418-
return filepath.Clean(path)
438+
return canonicalSocketPathKey(path)
419439
}
420440

421441
func socketHint(path string) string {

0 commit comments

Comments
 (0)