93 lines
2.1 KiB
Go
93 lines
2.1 KiB
Go
package projects
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"codex-agent-manager/internal/codexhome"
|
|
)
|
|
|
|
type Store struct {
|
|
CodexHome string
|
|
}
|
|
|
|
func (s Store) List() ([]Project, error) {
|
|
configPath, err := codexhome.ResolveInside(s.CodexHome, "config.toml")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
data, err := os.ReadFile(configPath)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return []Project{}, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
projects := parseProjectsConfig(string(data), configPath)
|
|
sort.Slice(projects, func(i, j int) bool {
|
|
return projects[i].Path < projects[j].Path
|
|
})
|
|
for i := range projects {
|
|
if projects[i].DisplayName == "" {
|
|
projects[i].DisplayName = filepath.Base(projects[i].Path)
|
|
}
|
|
if info, err := os.Stat(projects[i].Path); err == nil && info.IsDir() {
|
|
projects[i].DirectoryExists = true
|
|
}
|
|
}
|
|
return projects, nil
|
|
}
|
|
|
|
func parseProjectsConfig(input string, sourcePath string) []Project {
|
|
var result []Project
|
|
var current *Project
|
|
scanner := bufio.NewScanner(strings.NewReader(input))
|
|
for scanner.Scan() {
|
|
line := strings.TrimSpace(scanner.Text())
|
|
if line == "" || strings.HasPrefix(line, "#") {
|
|
continue
|
|
}
|
|
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
|
|
current = nil
|
|
section := strings.TrimSuffix(strings.TrimPrefix(line, "["), "]")
|
|
if !strings.HasPrefix(section, "projects.") {
|
|
continue
|
|
}
|
|
path, err := strconv.Unquote(strings.TrimPrefix(section, "projects."))
|
|
if err != nil || path == "" {
|
|
continue
|
|
}
|
|
result = append(result, Project{
|
|
Path: path,
|
|
Source: SourceEvidence{Kind: "config_toml", Path: sourcePath, Confidence: "high"},
|
|
TrustLevel: "unknown",
|
|
})
|
|
current = &result[len(result)-1]
|
|
continue
|
|
}
|
|
if current == nil {
|
|
continue
|
|
}
|
|
key, raw, ok := strings.Cut(line, "=")
|
|
if !ok {
|
|
continue
|
|
}
|
|
value, err := strconv.Unquote(strings.TrimSpace(raw))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
switch strings.TrimSpace(key) {
|
|
case "trust_level":
|
|
current.TrustLevel = value
|
|
case "display_name":
|
|
current.DisplayName = value
|
|
}
|
|
}
|
|
return result
|
|
}
|