Files
2026-06-23 05:02:15 +08:00

64 lines
1.6 KiB
Go

package files
import (
"io/fs"
"os"
"path/filepath"
"strings"
)
type EnvLockResult struct {
Total int
OK []string
Failed []struct{ Path, Reason string }
}
// FindEnvFiles walks workspaceRoot recursively and returns all .env* files,
// skipping node_modules, .git, and .claude directories.
func FindEnvFiles(workspaceRoot string) ([]string, error) {
var found []string
err := filepath.WalkDir(workspaceRoot, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
name := d.Name()
if name == "node_modules" || name == ".git" || name == ".claude" {
return filepath.SkipDir
}
return nil
}
if strings.HasPrefix(d.Name(), ".env") {
found = append(found, path)
}
return nil
})
return found, err
}
// LockEnvFiles sets all .env* files under workspaceRoot to read-only (0444).
func LockEnvFiles(workspaceRoot string) (EnvLockResult, error) {
return chmodEnvFiles(workspaceRoot, 0o444)
}
// UnlockEnvFiles sets all .env* files under workspaceRoot to read-write (0644).
func UnlockEnvFiles(workspaceRoot string) (EnvLockResult, error) {
return chmodEnvFiles(workspaceRoot, 0o644)
}
func chmodEnvFiles(workspaceRoot string, mode os.FileMode) (EnvLockResult, error) {
paths, err := FindEnvFiles(workspaceRoot)
if err != nil {
return EnvLockResult{}, err
}
result := EnvLockResult{Total: len(paths)}
for _, p := range paths {
if cErr := os.Chmod(p, mode); cErr != nil {
result.Failed = append(result.Failed, struct{ Path, Reason string }{Path: p, Reason: cErr.Error()})
} else {
result.OK = append(result.OK, p)
}
}
return result, nil
}