github.com/sams1990/dockerrepo@v17.12.1-ce-rc2+incompatible/builder/remotecontext/git/gitutils_test.go (about) 1 package git 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "net/http/httptest" 8 "net/url" 9 "os" 10 "path/filepath" 11 "runtime" 12 "strings" 13 "testing" 14 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 ) 18 19 func TestParseRemoteURL(t *testing.T) { 20 dir, err := parseRemoteURL("git://github.com/user/repo.git") 21 require.NoError(t, err) 22 assert.NotEmpty(t, dir) 23 assert.Equal(t, gitRepo{"git://github.com/user/repo.git", "master", ""}, dir) 24 25 dir, err = parseRemoteURL("git://github.com/user/repo.git#mybranch:mydir/mysubdir/") 26 require.NoError(t, err) 27 assert.NotEmpty(t, dir) 28 assert.Equal(t, gitRepo{"git://github.com/user/repo.git", "mybranch", "mydir/mysubdir/"}, dir) 29 30 dir, err = parseRemoteURL("https://github.com/user/repo.git") 31 require.NoError(t, err) 32 assert.NotEmpty(t, dir) 33 assert.Equal(t, gitRepo{"https://github.com/user/repo.git", "master", ""}, dir) 34 35 dir, err = parseRemoteURL("https://github.com/user/repo.git#mybranch:mydir/mysubdir/") 36 require.NoError(t, err) 37 assert.NotEmpty(t, dir) 38 assert.Equal(t, gitRepo{"https://github.com/user/repo.git", "mybranch", "mydir/mysubdir/"}, dir) 39 40 dir, err = parseRemoteURL("git@github.com:user/repo.git") 41 require.NoError(t, err) 42 assert.NotEmpty(t, dir) 43 assert.Equal(t, gitRepo{"git@github.com:user/repo.git", "master", ""}, dir) 44 45 dir, err = parseRemoteURL("git@github.com:user/repo.git#mybranch:mydir/mysubdir/") 46 require.NoError(t, err) 47 assert.NotEmpty(t, dir) 48 assert.Equal(t, gitRepo{"git@github.com:user/repo.git", "mybranch", "mydir/mysubdir/"}, dir) 49 } 50 51 func TestCloneArgsSmartHttp(t *testing.T) { 52 mux := http.NewServeMux() 53 server := httptest.NewServer(mux) 54 serverURL, _ := url.Parse(server.URL) 55 56 serverURL.Path = "/repo.git" 57 58 mux.HandleFunc("/repo.git/info/refs", func(w http.ResponseWriter, r *http.Request) { 59 q := r.URL.Query().Get("service") 60 w.Header().Set("Content-Type", fmt.Sprintf("application/x-%s-advertisement", q)) 61 }) 62 63 args := fetchArgs(serverURL.String(), "master") 64 exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"} 65 assert.Equal(t, exp, args) 66 } 67 68 func TestCloneArgsDumbHttp(t *testing.T) { 69 mux := http.NewServeMux() 70 server := httptest.NewServer(mux) 71 serverURL, _ := url.Parse(server.URL) 72 73 serverURL.Path = "/repo.git" 74 75 mux.HandleFunc("/repo.git/info/refs", func(w http.ResponseWriter, r *http.Request) { 76 w.Header().Set("Content-Type", "text/plain") 77 }) 78 79 args := fetchArgs(serverURL.String(), "master") 80 exp := []string{"fetch", "--recurse-submodules=yes", "origin", "master"} 81 assert.Equal(t, exp, args) 82 } 83 84 func TestCloneArgsGit(t *testing.T) { 85 args := fetchArgs("git://github.com/docker/docker", "master") 86 exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"} 87 assert.Equal(t, exp, args) 88 } 89 90 func gitGetConfig(name string) string { 91 b, err := git([]string{"config", "--get", name}...) 92 if err != nil { 93 // since we are interested in empty or non empty string, 94 // we can safely ignore the err here. 95 return "" 96 } 97 return strings.TrimSpace(string(b)) 98 } 99 100 func TestCheckoutGit(t *testing.T) { 101 root, err := ioutil.TempDir("", "docker-build-git-checkout") 102 require.NoError(t, err) 103 defer os.RemoveAll(root) 104 105 autocrlf := gitGetConfig("core.autocrlf") 106 if !(autocrlf == "true" || autocrlf == "false" || 107 autocrlf == "input" || autocrlf == "") { 108 t.Logf("unknown core.autocrlf value: \"%s\"", autocrlf) 109 } 110 eol := "\n" 111 if autocrlf == "true" { 112 eol = "\r\n" 113 } 114 115 gitDir := filepath.Join(root, "repo") 116 _, err = git("init", gitDir) 117 require.NoError(t, err) 118 119 _, err = gitWithinDir(gitDir, "config", "user.email", "test@docker.com") 120 require.NoError(t, err) 121 122 _, err = gitWithinDir(gitDir, "config", "user.name", "Docker test") 123 require.NoError(t, err) 124 125 err = ioutil.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte("FROM scratch"), 0644) 126 require.NoError(t, err) 127 128 subDir := filepath.Join(gitDir, "subdir") 129 require.NoError(t, os.Mkdir(subDir, 0755)) 130 131 err = ioutil.WriteFile(filepath.Join(subDir, "Dockerfile"), []byte("FROM scratch\nEXPOSE 5000"), 0644) 132 require.NoError(t, err) 133 134 if runtime.GOOS != "windows" { 135 if err = os.Symlink("../subdir", filepath.Join(gitDir, "parentlink")); err != nil { 136 t.Fatal(err) 137 } 138 139 if err = os.Symlink("/subdir", filepath.Join(gitDir, "absolutelink")); err != nil { 140 t.Fatal(err) 141 } 142 } 143 144 _, err = gitWithinDir(gitDir, "add", "-A") 145 require.NoError(t, err) 146 147 _, err = gitWithinDir(gitDir, "commit", "-am", "First commit") 148 require.NoError(t, err) 149 150 _, err = gitWithinDir(gitDir, "checkout", "-b", "test") 151 require.NoError(t, err) 152 153 err = ioutil.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte("FROM scratch\nEXPOSE 3000"), 0644) 154 require.NoError(t, err) 155 156 err = ioutil.WriteFile(filepath.Join(subDir, "Dockerfile"), []byte("FROM busybox\nEXPOSE 5000"), 0644) 157 require.NoError(t, err) 158 159 _, err = gitWithinDir(gitDir, "add", "-A") 160 require.NoError(t, err) 161 162 _, err = gitWithinDir(gitDir, "commit", "-am", "Branch commit") 163 require.NoError(t, err) 164 165 _, err = gitWithinDir(gitDir, "checkout", "master") 166 require.NoError(t, err) 167 168 type singleCase struct { 169 frag string 170 exp string 171 fail bool 172 } 173 174 cases := []singleCase{ 175 {"", "FROM scratch", false}, 176 {"master", "FROM scratch", false}, 177 {":subdir", "FROM scratch" + eol + "EXPOSE 5000", false}, 178 {":nosubdir", "", true}, // missing directory error 179 {":Dockerfile", "", true}, // not a directory error 180 {"master:nosubdir", "", true}, 181 {"master:subdir", "FROM scratch" + eol + "EXPOSE 5000", false}, 182 {"master:../subdir", "", true}, 183 {"test", "FROM scratch" + eol + "EXPOSE 3000", false}, 184 {"test:", "FROM scratch" + eol + "EXPOSE 3000", false}, 185 {"test:subdir", "FROM busybox" + eol + "EXPOSE 5000", false}, 186 } 187 188 if runtime.GOOS != "windows" { 189 // Windows GIT (2.7.1 x64) does not support parentlink/absolutelink. Sample output below 190 // git --work-tree .\repo --git-dir .\repo\.git add -A 191 // error: readlink("absolutelink"): Function not implemented 192 // error: unable to index file absolutelink 193 // fatal: adding files failed 194 cases = append(cases, singleCase{frag: "master:absolutelink", exp: "FROM scratch" + eol + "EXPOSE 5000", fail: false}) 195 cases = append(cases, singleCase{frag: "master:parentlink", exp: "FROM scratch" + eol + "EXPOSE 5000", fail: false}) 196 } 197 198 for _, c := range cases { 199 ref, subdir := getRefAndSubdir(c.frag) 200 r, err := checkoutGit(gitDir, ref, subdir) 201 202 if c.fail { 203 assert.Error(t, err) 204 continue 205 } 206 207 b, err := ioutil.ReadFile(filepath.Join(r, "Dockerfile")) 208 require.NoError(t, err) 209 assert.Equal(t, c.exp, string(b)) 210 } 211 } 212 213 func TestValidGitTransport(t *testing.T) { 214 gitUrls := []string{ 215 "git://github.com/docker/docker", 216 "git@github.com:docker/docker.git", 217 "git@bitbucket.org:atlassianlabs/atlassian-docker.git", 218 "https://github.com/docker/docker.git", 219 "http://github.com/docker/docker.git", 220 "http://github.com/docker/docker.git#branch", 221 "http://github.com/docker/docker.git#:dir", 222 } 223 incompleteGitUrls := []string{ 224 "github.com/docker/docker", 225 } 226 227 for _, url := range gitUrls { 228 if !isGitTransport(url) { 229 t.Fatalf("%q should be detected as valid Git prefix", url) 230 } 231 } 232 233 for _, url := range incompleteGitUrls { 234 if isGitTransport(url) { 235 t.Fatalf("%q should not be detected as valid Git prefix", url) 236 } 237 } 238 }