aboutsummaryrefslogtreecommitdiff
path: root/internal/config/load.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-16 01:34:45 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-16 01:34:45 +0200
commitecfaeabf2a92e26c6a521d5fac404a0fff6263b6 (patch)
tree4147dd6809a45fe5b773447352354dbee2295900 /internal/config/load.go
parentbe4b1275c76b9cad984dfafaa8023db94eb3eecf (diff)
downloadkrino-ecfaeabf2a92e26c6a521d5fac404a0fff6263b6.tar.gz
krino-ecfaeabf2a92e26c6a521d5fac404a0fff6263b6.zip
milestone 1 review: claims span the run, explain's chain is opt-in and its own, overrides keyed by clean path, splice and enum guards
Diffstat (limited to 'internal/config/load.go')
-rw-r--r--internal/config/load.go45
1 files changed, 39 insertions, 6 deletions
diff --git a/internal/config/load.go b/internal/config/load.go
index 3811802..14ce635 100644
--- a/internal/config/load.go
+++ b/internal/config/load.go
@@ -8,6 +8,7 @@ import (
"io/fs"
"os"
"path/filepath"
+ "sort"
"krino/internal/sexp"
"krino/internal/xdg"
@@ -20,15 +21,45 @@ type Config struct {
Dirs []*Dir
}
+// unusedOverrides reports every override LoadWith never read: text meant
+// for a file this load does not touch, which would otherwise pass as
+// checked while the file on disk was read instead (plan 13 review F4).
+func unusedOverrides(over map[string][]byte, used map[string]bool, mainFile string) []*Diag {
+ var out []*Diag
+ for file := range over {
+ if !used[file] {
+ out = append(out, &Diag{File: mainFile, Msg: fmt.Sprintf("unsaved text for %s, which this configuration does not read", file)})
+ }
+ }
+ sort.Slice(out, func(i, j int) bool { return out[i].Msg < out[j].Msg })
+ return out
+}
+
// readSource is the text of file: the caller's override when it has one,
-// else the file's own bytes.
-func readSource(overrides map[string][]byte, file string) ([]byte, error) {
- if src, ok := overrides[file]; ok {
+// else the file's own bytes. It records which overrides were used, so
+// LoadWith can report one it never reached.
+func readSource(overrides map[string][]byte, used map[string]bool, file string) ([]byte, error) {
+ key := filepath.Clean(file)
+ if src, ok := overrides[key]; ok {
+ used[key] = true
return src, nil
}
return os.ReadFile(file)
}
+// cleanOverrides keys the caller's overrides by cleaned path, so a file
+// named with a "." or ".." segment is still recognised as itself.
+func cleanOverrides(overrides map[string][]byte) map[string][]byte {
+ if len(overrides) == 0 {
+ return nil
+ }
+ out := make(map[string][]byte, len(overrides))
+ for file, src := range overrides {
+ out[filepath.Clean(file)] = src
+ }
+ return out
+}
+
// DefaultFile is krino.conf in the XDG config directory.
func DefaultFile() string {
return filepath.Join(xdg.ConfigHome(), "krino", "krino.conf")
@@ -52,7 +83,9 @@ func Load(mainFile string, names ...string) (*Config, []*Diag) {
// checked exactly as a run would read it (GUI design ยง1.3). A nil map is
// Load.
func LoadWith(mainFile string, overrides map[string][]byte, names ...string) (*Config, []*Diag) {
- src, err := readSource(overrides, mainFile)
+ over := cleanOverrides(overrides)
+ used := map[string]bool{}
+ src, err := readSource(over, used, mainFile)
if errors.Is(err, fs.ErrNotExist) {
return nil, []*Diag{{File: mainFile, Msg: "not found; create it with: krino init"}}
}
@@ -80,7 +113,7 @@ func LoadWith(mainFile string, overrides map[string][]byte, names ...string) (*C
}
for _, name := range want {
file := DirFile(mainFile, name)
- src, err := readSource(overrides, file)
+ src, err := readSource(over, used, file)
if err != nil {
msg := err.Error()
if errors.Is(err, fs.ErrNotExist) {
@@ -93,7 +126,7 @@ func LoadWith(mainFile string, overrides map[string][]byte, names ...string) (*C
errs = append(errs, derrs...)
cfg.Dirs = append(cfg.Dirs, dir)
}
- return cfg, errs
+ return cfg, append(errs, unusedOverrides(over, used, mainFile)...)
}
// Resolved is the settings that apply in dir: built-in, then the main