forked from a8m/envsubst
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnode.go
More file actions
executable file
·107 lines (91 loc) · 2.07 KB
/
Copy pathnode.go
File metadata and controls
executable file
·107 lines (91 loc) · 2.07 KB
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package main
import (
"fmt"
)
type Node interface {
Type() NodeType
String() (string, error)
}
// NodeType identifies the type of a node.
type NodeType int
// Type returns itself and provides an easy default implementation
// for embedding in a Node. Embedded in all non-trivial Nodes.
func (t NodeType) Type() NodeType {
return t
}
const (
NodeText NodeType = iota
NodeSubstitution
NodeVariable
)
type TextNode struct {
NodeType
Text string
}
func NewText(text string) *TextNode {
return &TextNode{NodeText, text}
}
func (t *TextNode) String() (string, error) {
return t.Text, nil
}
type VariableNode struct {
NodeType
Ident string
Env Env
Restrict *Restrictions
}
func NewVariable(ident string, env Env, restrict *Restrictions) *VariableNode {
return &VariableNode{NodeVariable, ident, env, restrict}
}
func (t *VariableNode) String() (string, error) {
if err := t.validateNoUnset(); err != nil {
return "", err
}
value := t.Env.Get(t.Ident)
if err := t.validateNoEmpty(value); err != nil {
return "", err
}
return value, nil
}
func (t *VariableNode) isSet() bool {
return t.Env.Has(t.Ident)
}
func (t *VariableNode) validateNoUnset() error {
if t.Restrict.NoUnset && !t.isSet() {
return fmt.Errorf("variable ${%s} not set", t.Ident)
}
return nil
}
func (t *VariableNode) validateNoEmpty(value string) error {
if t.Restrict.NoEmpty && value == "" && t.isSet() {
return fmt.Errorf("variable ${%s} set but empty", t.Ident)
}
return nil
}
type SubstitutionNode struct {
NodeType
ExpType itemType
Variable *VariableNode
Default Node // Default could be variable or text
}
func (t *SubstitutionNode) String() (string, error) {
if t.ExpType >= itemPlus && t.Default != nil {
switch t.ExpType {
case itemColonDash, itemColonEquals:
if s, _ := t.Variable.String(); s != "" {
return s, nil
}
return t.Default.String()
case itemPlus, itemColonPlus:
if t.Variable.isSet() {
return t.Default.String()
}
return "", nil
default:
if !t.Variable.isSet() {
return t.Default.String()
}
}
}
return t.Variable.String()
}