/
include.go
67 lines (59 loc) · 2.15 KB
/
include.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Copyright (c) 2023, Cogent Core. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// note: FindFileOnPaths adapted from viper package https://github.com/spf13/viper
// Copyright (c) 2014 Steve Francia
package cli
import (
"errors"
"reflect"
"cogentcore.org/core/gox/dirs"
"cogentcore.org/core/iox/tomlx"
"cogentcore.org/core/reflectx"
)
// TODO(kai): this seems bad
// Includer is an interface that facilitates processing
// include files in configuration objects. It typically
// should not be used by end-user code.
type Includer interface {
// IncludesPtr returns a pointer to the "Includes []string"
// field containing file(s) to include before processing
// the current config file.
IncludesPtr() *[]string
}
// IncludeStack returns the stack of include files in the natural
// order in which they are encountered (nil if none).
// Files should then be read in reverse order of the slice.
// Returns an error if any of the include files cannot be found on IncludePath.
// Does not alter cfg. It typically should not be used by end-user code.
func IncludeStack(opts *Options, cfg Includer) ([]string, error) {
clone := reflect.New(reflectx.NonPointerType(reflect.TypeOf(cfg))).Interface().(Includer)
*clone.IncludesPtr() = *cfg.IncludesPtr()
return includeStackImpl(opts, clone, nil)
}
// includeStackImpl implements IncludeStack, operating on cloned cfg
// todo: could use a more efficient method to just extract the include field..
func includeStackImpl(opts *Options, clone Includer, includes []string) ([]string, error) {
incs := *clone.IncludesPtr()
ni := len(incs)
if ni == 0 {
return includes, nil
}
for i := ni - 1; i >= 0; i-- {
includes = append(includes, incs[i]) // reverse order so later overwrite earlier
}
var errs []error
for _, inc := range incs {
*clone.IncludesPtr() = nil
err := tomlx.OpenFiles(clone, dirs.FindFilesOnPaths(opts.IncludePaths, inc))
if err == nil {
includes, err = includeStackImpl(opts, clone, includes)
if err != nil {
errs = append(errs, err)
}
} else {
errs = append(errs, err)
}
}
return includes, errors.Join(errs...)
}