// Copyright 2017 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package build import ( "bufio" "fmt" "io" "os" "strings" ) // Environment adds a number of useful manipulation functions to the list of // strings returned by os.Environ() and used in exec.Cmd.Env. type Environment []string // OsEnvironment wraps the current environment returned by os.Environ() func OsEnvironment() *Environment { env := Environment(os.Environ()) return &env } // Get returns the value associated with the key, and whether it exists. // It's equivalent to the os.LookupEnv function, but with this copy of the // Environment. func (e *Environment) Get(key string) (string, bool) { for _, env := range *e { if k, v, ok := decodeKeyValue(env); ok && k == key { return v, true } } return "", false } // Set sets the value associated with the key, overwriting the current value // if it exists. func (e *Environment) Set(key, value string) { e.Unset(key) *e = append(*e, key+"="+value) } // Unset removes the specified keys from the Environment. func (e *Environment) Unset(keys ...string) { out := (*e)[:0] for _, env := range *e { if key, _, ok := decodeKeyValue(env); ok && inList(key, keys) { continue } out = append(out, env) } *e = out } // UnsetWithPrefix removes all keys that start with prefix. func (e *Environment) UnsetWithPrefix(prefix string) { out := (*e)[:0] for _, env := range *e { if key, _, ok := decodeKeyValue(env); ok && strings.HasPrefix(key, prefix) { continue } out = append(out, env) } *e = out } // Allow removes all keys that are not present in the input list func (e *Environment) Allow(keys ...string) { out := (*e)[:0] for _, env := range *e { if key, _, ok := decodeKeyValue(env); ok && inList(key, keys) { out = append(out, env) } } *e = out } // Environ returns the []string required for exec.Cmd.Env func (e *Environment) Environ() []string { return []string(*e) } // Copy returns a copy of the Environment so that independent changes may be made. func (e *Environment) Copy() *Environment { ret := Environment(make([]string, len(*e))) for i, v := range *e { ret[i] = v } return &ret } // IsTrue returns whether an environment variable is set to a positive value (1,y,yes,on,true) func (e *Environment) IsEnvTrue(key string) bool { if value, ok := e.Get(key); ok { return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true" } return false } // IsFalse returns whether an environment variable is set to a negative value (0,n,no,off,false) func (e *Environment) IsFalse(key string) bool { if value, ok := e.Get(key); ok { return value == "0" || value == "n" || value == "no" || value == "off" || value == "false" } return false } // AppendFromKati reads a shell script written by Kati that exports or unsets // environment variables, and applies those to the local Environment. func (e *Environment) AppendFromKati(filename string) error { file, err := os.Open(filename) if err != nil { return err } defer file.Close() return e.appendFromKati(file) } func (e *Environment) appendFromKati(reader io.Reader) error { scanner := bufio.NewScanner(reader) for scanner.Scan() { text := strings.TrimSpace(scanner.Text()) if len(text) == 0 || text[0] == '#' { continue } cmd := strings.SplitN(text, " ", 2) if len(cmd) != 2 { return fmt.Errorf("Unknown kati environment line: %q", text) } if cmd[0] == "unset" { str, ok := singleUnquote(cmd[1]) if !ok { return fmt.Errorf("Failed to unquote kati line: %q", text) } e.Unset(str) } else if cmd[0] == "export" { key, value, ok := decodeKeyValue(cmd[1]) if !ok { return fmt.Errorf("Failed to parse export: %v", cmd) } key, ok = singleUnquote(key) if !ok { return fmt.Errorf("Failed to unquote kati line: %q", text) } value, ok = singleUnquote(value) if !ok { return fmt.Errorf("Failed to unquote kati line: %q", text) } e.Set(key, value) } else { return fmt.Errorf("Unknown kati environment command: %q", text) } } if err := scanner.Err(); err != nil { return err } return nil }