cli/pkg/build/discovery.go
Snider 71115d87bf feat(build): migrate filesystem operations to io.Local abstraction
Migrate config.go:
- os.ReadFile → io.Local.Read (with filepath.Abs for relative paths)

Migrate checksum.go:
- os.MkdirAll → io.Local.EnsureDir
- os.WriteFile → io.Local.Write

Migrate discovery.go:
- os.Stat → io.Local.IsFile (with filepath.Abs for relative paths)

Note: os.Open for file hashing remains unchanged as it requires io.Reader.

Part of #101 (io.Medium migration tracking issue).

Closes #105

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 04:52:14 +00:00

93 lines
2.6 KiB
Go

package build
import (
"path/filepath"
"slices"
"github.com/host-uk/core/pkg/io"
)
// Marker files for project type detection.
const (
markerGoMod = "go.mod"
markerWails = "wails.json"
markerNodePackage = "package.json"
markerComposer = "composer.json"
)
// projectMarker maps a marker file to its project type.
type projectMarker struct {
file string
projectType ProjectType
}
// markers defines the detection order. More specific types come first.
// Wails projects have both wails.json and go.mod, so wails is checked first.
var markers = []projectMarker{
{markerWails, ProjectTypeWails},
{markerGoMod, ProjectTypeGo},
{markerNodePackage, ProjectTypeNode},
{markerComposer, ProjectTypePHP},
}
// Discover detects project types in the given directory by checking for marker files.
// Returns a slice of detected project types, ordered by priority (most specific first).
// For example, a Wails project returns [wails, go] since it has both wails.json and go.mod.
func Discover(dir string) ([]ProjectType, error) {
var detected []ProjectType
for _, m := range markers {
path := filepath.Join(dir, m.file)
if fileExists(path) {
// Avoid duplicates (shouldn't happen with current markers, but defensive)
if !slices.Contains(detected, m.projectType) {
detected = append(detected, m.projectType)
}
}
}
return detected, nil
}
// PrimaryType returns the most specific project type detected in the directory.
// Returns empty string if no project type is detected.
func PrimaryType(dir string) (ProjectType, error) {
types, err := Discover(dir)
if err != nil {
return "", err
}
if len(types) == 0 {
return "", nil
}
return types[0], nil
}
// IsGoProject checks if the directory contains a Go project (go.mod or wails.json).
func IsGoProject(dir string) bool {
return fileExists(filepath.Join(dir, markerGoMod)) ||
fileExists(filepath.Join(dir, markerWails))
}
// IsWailsProject checks if the directory contains a Wails project.
func IsWailsProject(dir string) bool {
return fileExists(filepath.Join(dir, markerWails))
}
// IsNodeProject checks if the directory contains a Node.js project.
func IsNodeProject(dir string) bool {
return fileExists(filepath.Join(dir, markerNodePackage))
}
// IsPHPProject checks if the directory contains a PHP project.
func IsPHPProject(dir string) bool {
return fileExists(filepath.Join(dir, markerComposer))
}
// fileExists checks if a file exists and is not a directory.
func fileExists(path string) bool {
absPath, err := filepath.Abs(path)
if err != nil {
return false
}
return io.Local.IsFile(absPath)
}