gitutils_test.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package gitutils
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "net/http"
  6. "net/http/httptest"
  7. "net/url"
  8. "os"
  9. "path/filepath"
  10. "reflect"
  11. "runtime"
  12. "strings"
  13. "testing"
  14. )
  15. func TestCloneArgsSmartHttp(t *testing.T) {
  16. mux := http.NewServeMux()
  17. server := httptest.NewServer(mux)
  18. serverURL, _ := url.Parse(server.URL)
  19. serverURL.Path = "/repo.git"
  20. mux.HandleFunc("/repo.git/info/refs", func(w http.ResponseWriter, r *http.Request) {
  21. q := r.URL.Query().Get("service")
  22. w.Header().Set("Content-Type", fmt.Sprintf("application/x-%s-advertisement", q))
  23. })
  24. args := fetchArgs(serverURL, "master")
  25. exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"}
  26. if !reflect.DeepEqual(args, exp) {
  27. t.Fatalf("Expected %v, got %v", exp, args)
  28. }
  29. }
  30. func TestCloneArgsDumbHttp(t *testing.T) {
  31. mux := http.NewServeMux()
  32. server := httptest.NewServer(mux)
  33. serverURL, _ := url.Parse(server.URL)
  34. serverURL.Path = "/repo.git"
  35. mux.HandleFunc("/repo.git/info/refs", func(w http.ResponseWriter, r *http.Request) {
  36. w.Header().Set("Content-Type", "text/plain")
  37. })
  38. args := fetchArgs(serverURL, "master")
  39. exp := []string{"fetch", "--recurse-submodules=yes", "origin", "master"}
  40. if !reflect.DeepEqual(args, exp) {
  41. t.Fatalf("Expected %v, got %v", exp, args)
  42. }
  43. }
  44. func TestCloneArgsGit(t *testing.T) {
  45. u, _ := url.Parse("git://github.com/docker/docker")
  46. args := fetchArgs(u, "master")
  47. exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"}
  48. if !reflect.DeepEqual(args, exp) {
  49. t.Fatalf("Expected %v, got %v", exp, args)
  50. }
  51. }
  52. func gitGetConfig(name string) string {
  53. b, err := git([]string{"config", "--get", name}...)
  54. if err != nil {
  55. // since we are interested in empty or non empty string,
  56. // we can safely ignore the err here.
  57. return ""
  58. }
  59. return strings.TrimSpace(string(b))
  60. }
  61. func TestCheckoutGit(t *testing.T) {
  62. root, err := ioutil.TempDir("", "docker-build-git-checkout")
  63. if err != nil {
  64. t.Fatal(err)
  65. }
  66. defer os.RemoveAll(root)
  67. autocrlf := gitGetConfig("core.autocrlf")
  68. if !(autocrlf == "true" || autocrlf == "false" ||
  69. autocrlf == "input" || autocrlf == "") {
  70. t.Logf("unknown core.autocrlf value: \"%s\"", autocrlf)
  71. }
  72. eol := "\n"
  73. if autocrlf == "true" {
  74. eol = "\r\n"
  75. }
  76. gitDir := filepath.Join(root, "repo")
  77. _, err = git("init", gitDir)
  78. if err != nil {
  79. t.Fatal(err)
  80. }
  81. if _, err = gitWithinDir(gitDir, "config", "user.email", "test@docker.com"); err != nil {
  82. t.Fatal(err)
  83. }
  84. if _, err = gitWithinDir(gitDir, "config", "user.name", "Docker test"); err != nil {
  85. t.Fatal(err)
  86. }
  87. if err = ioutil.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte("FROM scratch"), 0644); err != nil {
  88. t.Fatal(err)
  89. }
  90. subDir := filepath.Join(gitDir, "subdir")
  91. if err = os.Mkdir(subDir, 0755); err != nil {
  92. t.Fatal(err)
  93. }
  94. if err = ioutil.WriteFile(filepath.Join(subDir, "Dockerfile"), []byte("FROM scratch\nEXPOSE 5000"), 0644); err != nil {
  95. t.Fatal(err)
  96. }
  97. if runtime.GOOS != "windows" {
  98. if err = os.Symlink("../subdir", filepath.Join(gitDir, "parentlink")); err != nil {
  99. t.Fatal(err)
  100. }
  101. if err = os.Symlink("/subdir", filepath.Join(gitDir, "absolutelink")); err != nil {
  102. t.Fatal(err)
  103. }
  104. }
  105. if _, err = gitWithinDir(gitDir, "add", "-A"); err != nil {
  106. t.Fatal(err)
  107. }
  108. if _, err = gitWithinDir(gitDir, "commit", "-am", "First commit"); err != nil {
  109. t.Fatal(err)
  110. }
  111. if _, err = gitWithinDir(gitDir, "checkout", "-b", "test"); err != nil {
  112. t.Fatal(err)
  113. }
  114. if err = ioutil.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte("FROM scratch\nEXPOSE 3000"), 0644); err != nil {
  115. t.Fatal(err)
  116. }
  117. if err = ioutil.WriteFile(filepath.Join(subDir, "Dockerfile"), []byte("FROM busybox\nEXPOSE 5000"), 0644); err != nil {
  118. t.Fatal(err)
  119. }
  120. if _, err = gitWithinDir(gitDir, "add", "-A"); err != nil {
  121. t.Fatal(err)
  122. }
  123. if _, err = gitWithinDir(gitDir, "commit", "-am", "Branch commit"); err != nil {
  124. t.Fatal(err)
  125. }
  126. if _, err = gitWithinDir(gitDir, "checkout", "master"); err != nil {
  127. t.Fatal(err)
  128. }
  129. type singleCase struct {
  130. frag string
  131. exp string
  132. fail bool
  133. }
  134. cases := []singleCase{
  135. {"", "FROM scratch", false},
  136. {"master", "FROM scratch", false},
  137. {":subdir", "FROM scratch" + eol + "EXPOSE 5000", false},
  138. {":nosubdir", "", true}, // missing directory error
  139. {":Dockerfile", "", true}, // not a directory error
  140. {"master:nosubdir", "", true},
  141. {"master:subdir", "FROM scratch" + eol + "EXPOSE 5000", false},
  142. {"master:../subdir", "", true},
  143. {"test", "FROM scratch" + eol + "EXPOSE 3000", false},
  144. {"test:", "FROM scratch" + eol + "EXPOSE 3000", false},
  145. {"test:subdir", "FROM busybox" + eol + "EXPOSE 5000", false},
  146. }
  147. if runtime.GOOS != "windows" {
  148. // Windows GIT (2.7.1 x64) does not support parentlink/absolutelink. Sample output below
  149. // git --work-tree .\repo --git-dir .\repo\.git add -A
  150. // error: readlink("absolutelink"): Function not implemented
  151. // error: unable to index file absolutelink
  152. // fatal: adding files failed
  153. cases = append(cases, singleCase{frag: "master:absolutelink", exp: "FROM scratch" + eol + "EXPOSE 5000", fail: false})
  154. cases = append(cases, singleCase{frag: "master:parentlink", exp: "FROM scratch" + eol + "EXPOSE 5000", fail: false})
  155. }
  156. for _, c := range cases {
  157. ref, subdir := getRefAndSubdir(c.frag)
  158. r, err := checkoutGit(gitDir, ref, subdir)
  159. fail := err != nil
  160. if fail != c.fail {
  161. t.Fatalf("Expected %v failure, error was %v\n", c.fail, err)
  162. }
  163. if c.fail {
  164. continue
  165. }
  166. b, err := ioutil.ReadFile(filepath.Join(r, "Dockerfile"))
  167. if err != nil {
  168. t.Fatal(err)
  169. }
  170. if string(b) != c.exp {
  171. t.Fatalf("Expected %v, was %v\n", c.exp, string(b))
  172. }
  173. }
  174. }