123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- // 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"
- "strconv"
- "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
- }
- // Returns a copy of the environment as a map[string]string.
- func (e *Environment) AsMap() map[string]string {
- result := make(map[string]string)
- for _, envVar := range *e {
- if k, v, ok := decodeKeyValue(envVar); ok {
- result[k] = v
- }
- }
- return result
- }
- // 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 _, envVar := range *e {
- if k, v, ok := decodeKeyValue(envVar); ok && k == key {
- return v, true
- }
- }
- return "", false
- }
- // Get returns the int value associated with the key, and whether it exists
- // and is a valid int.
- func (e *Environment) GetInt(key string) (int, bool) {
- if v, ok := e.Get(key); ok {
- if i, err := strconv.Atoi(v); err == nil {
- return i, true
- }
- }
- return 0, 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) {
- newEnv := (*e)[:0]
- for _, envVar := range *e {
- if key, _, ok := decodeKeyValue(envVar); ok && inList(key, keys) {
- // Delete this key.
- continue
- }
- newEnv = append(newEnv, envVar)
- }
- *e = newEnv
- }
- // UnsetWithPrefix removes all keys that start with prefix.
- func (e *Environment) UnsetWithPrefix(prefix string) {
- newEnv := (*e)[:0]
- for _, envVar := range *e {
- if key, _, ok := decodeKeyValue(envVar); ok && strings.HasPrefix(key, prefix) {
- // Delete this key.
- continue
- }
- newEnv = append(newEnv, envVar)
- }
- *e = newEnv
- }
- // Allow removes all keys that are not present in the input list
- func (e *Environment) Allow(keys ...string) {
- newEnv := (*e)[:0]
- for _, envVar := range *e {
- if key, _, ok := decodeKeyValue(envVar); ok && inList(key, keys) {
- // Keep this key.
- newEnv = append(newEnv, envVar)
- }
- }
- *e = newEnv
- }
- // 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 {
- envCopy := Environment(make([]string, len(*e)))
- for i, envVar := range *e {
- envCopy[i] = envVar
- }
- return &envCopy
- }
- // 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)
- }
- // Helper function for AppendFromKati. Accepts an io.Reader to make testing easier.
- 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] == '#' {
- // Skip blank lines and comments.
- continue
- }
- // We expect two space-delimited strings, like:
- // unset 'HOME'
- // export 'BEST_PIZZA_CITY'='NYC'
- 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)
- }
- // Actually unset it.
- 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)
- }
- // Actually set it.
- e.Set(key, value)
- } else {
- return fmt.Errorf("Unknown kati environment command: %q", text)
- }
- }
- if err := scanner.Err(); err != nil {
- return err
- }
- return nil
- }
|