Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gitutils: fix checking out submodules #35737

Merged
merged 2 commits into from Jan 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 24 additions & 2 deletions builder/remotecontext/git/gitutils.go
Expand Up @@ -29,13 +29,23 @@ func Clone(remoteURL string) (string, error) {
return "", err
}

return cloneGitRepo(repo)
}

func cloneGitRepo(repo gitRepo) (checkoutDir string, err error) {
fetch := fetchArgs(repo.remote, repo.ref)

root, err := ioutil.TempDir("", "docker-build-git")
if err != nil {
return "", err
}

defer func() {
if err != nil {
os.RemoveAll(root)
}
}()

if out, err := gitWithinDir(root, "init"); err != nil {
return "", errors.Wrapf(err, "failed to init repo at %s: %s", root, out)
}
Expand All @@ -50,7 +60,19 @@ func Clone(remoteURL string) (string, error) {
return "", errors.Wrapf(err, "error fetching: %s", output)
}

return checkoutGit(root, repo.ref, repo.subdir)
checkoutDir, err = checkoutGit(root, repo.ref, repo.subdir)
if err != nil {
return "", err
}

cmd := exec.Command("git", "submodule", "update", "--init", "--recursive", "--depth=1")
cmd.Dir = root
output, err := cmd.CombinedOutput()
if err != nil {
return "", errors.Wrapf(err, "error initializing submodules: %s", output)
}

return checkoutDir, nil
}

func parseRemoteURL(remoteURL string) (gitRepo, error) {
Expand Down Expand Up @@ -96,7 +118,7 @@ func getRefAndSubdir(fragment string) (ref string, subdir string) {
}

func fetchArgs(remoteURL string, ref string) []string {
args := []string{"fetch", "--recurse-submodules=yes"}
args := []string{"fetch"}

if supportsShallowClone(remoteURL) {
args = append(args, "--depth", "1")
Expand Down
79 changes: 61 additions & 18 deletions builder/remotecontext/git/gitutils_test.go
Expand Up @@ -7,6 +7,7 @@ import (
"net/http/httptest"
"net/url"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
Expand Down Expand Up @@ -61,7 +62,7 @@ func TestCloneArgsSmartHttp(t *testing.T) {
})

args := fetchArgs(serverURL.String(), "master")
exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"}
exp := []string{"fetch", "--depth", "1", "origin", "master"}
assert.Equal(t, exp, args)
}

Expand All @@ -77,13 +78,13 @@ func TestCloneArgsDumbHttp(t *testing.T) {
})

args := fetchArgs(serverURL.String(), "master")
exp := []string{"fetch", "--recurse-submodules=yes", "origin", "master"}
exp := []string{"fetch", "origin", "master"}
assert.Equal(t, exp, args)
}

func TestCloneArgsGit(t *testing.T) {
args := fetchArgs("git://github.com/docker/docker", "master")
exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"}
exp := []string{"fetch", "--depth", "1", "origin", "master"}
assert.Equal(t, exp, args)
}

Expand Down Expand Up @@ -165,24 +166,55 @@ func TestCheckoutGit(t *testing.T) {
_, err = gitWithinDir(gitDir, "checkout", "master")
require.NoError(t, err)

// set up submodule
subrepoDir := filepath.Join(root, "subrepo")
_, err = git("init", subrepoDir)
require.NoError(t, err)

_, err = gitWithinDir(subrepoDir, "config", "user.email", "test@docker.com")
require.NoError(t, err)

_, err = gitWithinDir(subrepoDir, "config", "user.name", "Docker test")
require.NoError(t, err)

err = ioutil.WriteFile(filepath.Join(subrepoDir, "subfile"), []byte("subcontents"), 0644)
require.NoError(t, err)

_, err = gitWithinDir(subrepoDir, "add", "-A")
require.NoError(t, err)

_, err = gitWithinDir(subrepoDir, "commit", "-am", "Subrepo initial")
require.NoError(t, err)

cmd := exec.Command("git", "submodule", "add", subrepoDir, "sub") // this command doesn't work with --work-tree
cmd.Dir = gitDir
require.NoError(t, cmd.Run())

_, err = gitWithinDir(gitDir, "add", "-A")
require.NoError(t, err)

_, err = gitWithinDir(gitDir, "commit", "-am", "With submodule")
require.NoError(t, err)

type singleCase struct {
frag string
exp string
fail bool
frag string
exp string
fail bool
submodule bool
}

cases := []singleCase{
{"", "FROM scratch", false},
{"master", "FROM scratch", false},
{":subdir", "FROM scratch" + eol + "EXPOSE 5000", false},
{":nosubdir", "", true}, // missing directory error
{":Dockerfile", "", true}, // not a directory error
{"master:nosubdir", "", true},
{"master:subdir", "FROM scratch" + eol + "EXPOSE 5000", false},
{"master:../subdir", "", true},
{"test", "FROM scratch" + eol + "EXPOSE 3000", false},
{"test:", "FROM scratch" + eol + "EXPOSE 3000", false},
{"test:subdir", "FROM busybox" + eol + "EXPOSE 5000", false},
{"", "FROM scratch", false, true},
{"master", "FROM scratch", false, true},
{":subdir", "FROM scratch" + eol + "EXPOSE 5000", false, false},
{":nosubdir", "", true, false}, // missing directory error
{":Dockerfile", "", true, false}, // not a directory error
{"master:nosubdir", "", true, false},
{"master:subdir", "FROM scratch" + eol + "EXPOSE 5000", false, false},
{"master:../subdir", "", true, false},
{"test", "FROM scratch" + eol + "EXPOSE 3000", false, false},
{"test:", "FROM scratch" + eol + "EXPOSE 3000", false, false},
{"test:subdir", "FROM busybox" + eol + "EXPOSE 5000", false, false},
}

if runtime.GOOS != "windows" {
Expand All @@ -197,12 +229,23 @@ func TestCheckoutGit(t *testing.T) {

for _, c := range cases {
ref, subdir := getRefAndSubdir(c.frag)
r, err := checkoutGit(gitDir, ref, subdir)
r, err := cloneGitRepo(gitRepo{remote: gitDir, ref: ref, subdir: subdir})

if c.fail {
assert.Error(t, err)
continue
}
require.NoError(t, err)
defer os.RemoveAll(r)
if c.submodule {
b, err := ioutil.ReadFile(filepath.Join(r, "sub/subfile"))
require.NoError(t, err)
assert.Equal(t, "subcontents", string(b))
} else {
_, err := os.Stat(filepath.Join(r, "sub/subfile"))
require.Error(t, err)
require.True(t, os.IsNotExist(err))
}

b, err := ioutil.ReadFile(filepath.Join(r, "Dockerfile"))
require.NoError(t, err)
Expand Down