Includes the current working directory changes. Historical commits and release binaries are excluded to limit Gitea storage. Source base: d7515973fbfd6dd2001fa156c483455b8081c7cb
97 lines
2.5 KiB
Go
97 lines
2.5 KiB
Go
//go:build windows
|
||
|
||
package cursor
|
||
|
||
import (
|
||
"os"
|
||
"path/filepath"
|
||
"strings"
|
||
)
|
||
|
||
// maxScanDirs 限制驱动器扫描的目录总数,避免在超大盘上长时间阻塞。
|
||
const maxScanDirs = 8000
|
||
|
||
// skippedRootNames 是驱动器扫描时跳过的系统目录(大且不可能装 Cursor)。
|
||
var skippedRootNames = map[string]struct{}{
|
||
"windows": {},
|
||
"programdata": {},
|
||
"users": {},
|
||
"$recycle.bin": {},
|
||
"system volume information": {},
|
||
"recovery": {},
|
||
"perflogs": {},
|
||
"dumpstack.log.tmp": {},
|
||
"config.msi": {},
|
||
"intel": {},
|
||
"drivers": {},
|
||
"msocache": {},
|
||
}
|
||
|
||
// scanDriveRootsForCursor 兜底扫描各固定驱动器:
|
||
// 根目录与二级目录中查找名称含 cursor 且包含 Cursor.exe 的目录。
|
||
// 纯文件系统探测,不依赖注册表枚举或子进程(部分安全软件会拦截)。
|
||
func scanDriveRootsForCursor() string {
|
||
visited := 0
|
||
for letter := 'C'; letter <= 'Z'; letter++ {
|
||
drive := string(letter) + `:\`
|
||
if _, err := os.Stat(drive); err != nil {
|
||
continue
|
||
}
|
||
if dir := scanDirForCursor(drive, &visited); dir != "" {
|
||
return dir
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// scanDirForCursor 在目录及其一级子目录中查找 Cursor 安装目录。
|
||
func scanDirForCursor(root string, visited *int) string {
|
||
entries, err := os.ReadDir(root)
|
||
if err != nil {
|
||
return ""
|
||
}
|
||
var deferred []string
|
||
for _, entry := range entries {
|
||
if !entry.IsDir() {
|
||
continue
|
||
}
|
||
name := entry.Name()
|
||
if _, skip := skippedRootNames[strings.ToLower(name)]; skip {
|
||
continue
|
||
}
|
||
*visited++
|
||
if *visited > maxScanDirs {
|
||
return ""
|
||
}
|
||
full := filepath.Join(root, name)
|
||
if strings.Contains(strings.ToLower(name), "cursor") {
|
||
if isCursorInstallDir(full) {
|
||
return full
|
||
}
|
||
continue
|
||
}
|
||
deferred = append(deferred, full)
|
||
}
|
||
// 二级目录:仅在一级目录名像程序目录时展开,控制扫描量。
|
||
for _, dir := range deferred {
|
||
if !looksLikeProgramsDir(filepath.Base(dir)) {
|
||
continue
|
||
}
|
||
if dir := scanDirForCursor(dir, visited); dir != "" {
|
||
return dir
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// looksLikeProgramsDir 判断目录名是否像程序/工具安装根目录。
|
||
func looksLikeProgramsDir(name string) bool {
|
||
lower := strings.ToLower(name)
|
||
for _, keyword := range []string{"program", "app", "dev", "soft", "tool", "work", "bin"} {
|
||
if strings.Contains(lower, keyword) {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|