github.com/oweisse/u-root@v0.0.0-20181109060735-d005ad25fef1/cmds/elvish/eval/env_list.go (about) 1 package eval 2 3 import ( 4 "errors" 5 "os" 6 "strings" 7 "sync" 8 9 "github.com/u-root/u-root/cmds/elvish/eval/vals" 10 "github.com/u-root/u-root/cmds/elvish/eval/vars" 11 "github.com/u-root/u-root/cmds/elvish/util" 12 "github.com/u-root/u-root/cmds/elvish/vector" 13 ) 14 15 var ( 16 pathListSeparator = string(os.PathListSeparator) 17 forbiddenInPath = pathListSeparator + "\x00" 18 ) 19 20 // Errors 21 var ( 22 ErrCanOnlyAssignList = errors.New("can only assign compatible values") 23 ErrPathMustBeString = errors.New("path must be string") 24 ErrPathCannotContainColonZero = errors.New(`path cannot contain colon or \0`) 25 ) 26 27 // EnvList is a variable whose value is constructed from an environment variable 28 // by splitting at pathListSeparator. Changes to it are also propagated to the 29 // corresponding environment variable. Its elements cannot contain 30 // pathListSeparator or \0; attempting to put any in its elements will result in 31 // an error. 32 type EnvList struct { 33 sync.RWMutex 34 envName string 35 cacheFor string 36 cacheValue interface{} 37 } 38 39 var ( 40 _ vars.Var = (*EnvList)(nil) 41 ) 42 43 // Get returns a Value for an EnvPathList. 44 func (envli *EnvList) Get() interface{} { 45 envli.Lock() 46 defer envli.Unlock() 47 48 value := os.Getenv(envli.envName) 49 if value == envli.cacheFor { 50 return envli.cacheValue 51 } 52 envli.cacheFor = value 53 v := vector.Empty 54 for _, path := range strings.Split(value, pathListSeparator) { 55 v = v.Cons(path) 56 } 57 envli.cacheValue = v 58 return envli.cacheValue 59 } 60 61 // Set sets an EnvPathList. The underlying environment variable is set. 62 func (envli *EnvList) Set(v interface{}) error { 63 var ( 64 paths []string 65 errElement error 66 ) 67 errIterate := vals.Iterate(v, func(v interface{}) bool { 68 s, ok := v.(string) 69 if !ok { 70 errElement = ErrPathMustBeString 71 return false 72 } 73 path := s 74 if strings.ContainsAny(path, forbiddenInPath) { 75 errElement = ErrPathCannotContainColonZero 76 return false 77 } 78 paths = append(paths, s) 79 return true 80 }) 81 82 if errElement != nil || errIterate != nil { 83 return util.Errors(errElement, errIterate) 84 } 85 86 envli.Lock() 87 defer envli.Unlock() 88 os.Setenv(envli.envName, strings.Join(paths, pathListSeparator)) 89 return nil 90 }