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