mirror of
https://github.com/containers/podman.git
synced 2025-05-20 00:27:03 +08:00

Cut is a cleaner & more performant api relative to SplitN(_, _, 2) added in go 1.18 Previously applied this refactoring to buildah: https://github.com/containers/buildah/pull/5239 Signed-off-by: Philip Dubé <philip@peerdb.io>
120 lines
2.8 KiB
Go
120 lines
2.8 KiB
Go
// Package for processing environment variables.
|
|
package env
|
|
|
|
// TODO: we need to add tests for this package.
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
const whiteSpaces = " \t"
|
|
|
|
// DefaultEnvVariables returns a default environment, with $PATH and $TERM set.
|
|
func DefaultEnvVariables() map[string]string {
|
|
return map[string]string{
|
|
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
"container": "podman",
|
|
}
|
|
}
|
|
|
|
// Slice transforms the specified map of environment variables into a
|
|
// slice. If a value is non-empty, the key and value are joined with '='.
|
|
func Slice(m map[string]string) []string {
|
|
env := make([]string, 0, len(m))
|
|
for k, v := range m {
|
|
var s string
|
|
if len(v) > 0 {
|
|
s = fmt.Sprintf("%s=%s", k, v)
|
|
} else {
|
|
s = k
|
|
}
|
|
env = append(env, s)
|
|
}
|
|
return env
|
|
}
|
|
|
|
// Map transforms the specified slice of environment variables into a
|
|
// map.
|
|
func Map(slice []string) map[string]string {
|
|
envmap := make(map[string]string, len(slice))
|
|
for _, line := range slice {
|
|
key, val, _ := strings.Cut(line, "=")
|
|
envmap[key] = val
|
|
}
|
|
return envmap
|
|
}
|
|
|
|
// Join joins the two environment maps with override overriding base.
|
|
func Join(base map[string]string, override map[string]string) map[string]string {
|
|
if len(base) == 0 {
|
|
return override
|
|
}
|
|
for k, v := range override {
|
|
base[k] = v
|
|
}
|
|
return base
|
|
}
|
|
|
|
// ParseFile parses the specified path for environment variables and returns them
|
|
// as a map.
|
|
func ParseFile(path string) (_ map[string]string, err error) {
|
|
env := make(map[string]string)
|
|
defer func() {
|
|
if err != nil {
|
|
err = fmt.Errorf("parsing file %q: %w", path, err)
|
|
}
|
|
}()
|
|
|
|
fh, err := os.Open(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer fh.Close()
|
|
|
|
scanner := bufio.NewScanner(fh)
|
|
for scanner.Scan() {
|
|
// trim the line from all leading whitespace first
|
|
line := strings.TrimLeft(scanner.Text(), whiteSpaces)
|
|
// line is not empty, and not starting with '#'
|
|
if len(line) > 0 && !strings.HasPrefix(line, "#") {
|
|
if err := parseEnv(env, line); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
return env, scanner.Err()
|
|
}
|
|
|
|
func parseEnv(env map[string]string, line string) error {
|
|
key, val, hasVal := strings.Cut(line, "=")
|
|
|
|
// catch invalid variables such as "=" or "=A"
|
|
if key == "" {
|
|
return fmt.Errorf("invalid variable: %q", line)
|
|
}
|
|
// trim the front of a variable, but nothing else
|
|
name := strings.TrimLeft(key, whiteSpaces)
|
|
if hasVal {
|
|
env[name] = val
|
|
} else {
|
|
if name, hasStar := strings.CutSuffix(name, "*"); hasStar {
|
|
for _, e := range os.Environ() {
|
|
envKey, envVal, hasEq := strings.Cut(e, "=")
|
|
if !hasEq {
|
|
continue
|
|
}
|
|
if strings.HasPrefix(envKey, name) {
|
|
env[envKey] = envVal
|
|
}
|
|
}
|
|
} else if val, ok := os.LookupEnv(name); ok {
|
|
// if only a pass-through variable is given, clean it up.
|
|
env[name] = val
|
|
}
|
|
}
|
|
return nil
|
|
}
|