6aec0413bb
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
62 lines
1.9 KiB
Go
62 lines
1.9 KiB
Go
package infra
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// ResolveRegistryRoot returns the absolute path of the fn_registry root
|
|
// (the directory that contains registry.db), or an error if not found.
|
|
//
|
|
// Resolution order:
|
|
// 1. FN_REGISTRY_ROOT env var — if set and <dir>/registry.db exists, return it.
|
|
// 2. Walk up from the executable's directory — up to 6 levels; first dir
|
|
// that contains registry.db wins. Covers binaries at <root>/fn and at
|
|
// <root>/apps/<x>/<bin>.
|
|
// 3. $HOME/fn_registry — if <$HOME>/fn_registry/registry.db exists.
|
|
// 4. Error — no method found a valid registry root.
|
|
func ResolveRegistryRoot() (string, error) {
|
|
// 1. Env var
|
|
if envDir := os.Getenv("FN_REGISTRY_ROOT"); envDir != "" {
|
|
if nonEmptyFile(filepath.Join(envDir, "registry.db")) {
|
|
return filepath.Clean(envDir), nil
|
|
}
|
|
}
|
|
|
|
// 2. Walk up from executable
|
|
if exe, err := os.Executable(); err == nil {
|
|
dir := filepath.Dir(exe)
|
|
for i := 0; i < 6; i++ {
|
|
if nonEmptyFile(filepath.Join(dir, "registry.db")) {
|
|
return dir, nil
|
|
}
|
|
parent := filepath.Dir(dir)
|
|
if parent == dir {
|
|
// Reached filesystem root
|
|
break
|
|
}
|
|
dir = parent
|
|
}
|
|
}
|
|
|
|
// 3. $HOME/fn_registry
|
|
if home, err := os.UserHomeDir(); err == nil {
|
|
candidate := filepath.Join(home, "fn_registry")
|
|
if nonEmptyFile(filepath.Join(candidate, "registry.db")) {
|
|
return candidate, nil
|
|
}
|
|
}
|
|
|
|
return "", fmt.Errorf("resolve_registry_root: no se encontro registry.db (set FN_REGISTRY_ROOT)")
|
|
}
|
|
|
|
// nonEmptyFile reports whether path is an existing, non-empty regular file.
|
|
// A zero-byte registry.db — which sql.Open silently creates when handed a
|
|
// mis-resolved path — must NOT count as a valid registry root, otherwise such
|
|
// a shadow file would hijack the walk-up and mask the real database.
|
|
func nonEmptyFile(path string) bool {
|
|
fi, err := os.Stat(path)
|
|
return err == nil && fi.Mode().IsRegular() && fi.Size() > 0
|
|
}
|