Browse code

Move pkg/gitutils to remotecontext/git

Signed-off-by: Daniel Nephin <dnephin@docker.com>

Daniel Nephin authored on 2017/06/02 06:15:13
Showing 5 changed files
... ...
@@ -4,13 +4,13 @@ import (
4 4
 	"os"
5 5
 
6 6
 	"github.com/docker/docker/builder"
7
+	"github.com/docker/docker/builder/remotecontext/git"
7 8
 	"github.com/docker/docker/pkg/archive"
8
-	"github.com/docker/docker/pkg/gitutils"
9 9
 )
10 10
 
11 11
 // MakeGitContext returns a Context from gitURL that is cloned in a temporary directory.
12 12
 func MakeGitContext(gitURL string) (builder.Source, error) {
13
-	root, err := gitutils.Clone(gitURL)
13
+	root, err := git.Clone(gitURL)
14 14
 	if err != nil {
15 15
 		return nil, err
16 16
 	}
17 17
new file mode 100644
... ...
@@ -0,0 +1,122 @@
0
+package git
1
+
2
+import (
3
+	"fmt"
4
+	"io/ioutil"
5
+	"net/http"
6
+	"net/url"
7
+	"os"
8
+	"os/exec"
9
+	"path/filepath"
10
+	"strings"
11
+
12
+	"github.com/docker/docker/pkg/symlink"
13
+	"github.com/docker/docker/pkg/urlutil"
14
+	"github.com/pkg/errors"
15
+)
16
+
17
+// Clone clones a repository into a newly created directory which
18
+// will be under "docker-build-git"
19
+func Clone(remoteURL string) (string, error) {
20
+	if !urlutil.IsGitTransport(remoteURL) {
21
+		remoteURL = "https://" + remoteURL
22
+	}
23
+	root, err := ioutil.TempDir("", "docker-build-git")
24
+	if err != nil {
25
+		return "", err
26
+	}
27
+
28
+	u, err := url.Parse(remoteURL)
29
+	if err != nil {
30
+		return "", err
31
+	}
32
+
33
+	if out, err := gitWithinDir(root, "init"); err != nil {
34
+		return "", errors.Wrapf(err, "failed to init repo at %s: %s", root, out)
35
+	}
36
+
37
+	ref, subdir := getRefAndSubdir(u.Fragment)
38
+	fetch := fetchArgs(u, ref)
39
+
40
+	u.Fragment = ""
41
+
42
+	// Add origin remote for compatibility with previous implementation that
43
+	// used "git clone" and also to make sure local refs are created for branches
44
+	if out, err := gitWithinDir(root, "remote", "add", "origin", u.String()); err != nil {
45
+		return "", errors.Wrapf(err, "failed add origin repo at %s: %s", u.String(), out)
46
+	}
47
+
48
+	if output, err := gitWithinDir(root, fetch...); err != nil {
49
+		return "", errors.Wrapf(err, "error fetching: %s", output)
50
+	}
51
+
52
+	return checkoutGit(root, ref, subdir)
53
+}
54
+
55
+func getRefAndSubdir(fragment string) (ref string, subdir string) {
56
+	refAndDir := strings.SplitN(fragment, ":", 2)
57
+	ref = "master"
58
+	if len(refAndDir[0]) != 0 {
59
+		ref = refAndDir[0]
60
+	}
61
+	if len(refAndDir) > 1 && len(refAndDir[1]) != 0 {
62
+		subdir = refAndDir[1]
63
+	}
64
+	return
65
+}
66
+
67
+func fetchArgs(remoteURL *url.URL, ref string) []string {
68
+	args := []string{"fetch", "--recurse-submodules=yes"}
69
+	shallow := true
70
+
71
+	if strings.HasPrefix(remoteURL.Scheme, "http") {
72
+		res, err := http.Head(fmt.Sprintf("%s/info/refs?service=git-upload-pack", remoteURL))
73
+		if err != nil || res.Header.Get("Content-Type") != "application/x-git-upload-pack-advertisement" {
74
+			shallow = false
75
+		}
76
+	}
77
+
78
+	if shallow {
79
+		args = append(args, "--depth", "1")
80
+	}
81
+
82
+	return append(args, "origin", ref)
83
+}
84
+
85
+func checkoutGit(root, ref, subdir string) (string, error) {
86
+	// Try checking out by ref name first. This will work on branches and sets
87
+	// .git/HEAD to the current branch name
88
+	if output, err := gitWithinDir(root, "checkout", ref); err != nil {
89
+		// If checking out by branch name fails check out the last fetched ref
90
+		if _, err2 := gitWithinDir(root, "checkout", "FETCH_HEAD"); err2 != nil {
91
+			return "", errors.Wrapf(err, "error checking out %s: %s", ref, output)
92
+		}
93
+	}
94
+
95
+	if subdir != "" {
96
+		newCtx, err := symlink.FollowSymlinkInScope(filepath.Join(root, subdir), root)
97
+		if err != nil {
98
+			return "", errors.Wrapf(err, "error setting git context, %q not within git root", subdir)
99
+		}
100
+
101
+		fi, err := os.Stat(newCtx)
102
+		if err != nil {
103
+			return "", err
104
+		}
105
+		if !fi.IsDir() {
106
+			return "", errors.Errorf("error setting git context, not a directory: %s", newCtx)
107
+		}
108
+		root = newCtx
109
+	}
110
+
111
+	return root, nil
112
+}
113
+
114
+func gitWithinDir(dir string, args ...string) ([]byte, error) {
115
+	a := []string{"--work-tree", dir, "--git-dir", filepath.Join(dir, ".git")}
116
+	return git(append(a, args...)...)
117
+}
118
+
119
+func git(args ...string) ([]byte, error) {
120
+	return exec.Command("git", args...).CombinedOutput()
121
+}
0 122
new file mode 100644
... ...
@@ -0,0 +1,180 @@
0
+package git
1
+
2
+import (
3
+	"fmt"
4
+	"io/ioutil"
5
+	"net/http"
6
+	"net/http/httptest"
7
+	"net/url"
8
+	"os"
9
+	"path/filepath"
10
+	"runtime"
11
+	"strings"
12
+	"testing"
13
+
14
+	"github.com/stretchr/testify/assert"
15
+	"github.com/stretchr/testify/require"
16
+)
17
+
18
+func TestCloneArgsSmartHttp(t *testing.T) {
19
+	mux := http.NewServeMux()
20
+	server := httptest.NewServer(mux)
21
+	serverURL, _ := url.Parse(server.URL)
22
+
23
+	serverURL.Path = "/repo.git"
24
+
25
+	mux.HandleFunc("/repo.git/info/refs", func(w http.ResponseWriter, r *http.Request) {
26
+		q := r.URL.Query().Get("service")
27
+		w.Header().Set("Content-Type", fmt.Sprintf("application/x-%s-advertisement", q))
28
+	})
29
+
30
+	args := fetchArgs(serverURL, "master")
31
+	exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"}
32
+	assert.Equal(t, exp, args)
33
+}
34
+
35
+func TestCloneArgsDumbHttp(t *testing.T) {
36
+	mux := http.NewServeMux()
37
+	server := httptest.NewServer(mux)
38
+	serverURL, _ := url.Parse(server.URL)
39
+
40
+	serverURL.Path = "/repo.git"
41
+
42
+	mux.HandleFunc("/repo.git/info/refs", func(w http.ResponseWriter, r *http.Request) {
43
+		w.Header().Set("Content-Type", "text/plain")
44
+	})
45
+
46
+	args := fetchArgs(serverURL, "master")
47
+	exp := []string{"fetch", "--recurse-submodules=yes", "origin", "master"}
48
+	assert.Equal(t, exp, args)
49
+}
50
+
51
+func TestCloneArgsGit(t *testing.T) {
52
+	u, _ := url.Parse("git://github.com/docker/docker")
53
+	args := fetchArgs(u, "master")
54
+	exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"}
55
+	assert.Equal(t, exp, args)
56
+}
57
+
58
+func gitGetConfig(name string) string {
59
+	b, err := git([]string{"config", "--get", name}...)
60
+	if err != nil {
61
+		// since we are interested in empty or non empty string,
62
+		// we can safely ignore the err here.
63
+		return ""
64
+	}
65
+	return strings.TrimSpace(string(b))
66
+}
67
+
68
+func TestCheckoutGit(t *testing.T) {
69
+	root, err := ioutil.TempDir("", "docker-build-git-checkout")
70
+	require.NoError(t, err)
71
+	defer os.RemoveAll(root)
72
+
73
+	autocrlf := gitGetConfig("core.autocrlf")
74
+	if !(autocrlf == "true" || autocrlf == "false" ||
75
+		autocrlf == "input" || autocrlf == "") {
76
+		t.Logf("unknown core.autocrlf value: \"%s\"", autocrlf)
77
+	}
78
+	eol := "\n"
79
+	if autocrlf == "true" {
80
+		eol = "\r\n"
81
+	}
82
+
83
+	gitDir := filepath.Join(root, "repo")
84
+	_, err = git("init", gitDir)
85
+	require.NoError(t, err)
86
+
87
+	_, err = gitWithinDir(gitDir, "config", "user.email", "test@docker.com")
88
+	require.NoError(t, err)
89
+
90
+	_, err = gitWithinDir(gitDir, "config", "user.name", "Docker test")
91
+	require.NoError(t, err)
92
+
93
+	err = ioutil.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte("FROM scratch"), 0644)
94
+	require.NoError(t, err)
95
+
96
+	subDir := filepath.Join(gitDir, "subdir")
97
+	require.NoError(t, os.Mkdir(subDir, 0755))
98
+
99
+	err = ioutil.WriteFile(filepath.Join(subDir, "Dockerfile"), []byte("FROM scratch\nEXPOSE 5000"), 0644)
100
+	require.NoError(t, err)
101
+
102
+	if runtime.GOOS != "windows" {
103
+		if err = os.Symlink("../subdir", filepath.Join(gitDir, "parentlink")); err != nil {
104
+			t.Fatal(err)
105
+		}
106
+
107
+		if err = os.Symlink("/subdir", filepath.Join(gitDir, "absolutelink")); err != nil {
108
+			t.Fatal(err)
109
+		}
110
+	}
111
+
112
+	_, err = gitWithinDir(gitDir, "add", "-A")
113
+	require.NoError(t, err)
114
+
115
+	_, err = gitWithinDir(gitDir, "commit", "-am", "First commit")
116
+	require.NoError(t, err)
117
+
118
+	_, err = gitWithinDir(gitDir, "checkout", "-b", "test")
119
+	require.NoError(t, err)
120
+
121
+	err = ioutil.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte("FROM scratch\nEXPOSE 3000"), 0644)
122
+	require.NoError(t, err)
123
+
124
+	err = ioutil.WriteFile(filepath.Join(subDir, "Dockerfile"), []byte("FROM busybox\nEXPOSE 5000"), 0644)
125
+	require.NoError(t, err)
126
+
127
+	_, err = gitWithinDir(gitDir, "add", "-A")
128
+	require.NoError(t, err)
129
+
130
+	_, err = gitWithinDir(gitDir, "commit", "-am", "Branch commit")
131
+	require.NoError(t, err)
132
+
133
+	_, err = gitWithinDir(gitDir, "checkout", "master")
134
+	require.NoError(t, err)
135
+
136
+	type singleCase struct {
137
+		frag string
138
+		exp  string
139
+		fail bool
140
+	}
141
+
142
+	cases := []singleCase{
143
+		{"", "FROM scratch", false},
144
+		{"master", "FROM scratch", false},
145
+		{":subdir", "FROM scratch" + eol + "EXPOSE 5000", false},
146
+		{":nosubdir", "", true},   // missing directory error
147
+		{":Dockerfile", "", true}, // not a directory error
148
+		{"master:nosubdir", "", true},
149
+		{"master:subdir", "FROM scratch" + eol + "EXPOSE 5000", false},
150
+		{"master:../subdir", "", true},
151
+		{"test", "FROM scratch" + eol + "EXPOSE 3000", false},
152
+		{"test:", "FROM scratch" + eol + "EXPOSE 3000", false},
153
+		{"test:subdir", "FROM busybox" + eol + "EXPOSE 5000", false},
154
+	}
155
+
156
+	if runtime.GOOS != "windows" {
157
+		// Windows GIT (2.7.1 x64) does not support parentlink/absolutelink. Sample output below
158
+		// 	git --work-tree .\repo --git-dir .\repo\.git add -A
159
+		//	error: readlink("absolutelink"): Function not implemented
160
+		// 	error: unable to index file absolutelink
161
+		// 	fatal: adding files failed
162
+		cases = append(cases, singleCase{frag: "master:absolutelink", exp: "FROM scratch" + eol + "EXPOSE 5000", fail: false})
163
+		cases = append(cases, singleCase{frag: "master:parentlink", exp: "FROM scratch" + eol + "EXPOSE 5000", fail: false})
164
+	}
165
+
166
+	for _, c := range cases {
167
+		ref, subdir := getRefAndSubdir(c.frag)
168
+		r, err := checkoutGit(gitDir, ref, subdir)
169
+
170
+		if c.fail {
171
+			assert.Error(t, err)
172
+			continue
173
+		}
174
+
175
+		b, err := ioutil.ReadFile(filepath.Join(r, "Dockerfile"))
176
+		require.NoError(t, err)
177
+		assert.Equal(t, c.exp, string(b))
178
+	}
179
+}
0 180
deleted file mode 100644
... ...
@@ -1,122 +0,0 @@
1
-package gitutils
2
-
3
-import (
4
-	"fmt"
5
-	"io/ioutil"
6
-	"net/http"
7
-	"net/url"
8
-	"os"
9
-	"os/exec"
10
-	"path/filepath"
11
-	"strings"
12
-
13
-	"github.com/docker/docker/pkg/symlink"
14
-	"github.com/docker/docker/pkg/urlutil"
15
-	"github.com/pkg/errors"
16
-)
17
-
18
-// Clone clones a repository into a newly created directory which
19
-// will be under "docker-build-git"
20
-func Clone(remoteURL string) (string, error) {
21
-	if !urlutil.IsGitTransport(remoteURL) {
22
-		remoteURL = "https://" + remoteURL
23
-	}
24
-	root, err := ioutil.TempDir("", "docker-build-git")
25
-	if err != nil {
26
-		return "", err
27
-	}
28
-
29
-	u, err := url.Parse(remoteURL)
30
-	if err != nil {
31
-		return "", err
32
-	}
33
-
34
-	if out, err := gitWithinDir(root, "init"); err != nil {
35
-		return "", errors.Wrapf(err, "failed to init repo at %s: %s", root, out)
36
-	}
37
-
38
-	ref, subdir := getRefAndSubdir(u.Fragment)
39
-	fetch := fetchArgs(u, ref)
40
-
41
-	u.Fragment = ""
42
-
43
-	// Add origin remote for compatibility with previous implementation that
44
-	// used "git clone" and also to make sure local refs are created for branches
45
-	if out, err := gitWithinDir(root, "remote", "add", "origin", u.String()); err != nil {
46
-		return "", errors.Wrapf(err, "failed add origin repo at %s: %s", u.String(), out)
47
-	}
48
-
49
-	if output, err := gitWithinDir(root, fetch...); err != nil {
50
-		return "", errors.Wrapf(err, "error fetching: %s", output)
51
-	}
52
-
53
-	return checkoutGit(root, ref, subdir)
54
-}
55
-
56
-func getRefAndSubdir(fragment string) (ref string, subdir string) {
57
-	refAndDir := strings.SplitN(fragment, ":", 2)
58
-	ref = "master"
59
-	if len(refAndDir[0]) != 0 {
60
-		ref = refAndDir[0]
61
-	}
62
-	if len(refAndDir) > 1 && len(refAndDir[1]) != 0 {
63
-		subdir = refAndDir[1]
64
-	}
65
-	return
66
-}
67
-
68
-func fetchArgs(remoteURL *url.URL, ref string) []string {
69
-	args := []string{"fetch", "--recurse-submodules=yes"}
70
-	shallow := true
71
-
72
-	if strings.HasPrefix(remoteURL.Scheme, "http") {
73
-		res, err := http.Head(fmt.Sprintf("%s/info/refs?service=git-upload-pack", remoteURL))
74
-		if err != nil || res.Header.Get("Content-Type") != "application/x-git-upload-pack-advertisement" {
75
-			shallow = false
76
-		}
77
-	}
78
-
79
-	if shallow {
80
-		args = append(args, "--depth", "1")
81
-	}
82
-
83
-	return append(args, "origin", ref)
84
-}
85
-
86
-func checkoutGit(root, ref, subdir string) (string, error) {
87
-	// Try checking out by ref name first. This will work on branches and sets
88
-	// .git/HEAD to the current branch name
89
-	if output, err := gitWithinDir(root, "checkout", ref); err != nil {
90
-		// If checking out by branch name fails check out the last fetched ref
91
-		if _, err2 := gitWithinDir(root, "checkout", "FETCH_HEAD"); err2 != nil {
92
-			return "", errors.Wrapf(err, "error checking out %s: %s", ref, output)
93
-		}
94
-	}
95
-
96
-	if subdir != "" {
97
-		newCtx, err := symlink.FollowSymlinkInScope(filepath.Join(root, subdir), root)
98
-		if err != nil {
99
-			return "", errors.Wrapf(err, "error setting git context, %q not within git root", subdir)
100
-		}
101
-
102
-		fi, err := os.Stat(newCtx)
103
-		if err != nil {
104
-			return "", err
105
-		}
106
-		if !fi.IsDir() {
107
-			return "", errors.Errorf("error setting git context, not a directory: %s", newCtx)
108
-		}
109
-		root = newCtx
110
-	}
111
-
112
-	return root, nil
113
-}
114
-
115
-func gitWithinDir(dir string, args ...string) ([]byte, error) {
116
-	a := []string{"--work-tree", dir, "--git-dir", filepath.Join(dir, ".git")}
117
-	return git(append(a, args...)...)
118
-}
119
-
120
-func git(args ...string) ([]byte, error) {
121
-	return exec.Command("git", args...).CombinedOutput()
122
-}
123 1
deleted file mode 100644
... ...
@@ -1,210 +0,0 @@
1
-package gitutils
2
-
3
-import (
4
-	"fmt"
5
-	"io/ioutil"
6
-	"net/http"
7
-	"net/http/httptest"
8
-	"net/url"
9
-	"os"
10
-	"path/filepath"
11
-	"reflect"
12
-	"runtime"
13
-	"strings"
14
-	"testing"
15
-)
16
-
17
-func TestCloneArgsSmartHttp(t *testing.T) {
18
-	mux := http.NewServeMux()
19
-	server := httptest.NewServer(mux)
20
-	serverURL, _ := url.Parse(server.URL)
21
-
22
-	serverURL.Path = "/repo.git"
23
-
24
-	mux.HandleFunc("/repo.git/info/refs", func(w http.ResponseWriter, r *http.Request) {
25
-		q := r.URL.Query().Get("service")
26
-		w.Header().Set("Content-Type", fmt.Sprintf("application/x-%s-advertisement", q))
27
-	})
28
-
29
-	args := fetchArgs(serverURL, "master")
30
-	exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"}
31
-	if !reflect.DeepEqual(args, exp) {
32
-		t.Fatalf("Expected %v, got %v", exp, args)
33
-	}
34
-}
35
-
36
-func TestCloneArgsDumbHttp(t *testing.T) {
37
-	mux := http.NewServeMux()
38
-	server := httptest.NewServer(mux)
39
-	serverURL, _ := url.Parse(server.URL)
40
-
41
-	serverURL.Path = "/repo.git"
42
-
43
-	mux.HandleFunc("/repo.git/info/refs", func(w http.ResponseWriter, r *http.Request) {
44
-		w.Header().Set("Content-Type", "text/plain")
45
-	})
46
-
47
-	args := fetchArgs(serverURL, "master")
48
-	exp := []string{"fetch", "--recurse-submodules=yes", "origin", "master"}
49
-	if !reflect.DeepEqual(args, exp) {
50
-		t.Fatalf("Expected %v, got %v", exp, args)
51
-	}
52
-}
53
-
54
-func TestCloneArgsGit(t *testing.T) {
55
-	u, _ := url.Parse("git://github.com/docker/docker")
56
-	args := fetchArgs(u, "master")
57
-	exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"}
58
-	if !reflect.DeepEqual(args, exp) {
59
-		t.Fatalf("Expected %v, got %v", exp, args)
60
-	}
61
-}
62
-
63
-func gitGetConfig(name string) string {
64
-	b, err := git([]string{"config", "--get", name}...)
65
-	if err != nil {
66
-		// since we are interested in empty or non empty string,
67
-		// we can safely ignore the err here.
68
-		return ""
69
-	}
70
-	return strings.TrimSpace(string(b))
71
-}
72
-
73
-func TestCheckoutGit(t *testing.T) {
74
-	root, err := ioutil.TempDir("", "docker-build-git-checkout")
75
-	if err != nil {
76
-		t.Fatal(err)
77
-	}
78
-	defer os.RemoveAll(root)
79
-
80
-	autocrlf := gitGetConfig("core.autocrlf")
81
-	if !(autocrlf == "true" || autocrlf == "false" ||
82
-		autocrlf == "input" || autocrlf == "") {
83
-		t.Logf("unknown core.autocrlf value: \"%s\"", autocrlf)
84
-	}
85
-	eol := "\n"
86
-	if autocrlf == "true" {
87
-		eol = "\r\n"
88
-	}
89
-
90
-	gitDir := filepath.Join(root, "repo")
91
-	_, err = git("init", gitDir)
92
-	if err != nil {
93
-		t.Fatal(err)
94
-	}
95
-
96
-	if _, err = gitWithinDir(gitDir, "config", "user.email", "test@docker.com"); err != nil {
97
-		t.Fatal(err)
98
-	}
99
-
100
-	if _, err = gitWithinDir(gitDir, "config", "user.name", "Docker test"); err != nil {
101
-		t.Fatal(err)
102
-	}
103
-
104
-	if err = ioutil.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte("FROM scratch"), 0644); err != nil {
105
-		t.Fatal(err)
106
-	}
107
-
108
-	subDir := filepath.Join(gitDir, "subdir")
109
-	if err = os.Mkdir(subDir, 0755); err != nil {
110
-		t.Fatal(err)
111
-	}
112
-
113
-	if err = ioutil.WriteFile(filepath.Join(subDir, "Dockerfile"), []byte("FROM scratch\nEXPOSE 5000"), 0644); err != nil {
114
-		t.Fatal(err)
115
-	}
116
-
117
-	if runtime.GOOS != "windows" {
118
-		if err = os.Symlink("../subdir", filepath.Join(gitDir, "parentlink")); err != nil {
119
-			t.Fatal(err)
120
-		}
121
-
122
-		if err = os.Symlink("/subdir", filepath.Join(gitDir, "absolutelink")); err != nil {
123
-			t.Fatal(err)
124
-		}
125
-	}
126
-
127
-	if _, err = gitWithinDir(gitDir, "add", "-A"); err != nil {
128
-		t.Fatal(err)
129
-	}
130
-
131
-	if _, err = gitWithinDir(gitDir, "commit", "-am", "First commit"); err != nil {
132
-		t.Fatal(err)
133
-	}
134
-
135
-	if _, err = gitWithinDir(gitDir, "checkout", "-b", "test"); err != nil {
136
-		t.Fatal(err)
137
-	}
138
-
139
-	if err = ioutil.WriteFile(filepath.Join(gitDir, "Dockerfile"), []byte("FROM scratch\nEXPOSE 3000"), 0644); err != nil {
140
-		t.Fatal(err)
141
-	}
142
-
143
-	if err = ioutil.WriteFile(filepath.Join(subDir, "Dockerfile"), []byte("FROM busybox\nEXPOSE 5000"), 0644); err != nil {
144
-		t.Fatal(err)
145
-	}
146
-
147
-	if _, err = gitWithinDir(gitDir, "add", "-A"); err != nil {
148
-		t.Fatal(err)
149
-	}
150
-
151
-	if _, err = gitWithinDir(gitDir, "commit", "-am", "Branch commit"); err != nil {
152
-		t.Fatal(err)
153
-	}
154
-
155
-	if _, err = gitWithinDir(gitDir, "checkout", "master"); err != nil {
156
-		t.Fatal(err)
157
-	}
158
-
159
-	type singleCase struct {
160
-		frag string
161
-		exp  string
162
-		fail bool
163
-	}
164
-
165
-	cases := []singleCase{
166
-		{"", "FROM scratch", false},
167
-		{"master", "FROM scratch", false},
168
-		{":subdir", "FROM scratch" + eol + "EXPOSE 5000", false},
169
-		{":nosubdir", "", true},   // missing directory error
170
-		{":Dockerfile", "", true}, // not a directory error
171
-		{"master:nosubdir", "", true},
172
-		{"master:subdir", "FROM scratch" + eol + "EXPOSE 5000", false},
173
-		{"master:../subdir", "", true},
174
-		{"test", "FROM scratch" + eol + "EXPOSE 3000", false},
175
-		{"test:", "FROM scratch" + eol + "EXPOSE 3000", false},
176
-		{"test:subdir", "FROM busybox" + eol + "EXPOSE 5000", false},
177
-	}
178
-
179
-	if runtime.GOOS != "windows" {
180
-		// Windows GIT (2.7.1 x64) does not support parentlink/absolutelink. Sample output below
181
-		// 	git --work-tree .\repo --git-dir .\repo\.git add -A
182
-		//	error: readlink("absolutelink"): Function not implemented
183
-		// 	error: unable to index file absolutelink
184
-		// 	fatal: adding files failed
185
-		cases = append(cases, singleCase{frag: "master:absolutelink", exp: "FROM scratch" + eol + "EXPOSE 5000", fail: false})
186
-		cases = append(cases, singleCase{frag: "master:parentlink", exp: "FROM scratch" + eol + "EXPOSE 5000", fail: false})
187
-	}
188
-
189
-	for _, c := range cases {
190
-		ref, subdir := getRefAndSubdir(c.frag)
191
-		r, err := checkoutGit(gitDir, ref, subdir)
192
-
193
-		fail := err != nil
194
-		if fail != c.fail {
195
-			t.Fatalf("Expected %v failure, error was %v\n", c.fail, err)
196
-		}
197
-		if c.fail {
198
-			continue
199
-		}
200
-
201
-		b, err := ioutil.ReadFile(filepath.Join(r, "Dockerfile"))
202
-		if err != nil {
203
-			t.Fatal(err)
204
-		}
205
-
206
-		if string(b) != c.exp {
207
-			t.Fatalf("Expected %v, was %v\n", c.exp, string(b))
208
-		}
209
-	}
210
-}