utils/utils.go
2e69e172
 package utils
 
 import (
 	"fmt"
 	"io/ioutil"
 	"os"
6998c3c3
 	"runtime"
2e69e172
 	"strings"
3744452e
 
e5ecfd3b
 	"github.com/docker/docker/pkg/archive"
6896016b
 	"github.com/docker/docker/pkg/stringid"
2e69e172
 )
 
359a6f49
 var globalTestID string
 
 // TestDirectory creates a new temporary directory and returns its path.
 // The contents of directory at path `templateDir` is copied into the
 // new directory.
 func TestDirectory(templateDir string) (dir string, err error) {
 	if globalTestID == "" {
6bca8ec3
 		globalTestID = stringid.GenerateNonCryptoID()[:4]
359a6f49
 	}
 	prefix := fmt.Sprintf("docker-test%s-%s-", globalTestID, GetCallerName(2))
 	if prefix == "" {
 		prefix = "docker-test-"
 	}
 	dir, err = ioutil.TempDir("", prefix)
 	if err = os.Remove(dir); err != nil {
 		return
 	}
 	if templateDir != "" {
e5ecfd3b
 		if err = archive.CopyWithTar(templateDir, dir); err != nil {
359a6f49
 			return
 		}
 	}
 	return
 }
 
 // GetCallerName introspects the call stack and returns the name of the
 // function `depth` levels down in the stack.
 func GetCallerName(depth int) string {
 	// Use the caller function name as a prefix.
 	// This helps trace temp directories back to their test.
 	pc, _, _, _ := runtime.Caller(depth + 1)
 	callerLongName := runtime.FuncForPC(pc).Name()
 	parts := strings.Split(callerLongName, ".")
 	callerShortName := parts[len(parts)-1]
 	return callerShortName
 }
110c4f20
 
17ce3411
 // ReplaceOrAppendEnvValues returns the defaults with the overrides either
b02b933c
 // replaced by env key or appended to the list
 func ReplaceOrAppendEnvValues(defaults, overrides []string) []string {
 	cache := make(map[string]int, len(defaults))
 	for i, e := range defaults {
 		parts := strings.SplitN(e, "=", 2)
 		cache[parts[0]] = i
 	}
9ab73260
 
b02b933c
 	for _, value := range overrides {
9ab73260
 		// Values w/o = means they want this env to be removed/unset.
 		if !strings.Contains(value, "=") {
 			if i, exists := cache[value]; exists {
 				defaults[i] = "" // Used to indicate it should be removed
 			}
 			continue
 		}
 
 		// Just do a normal set/update
b02b933c
 		parts := strings.SplitN(value, "=", 2)
 		if i, exists := cache[parts[0]]; exists {
 			defaults[i] = value
 		} else {
 			defaults = append(defaults, value)
 		}
 	}
9ab73260
 
 	// Now remove all entries that we want to "unset"
 	for i := 0; i < len(defaults); i++ {
 		if defaults[i] == "" {
 			defaults = append(defaults[:i], defaults[i+1:]...)
 			i--
 		}
 	}
 
b02b933c
 	return defaults
 }