package main import ( "fmt" "log" "os" "path/filepath" ops "fn-registry/fn_operations" ) // listProjectDirs returns subdirectories under projectsDir. func listProjectDirs(projectsDir string) ([]ProjectInfo, error) { log.Printf("[listProjectDirs] scanning %s", projectsDir) entries, err := os.ReadDir(projectsDir) if err != nil { if os.IsNotExist(err) { log.Printf("[listProjectDirs] dir does not exist, returning nil") return nil, nil } log.Printf("[listProjectDirs] ERROR reading dir: %v", err) return nil, err } log.Printf("[listProjectDirs] found %d entries", len(entries)) var projects []ProjectInfo for _, e := range entries { log.Printf("[listProjectDirs] entry: %s isDir=%v", e.Name(), e.IsDir()) if !e.IsDir() { continue } dbPath := filepath.Join(projectsDir, e.Name(), "operations.db") if _, err := os.Stat(dbPath); err != nil { log.Printf("[listProjectDirs] %s: no operations.db, skipping", e.Name()) continue } info := ProjectInfo{Name: e.Name()} // Quick counts from the DB db, err := ops.Open(dbPath) if err == nil { entities, _ := db.ListEntities("", "") relations, _ := db.ListRelations("") info.EntityCount = len(entities) info.RelCount = len(relations) db.Close() log.Printf("[listProjectDirs] %s: OK (entities=%d relations=%d)", e.Name(), info.EntityCount, info.RelCount) } else { log.Printf("[listProjectDirs] %s: ERROR opening db: %v", e.Name(), err) } projects = append(projects, info) } log.Printf("[listProjectDirs] returning %d projects", len(projects)) return projects, nil } // createProject creates a new project directory with an operations.db. func createProject(projectsDir, name string) error { dir := filepath.Join(projectsDir, name) log.Printf("[createProject] creating dir: %s", dir) if err := os.MkdirAll(dir, 0o755); err != nil { log.Printf("[createProject] ERROR mkdir: %v", err) return fmt.Errorf("creating project directory: %w", err) } dbPath := filepath.Join(dir, "operations.db") log.Printf("[createProject] creating db: %s", dbPath) db, err := ops.Open(dbPath) if err != nil { log.Printf("[createProject] ERROR opening db: %v", err) return fmt.Errorf("creating operations.db: %w", err) } if err := db.Close(); err != nil { log.Printf("[createProject] ERROR closing db: %v", err) return err } // Verify if fi, err := os.Stat(dbPath); err != nil { log.Printf("[createProject] WARNING: db not found after creation: %v", err) } else { log.Printf("[createProject] OK: db created, size=%d bytes", fi.Size()) } return nil } // deleteProject removes a project directory and its operations.db. func deleteProject(projectsDir, name string) error { dir := filepath.Join(projectsDir, name) log.Printf("[deleteProject] removing: %s", dir) return os.RemoveAll(dir) }