github.com/go/docker@v1.12.0-rc2/utils/utils.go (about) 1 package utils 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "runtime" 8 "strings" 9 10 "github.com/docker/docker/pkg/archive" 11 "github.com/docker/docker/pkg/stringid" 12 ) 13 14 var globalTestID string 15 16 // TestDirectory creates a new temporary directory and returns its path. 17 // The contents of directory at path `templateDir` is copied into the 18 // new directory. 19 func TestDirectory(templateDir string) (dir string, err error) { 20 if globalTestID == "" { 21 globalTestID = stringid.GenerateNonCryptoID()[:4] 22 } 23 prefix := fmt.Sprintf("docker-test%s-%s-", globalTestID, GetCallerName(2)) 24 if prefix == "" { 25 prefix = "docker-test-" 26 } 27 dir, err = ioutil.TempDir("", prefix) 28 if err = os.Remove(dir); err != nil { 29 return 30 } 31 if templateDir != "" { 32 if err = archive.CopyWithTar(templateDir, dir); err != nil { 33 return 34 } 35 } 36 return 37 } 38 39 // GetCallerName introspects the call stack and returns the name of the 40 // function `depth` levels down in the stack. 41 func GetCallerName(depth int) string { 42 // Use the caller function name as a prefix. 43 // This helps trace temp directories back to their test. 44 pc, _, _, _ := runtime.Caller(depth + 1) 45 callerLongName := runtime.FuncForPC(pc).Name() 46 parts := strings.Split(callerLongName, ".") 47 callerShortName := parts[len(parts)-1] 48 return callerShortName 49 } 50 51 // ReplaceOrAppendEnvValues returns the defaults with the overrides either 52 // replaced by env key or appended to the list 53 func ReplaceOrAppendEnvValues(defaults, overrides []string) []string { 54 cache := make(map[string]int, len(defaults)) 55 for i, e := range defaults { 56 parts := strings.SplitN(e, "=", 2) 57 cache[parts[0]] = i 58 } 59 60 for _, value := range overrides { 61 // Values w/o = means they want this env to be removed/unset. 62 if !strings.Contains(value, "=") { 63 if i, exists := cache[value]; exists { 64 defaults[i] = "" // Used to indicate it should be removed 65 } 66 continue 67 } 68 69 // Just do a normal set/update 70 parts := strings.SplitN(value, "=", 2) 71 if i, exists := cache[parts[0]]; exists { 72 defaults[i] = value 73 } else { 74 defaults = append(defaults, value) 75 } 76 } 77 78 // Now remove all entries that we want to "unset" 79 for i := 0; i < len(defaults); i++ { 80 if defaults[i] == "" { 81 defaults = append(defaults[:i], defaults[i+1:]...) 82 i-- 83 } 84 } 85 86 return defaults 87 }