返回 DeepSeek-Reasonix
path_identity.go
根目录 / internal / sessioncatalog / path_identity.go
1 package sessioncatalog
2
3 import (
4 "os"
5 "path/filepath"
6 "strings"
7
8 "reasonix/internal/pathidentity"
9 )
10
11 // PathIdentityKey returns the stable comparison key for a catalog path while
12 // leaving the caller's access spelling untouched. Parent aliases are resolved,
13 // and case is folded only when the governing filesystem directory reports
14 // case-insensitive lookup.
15 func PathIdentityKey(path string) string {
16 path = cleanCatalogAccessPath(path)
17 if path == "" {
18 return ""
19 }
20 baseDir := ""
21 if !filepath.IsAbs(path) {
22 var err error
23 baseDir, err = os.Getwd()
24 if err != nil {
25 return ""
26 }
27 }
28 identity, err := pathidentity.Resolve(path, pathidentity.Options{BaseDir: baseDir, FollowLeaf: true})
29 if err != nil {
30 return ""
31 }
32 return identity.Key
33 }
34
35 func cleanCatalogAccessPath(path string) string {
36 path = strings.TrimSpace(path)
37 if path == "" {
38 return ""
39 }
40 path = filepath.Clean(path)
41 if path == "." {
42 return ""
43 }
44 return path
45 }
46
47 // UniqueDirectoryTargets keeps the first usable access spelling for each
48 // physical directory identity. Rebuild and every caller use the same boundary,
49 // so a missed Desktop or CLI call site cannot reintroduce duplicate scans.
50 func UniqueDirectoryTargets(targets []DirectoryTarget) []DirectoryTarget {
51 return uniqueDirectoryTargetsBy(targets, PathIdentityKey)
52 }
53
54 func uniqueDirectoryTargetsBy(targets []DirectoryTarget, identity func(string) string) []DirectoryTarget {
55 seen := make(map[string]struct{}, len(targets))
56 out := make([]DirectoryTarget, 0, len(targets))
57 for _, target := range targets {
58 target.Path = cleanCatalogAccessPath(target.Path)
59 if target.Path == "" {
60 continue
61 }
62 key := identity(target.Path)
63 if key == "" {
64 continue
65 }
66 if _, ok := seen[key]; ok {
67 continue
68 }
69 seen[key] = struct{}{}
70 out = append(out, target)
71 }
72 return out
73 }
74
74 lines GO