cuelang.org/go@v0.10.1/pkg/tool/os/env.go (about) 1 // Copyright 2019 CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package os 16 17 import ( 18 "os" 19 "strings" 20 21 "cuelang.org/go/cue" 22 "cuelang.org/go/cue/ast" 23 "cuelang.org/go/cue/errors" 24 "cuelang.org/go/internal/cli" 25 "cuelang.org/go/internal/task" 26 ) 27 28 func init() { 29 task.Register("tool/os.Getenv", newGetenvCmd) 30 task.Register("tool/os.Environ", newEnvironCmd) 31 32 // TODO: 33 // Tasks: 34 // - Exit? 35 // - Getwd/ Setwd (or in tool/file?) 36 37 // Functions: 38 // - Hostname 39 // - UserCache/Home/Config (or in os/user?) 40 } 41 42 type getenvCmd struct{} 43 44 func newGetenvCmd(v cue.Value) (task.Runner, error) { 45 return &getenvCmd{}, nil 46 } 47 48 func (c *getenvCmd) Run(ctx *task.Context) (res interface{}, err error) { 49 iter, err := ctx.Obj.Fields() 50 if err != nil { 51 return nil, err 52 } 53 54 update := map[string]interface{}{} 55 56 for iter.Next() { 57 name := iter.Label() 58 if strings.HasPrefix(name, "$") { 59 continue 60 } 61 v := iter.Value() 62 63 if err := v.Err(); err != nil { 64 return nil, err 65 } 66 67 if err := validateEntry(name, v); err != nil { 68 return nil, err 69 } 70 71 str, ok := os.LookupEnv(name) 72 if !ok { 73 update[name] = nil 74 continue 75 } 76 x, err := fromString(name, str, v) 77 if err != nil { 78 return nil, err 79 } 80 update[name] = x 81 } 82 83 return update, nil 84 } 85 86 type environCmd struct{} 87 88 func newEnvironCmd(v cue.Value) (task.Runner, error) { 89 return &environCmd{}, nil 90 } 91 92 func (c *environCmd) Run(ctx *task.Context) (res interface{}, err error) { 93 iter, err := ctx.Obj.Fields() 94 if err != nil { 95 return nil, err 96 } 97 98 update := map[string]interface{}{} 99 100 for _, kv := range os.Environ() { 101 name, str, _ := strings.Cut(kv, "=") 102 if v := ctx.Obj.LookupPath(cue.MakePath(cue.Str(name))); v.Exists() { 103 update[name], err = fromString(name, str, v) 104 if err != nil { 105 return nil, err 106 } 107 } else { 108 update[name] = str 109 } 110 } 111 112 for iter.Next() { 113 name := iter.Label() 114 if strings.HasPrefix(name, "$") { 115 continue 116 } 117 v := iter.Value() 118 if err := v.Err(); err != nil { 119 return nil, err 120 } 121 if err := validateEntry(name, v); err != nil { 122 return nil, err 123 } 124 if _, ok := update[name]; !ok { 125 update[name] = nil 126 } 127 } 128 129 return update, nil 130 } 131 132 func validateEntry(name string, v cue.Value) error { 133 if k := v.IncompleteKind(); k&^(cue.NumberKind|cue.NullKind|cue.BoolKind|cue.StringKind) != 0 { 134 return errors.Newf(v.Pos(), 135 "invalid type %s for environment variable %s", k, name) 136 } 137 return nil 138 } 139 140 func fromString(name, str string, v cue.Value) (x ast.Node, err error) { 141 k := v.IncompleteKind() 142 return cli.ParseValue(v.Pos(), name, str, k) 143 }