• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017 Google Inc. All rights reserved.
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
15package build
16
17import (
18	"bufio"
19	"fmt"
20	"io"
21	"os"
22	"strings"
23)
24
25// Environment adds a number of useful manipulation functions to the list of
26// strings returned by os.Environ() and used in exec.Cmd.Env.
27type Environment []string
28
29// OsEnvironment wraps the current environment returned by os.Environ()
30func OsEnvironment() *Environment {
31	env := Environment(os.Environ())
32	return &env
33}
34
35// Get returns the value associated with the key, and whether it exists.
36// It's equivalent to the os.LookupEnv function, but with this copy of the
37// Environment.
38func (e *Environment) Get(key string) (string, bool) {
39	for _, env := range *e {
40		if k, v, ok := decodeKeyValue(env); ok && k == key {
41			return v, true
42		}
43	}
44	return "", false
45}
46
47// Set sets the value associated with the key, overwriting the current value
48// if it exists.
49func (e *Environment) Set(key, value string) {
50	e.Unset(key)
51	*e = append(*e, key+"="+value)
52}
53
54// Unset removes the specified keys from the Environment.
55func (e *Environment) Unset(keys ...string) {
56	out := (*e)[:0]
57	for _, env := range *e {
58		if key, _, ok := decodeKeyValue(env); ok && inList(key, keys) {
59			continue
60		}
61		out = append(out, env)
62	}
63	*e = out
64}
65
66// Environ returns the []string required for exec.Cmd.Env
67func (e *Environment) Environ() []string {
68	return []string(*e)
69}
70
71// Copy returns a copy of the Environment so that independent changes may be made.
72func (e *Environment) Copy() *Environment {
73	ret := Environment(make([]string, len(*e)))
74	for i, v := range *e {
75		ret[i] = v
76	}
77	return &ret
78}
79
80// IsTrue returns whether an environment variable is set to a positive value (1,y,yes,on,true)
81func (e *Environment) IsEnvTrue(key string) bool {
82	if value, ok := e.Get(key); ok {
83		return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true"
84	}
85	return false
86}
87
88// IsFalse returns whether an environment variable is set to a negative value (0,n,no,off,false)
89func (e *Environment) IsFalse(key string) bool {
90	if value, ok := e.Get(key); ok {
91		return value == "0" || value == "n" || value == "no" || value == "off" || value == "false"
92	}
93	return false
94}
95
96// AppendFromKati reads a shell script written by Kati that exports or unsets
97// environment variables, and applies those to the local Environment.
98func (e *Environment) AppendFromKati(filename string) error {
99	file, err := os.Open(filename)
100	if err != nil {
101		return err
102	}
103	defer file.Close()
104
105	return e.appendFromKati(file)
106}
107
108func (e *Environment) appendFromKati(reader io.Reader) error {
109	scanner := bufio.NewScanner(reader)
110	for scanner.Scan() {
111		text := strings.TrimSpace(scanner.Text())
112
113		if len(text) == 0 || text[0] == '#' {
114			continue
115		}
116
117		cmd := strings.SplitN(text, " ", 2)
118		if len(cmd) != 2 {
119			return fmt.Errorf("Unknown kati environment line: %q", text)
120		}
121
122		if cmd[0] == "unset" {
123			str, ok := singleUnquote(cmd[1])
124			if !ok {
125				fmt.Errorf("Failed to unquote kati line: %q", text)
126			}
127			e.Unset(str)
128		} else if cmd[0] == "export" {
129			key, value, ok := decodeKeyValue(cmd[1])
130			if !ok {
131				return fmt.Errorf("Failed to parse export: %v", cmd)
132			}
133
134			key, ok = singleUnquote(key)
135			if !ok {
136				return fmt.Errorf("Failed to unquote kati line: %q", text)
137			}
138			value, ok = singleUnquote(value)
139			if !ok {
140				return fmt.Errorf("Failed to unquote kati line: %q", text)
141			}
142
143			e.Set(key, value)
144		} else {
145			return fmt.Errorf("Unknown kati environment command: %q", text)
146		}
147	}
148	if err := scanner.Err(); err != nil {
149		return err
150	}
151	return nil
152}
153