返回 DeepSeek-Reasonix
workspaceid_test.go
根目录 / internal / workspaceid / workspaceid_test.go
1 package workspaceid
2
3 import (
4 "os"
5 "path/filepath"
6 "strings"
7 "testing"
8 )
9
10 func sharesRepo(a, b string) bool {
11 repo := RepoDir(a)
12 return repo != "" && repo == RepoDir(b)
13 }
14
15 func TestKeyPathWhenNotARepository(t *testing.T) {
16 dir := t.TempDir()
17 key := Key(dir)
18 if !strings.HasPrefix(key, PathPrefix) {
19 t.Fatalf("Key(%q) = %q, want a %s key", dir, key, PathPrefix)
20 }
21 if RepoDir(dir) != "" {
22 t.Fatalf("RepoDir(%q) = %q, want empty", dir, RepoDir(dir))
23 }
24 }
25
26 func TestKeyRepoForRootAndSubdirectory(t *testing.T) {
27 repo := t.TempDir()
28 mkdir(t, filepath.Join(repo, ".git"))
29 sub := filepath.Join(repo, "internal", "agent")
30 mkdir(t, sub)
31
32 rootKey := Key(repo)
33 if !strings.HasPrefix(rootKey, RepoPrefix) {
34 t.Fatalf("Key(repo) = %q, want a %s key", rootKey, RepoPrefix)
35 }
36 if got := Key(sub); got != rootKey {
37 t.Fatalf("Key(subdir) = %q, want the repository key %q", got, rootKey)
38 }
39 }
40
41 // A linked worktree must land on the same key as the tree it was cut from, or
42 // a switch flipped in the main tree would silently not apply in the worktree.
43 func TestKeyLinkedWorktreeSharesTheRepositoryKey(t *testing.T) {
44 base := t.TempDir()
45 repo := filepath.Join(base, "repo")
46 gitDir := filepath.Join(repo, ".git")
47 mkdir(t, gitDir)
48 mkdir(t, filepath.Join(gitDir, "worktrees", "studio"))
49
50 tree := filepath.Join(base, "trees", "studio")
51 mkdir(t, tree)
52 writeFile(t, filepath.Join(tree, ".git"),
53 "gitdir: "+filepath.Join(gitDir, "worktrees", "studio")+"\n")
54
55 if got, want := Key(tree), Key(repo); got != want {
56 t.Fatalf("worktree key = %q, main tree key = %q, want equal", got, want)
57 }
58 if !sharesRepo(tree, repo) {
59 t.Fatal("sharesRepo(worktree, repo) = false, want true")
60 }
61 }
62
63 func TestKeyRelativeGitdirPointer(t *testing.T) {
64 base := t.TempDir()
65 repo := filepath.Join(base, "repo")
66 mkdir(t, filepath.Join(repo, ".git", "worktrees", "wt"))
67 tree := filepath.Join(base, "wt")
68 mkdir(t, tree)
69 writeFile(t, filepath.Join(tree, ".git"), "gitdir: ../repo/.git/worktrees/wt\n")
70
71 if got, want := Key(tree), Key(repo); got != want {
72 t.Fatalf("relative-pointer worktree key = %q, want %q", got, want)
73 }
74 }
75
76 // A submodule is its own repository: its gitdir has no worktrees element, so it
77 // must not converge onto the superproject's key.
78 func TestKeySubmoduleStaysItsOwnRepository(t *testing.T) {
79 base := t.TempDir()
80 super := filepath.Join(base, "super")
81 mkdir(t, filepath.Join(super, ".git", "modules", "vendor"))
82 sub := filepath.Join(super, "vendor")
83 mkdir(t, sub)
84 writeFile(t, filepath.Join(sub, ".git"), "gitdir: ../.git/modules/vendor\n")
85
86 if Key(sub) == Key(super) {
87 t.Fatalf("submodule shares the superproject key %q", Key(sub))
88 }
89 if !strings.HasPrefix(Key(sub), RepoPrefix) {
90 t.Fatalf("Key(submodule) = %q, want a %s key", Key(sub), RepoPrefix)
91 }
92 }
93
94 // Two plain folders are two projects. Walking up for a repository must not
95 // collapse them onto the drive the walk ended on.
96 func TestKeyDistinctPerFolderOutsideRepositories(t *testing.T) {
97 a, b := t.TempDir(), t.TempDir()
98 if Key(a) == Key(b) {
99 t.Fatalf("two plain folders share key %q", Key(a))
100 }
101 if Key(a) != Key(a+string(filepath.Separator)) {
102 t.Fatal("Key is not stable across spellings of one folder")
103 }
104 }
105
106 func TestKeyEmptyRoot(t *testing.T) {
107 if got := Key(" "); got != "" {
108 t.Fatalf("Key(blank) = %q, want empty", got)
109 }
110 }
111
112 func TestSharesRepoIsFalseOutsideRepositories(t *testing.T) {
113 a, b := t.TempDir(), t.TempDir()
114 if sharesRepo(a, b) {
115 t.Fatal("SharesRepo on two plain folders = true, want false")
116 }
117 }
118
119 func mkdir(t *testing.T, path string) {
120 t.Helper()
121 if err := os.MkdirAll(path, 0o700); err != nil {
122 t.Fatalf("mkdir %s: %v", path, err)
123 }
124 }
125
126 func writeFile(t *testing.T, path, body string) {
127 t.Helper()
128 if err := os.WriteFile(path, []byte(body), 0o600); err != nil {
129 t.Fatalf("write %s: %v", path, err)
130 }
131 }
132
132 lines GO