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  }