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  }