utils.go 2.8 KB

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