Skip to content

Commit

Permalink
Merge pull request #1477 from crazy-max/git-wsl
Browse files Browse the repository at this point in the history
build: lookup the right git binary on WSL
  • Loading branch information
tonistiigi authored Dec 16, 2022
2 parents fbbe1c1 + 551b8f6 commit 64e4c19
Show file tree
Hide file tree
Showing 23 changed files with 1,058 additions and 111 deletions.
11 changes: 7 additions & 4 deletions build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,10 +594,6 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
so.FrontendAttrs["attest:provenance"] = "mode=min,inline-only=true"
}

for k, v := range getGitAttributes(ctx, opt.Inputs.ContextPath, opt.Inputs.DockerfilePath) {
so.FrontendAttrs[k] = v
}

// set platforms
if len(opt.Platforms) != 0 {
pp := make([]string, len(opt.Platforms))
Expand Down Expand Up @@ -852,6 +848,10 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
for k, opt := range opt {
multiDriver := len(m[k]) > 1
hasMobyDriver := false
gitattrs, err := getGitAttributes(ctx, opt.Inputs.ContextPath, opt.Inputs.DockerfilePath)
if err != nil {
logrus.Warn(err)
}
for i, np := range m[k] {
node := nodes[np.driverIndex]
if node.Driver.IsMobyDriver() {
Expand All @@ -861,6 +861,9 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
so, release, err := toSolveOpt(ctx, node, multiDriver, opt, np.bopts, configDir, w, func(name string) (io.WriteCloser, func(), error) {
return docker.LoadImage(ctx, name, w)
})
for k, v := range gitattrs {
so.FrontendAttrs[k] = v
}
if err != nil {
return nil, err
}
Expand Down
72 changes: 37 additions & 35 deletions build/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ package build
import (
"context"
"os"
"path"
"path/filepath"
"strconv"
"strings"

"github.com/docker/buildx/util/gitutil"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/sirupsen/logrus"
"github.com/pkg/errors"
)

const DockerfileLabel = "com.docker.image.source.entrypoint"

func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath string) (res map[string]string) {
func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath string) (res map[string]string, _ error) {
res = make(map[string]string)
if contextPath == "" {
return
Expand Down Expand Up @@ -48,27 +49,50 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
wd, _ = filepath.Abs(filepath.Join(cwd, contextPath))
}

gitc := gitutil.New(gitutil.WithContext(ctx), gitutil.WithWorkingDir(wd))
if !gitc.IsInsideWorkTree() {
logrus.Warnf("Unable to determine Git information")
gitc, err := gitutil.New(gitutil.WithContext(ctx), gitutil.WithWorkingDir(wd))
if err != nil {
if st, err := os.Stat(path.Join(wd, ".git")); err == nil && st.IsDir() {
return res, errors.New("git was not found in the system. Current commit information was not captured by the build")
}
return
}

var resRevision, resSource, resDockerfilePath string
if !gitc.IsInsideWorkTree() {
if st, err := os.Stat(path.Join(wd, ".git")); err == nil && st.IsDir() {
return res, errors.New("failed to read current commit information with git rev-parse --is-inside-work-tree")
}
return res, nil
}

if sha, err := gitc.FullCommit(); err == nil && sha != "" {
resRevision = sha
if sha, err := gitc.FullCommit(); err != nil {
return res, errors.Wrapf(err, "failed to get git commit")
} else if sha != "" {
if gitc.IsDirty() {
resRevision += "-dirty"
sha += "-dirty"
}
if setGitLabels {
res["label:"+specs.AnnotationRevision] = sha
}
if setGitInfo {
res["vcs:revision"] = sha
}
}

if rurl, err := gitc.RemoteURL(); err == nil && rurl != "" {
resSource = rurl
if rurl, err := gitc.RemoteURL(); err != nil {
return res, errors.Wrapf(err, "failed to get git remote url")
} else if rurl != "" {
if setGitLabels {
res["label:"+specs.AnnotationSource] = rurl
}
if setGitInfo {
res["vcs:source"] = rurl
}
}

if setGitLabels {
if root, err := gitc.RootDir(); err == nil && root != "" {
if root, err := gitc.RootDir(); err != nil {
return res, errors.Wrapf(err, "failed to get git root dir")
} else if root != "" {
if dockerfilePath == "" {
dockerfilePath = filepath.Join(wd, "Dockerfile")
}
Expand All @@ -78,32 +102,10 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
}
dockerfilePath, _ = filepath.Rel(root, dockerfilePath)
if !strings.HasPrefix(dockerfilePath, "..") {
resDockerfilePath = dockerfilePath
res["label:"+DockerfileLabel] = dockerfilePath
}
}
}

if resSource != "" {
if setGitLabels {
res["label:"+specs.AnnotationSource] = resSource
}
if setGitInfo {
res["vcs:source"] = resSource
}
}
if resRevision != "" {
if setGitLabels {
res["label:"+specs.AnnotationRevision] = resRevision
}
if setGitInfo {
res["vcs:revision"] = resRevision
}
}
if resDockerfilePath != "" {
if setGitLabels {
res["label:"+DockerfileLabel] = resDockerfilePath
}
}

return
}
73 changes: 45 additions & 28 deletions build/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,50 @@ package build
import (
"context"
"os"
"path"
"path/filepath"
"strings"
"testing"

"github.com/docker/buildx/util/gitutil"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func setupTest(tb testing.TB) {
gitutil.Mktmp(tb)
gitutil.GitInit(tb)

c, err := gitutil.New()
require.NoError(tb, err)
gitutil.GitInit(c, tb)

df := []byte("FROM alpine:latest\n")
assert.NoError(tb, os.WriteFile("Dockerfile", df, 0644))
gitutil.GitAdd(tb, "Dockerfile")
gitutil.GitCommit(tb, "initial commit")

gitutil.GitAdd(c, tb, "Dockerfile")
gitutil.GitCommit(c, tb, "initial commit")
gitutil.GitSetRemote(c, tb, "git@github.com:docker/buildx.git")
}

func TestGetGitAttributesNotGitRepo(t *testing.T) {
_, err := getGitAttributes(context.Background(), t.TempDir(), "Dockerfile")
assert.NoError(t, err)
}

func TestGetGitAttributesBadGitRepo(t *testing.T) {
tmp := t.TempDir()
require.NoError(t, os.MkdirAll(path.Join(tmp, ".git"), 0755))

_, err := getGitAttributes(context.Background(), tmp, "Dockerfile")
assert.Error(t, err)
}

func TestGetGitAttributesNoContext(t *testing.T) {
setupTest(t)

gitattrs := getGitAttributes(context.Background(), "", "Dockerfile")
gitattrs, err := getGitAttributes(context.Background(), "", "Dockerfile")
assert.NoError(t, err)
assert.Empty(t, gitattrs)
}

Expand All @@ -41,6 +63,7 @@ func TestGetGitAttributes(t *testing.T) {
envGitInfo: "",
expected: []string{
"vcs:revision",
"vcs:source",
},
},
{
Expand All @@ -55,6 +78,7 @@ func TestGetGitAttributes(t *testing.T) {
envGitInfo: "true",
expected: []string{
"vcs:revision",
"vcs:source",
},
},
{
Expand All @@ -64,6 +88,7 @@ func TestGetGitAttributes(t *testing.T) {
expected: []string{
"label:" + DockerfileLabel,
"label:" + specs.AnnotationRevision,
"label:" + specs.AnnotationSource,
},
},
{
Expand All @@ -73,7 +98,9 @@ func TestGetGitAttributes(t *testing.T) {
expected: []string{
"label:" + DockerfileLabel,
"label:" + specs.AnnotationRevision,
"label:" + specs.AnnotationSource,
"vcs:revision",
"vcs:source",
},
},
}
Expand All @@ -87,52 +114,42 @@ func TestGetGitAttributes(t *testing.T) {
if tt.envGitInfo != "" {
t.Setenv("BUILDX_GIT_INFO", tt.envGitInfo)
}
gitattrs := getGitAttributes(context.Background(), ".", "Dockerfile")
gitattrs, err := getGitAttributes(context.Background(), ".", "Dockerfile")
require.NoError(t, err)
for _, e := range tt.expected {
assert.Contains(t, gitattrs, e)
assert.NotEmpty(t, gitattrs[e])
if e == "label:"+DockerfileLabel {
assert.Equal(t, "Dockerfile", gitattrs[e])
} else if e == "label:"+specs.AnnotationSource || e == "vcs:source" {
assert.Equal(t, "git@github.com:docker/buildx.git", gitattrs[e])
}
}
})
}
}

func TestGetGitAttributesWithRemote(t *testing.T) {
setupTest(t)
gitutil.GitSetRemote(t, "git@github.com:docker/buildx.git")

t.Setenv("BUILDX_GIT_LABELS", "true")
gitattrs := getGitAttributes(context.Background(), ".", "Dockerfile")
assert.Equal(t, 5, len(gitattrs))
assert.Contains(t, gitattrs, "label:"+DockerfileLabel)
assert.Equal(t, "Dockerfile", gitattrs["label:"+DockerfileLabel])
assert.Contains(t, gitattrs, "label:"+specs.AnnotationRevision)
assert.NotEmpty(t, gitattrs["label:"+specs.AnnotationRevision])
assert.Contains(t, gitattrs, "label:"+specs.AnnotationSource)
assert.Equal(t, "git@github.com:docker/buildx.git", gitattrs["label:"+specs.AnnotationSource])
assert.Contains(t, gitattrs, "vcs:revision")
assert.NotEmpty(t, gitattrs["vcs:revision"])
assert.Contains(t, gitattrs, "vcs:source")
assert.Equal(t, "git@github.com:docker/buildx.git", gitattrs["vcs:source"])
}

func TestGetGitAttributesDirty(t *testing.T) {
setupTest(t)

// make a change to test dirty flag
df := []byte("FROM alpine:edge\n")
assert.NoError(t, os.Mkdir("dir", 0755))
assert.NoError(t, os.WriteFile(filepath.Join("dir", "Dockerfile"), df, 0644))
require.NoError(t, os.Mkdir("dir", 0755))
require.NoError(t, os.WriteFile(filepath.Join("dir", "Dockerfile"), df, 0644))

t.Setenv("BUILDX_GIT_LABELS", "true")
gitattrs := getGitAttributes(context.Background(), ".", "Dockerfile")
assert.Equal(t, 3, len(gitattrs))
gitattrs, _ := getGitAttributes(context.Background(), ".", "Dockerfile")
assert.Equal(t, 5, len(gitattrs))

assert.Contains(t, gitattrs, "label:"+DockerfileLabel)
assert.Equal(t, "Dockerfile", gitattrs["label:"+DockerfileLabel])
assert.Contains(t, gitattrs, "label:"+specs.AnnotationSource)
assert.Equal(t, "git@github.com:docker/buildx.git", gitattrs["label:"+specs.AnnotationSource])
assert.Contains(t, gitattrs, "label:"+specs.AnnotationRevision)
assert.True(t, strings.HasSuffix(gitattrs["label:"+specs.AnnotationRevision], "-dirty"))

assert.Contains(t, gitattrs, "vcs:source")
assert.Equal(t, "git@github.com:docker/buildx.git", gitattrs["vcs:source"])
assert.Contains(t, gitattrs, "vcs:revision")
assert.True(t, strings.HasSuffix(gitattrs["vcs:revision"], "-dirty"))
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ require (
github.com/hashicorp/go-cty-funcs v0.0.0-20200930094925-2721b1e36840
github.com/hashicorp/hcl/v2 v2.8.2
github.com/moby/buildkit v0.11.0-rc1.0.20221213193744-862b22d7e7cf
github.com/moby/sys/mountinfo v0.6.2
github.com/morikuni/aec v1.0.0
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.3-0.20220303224323-02efb9a75ee1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
Expand Down Expand Up @@ -780,6 +781,7 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
42 changes: 42 additions & 0 deletions util/gitutil/gitpath_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//go:build !windows
// +build !windows

package gitutil

import (
"os"
"os/exec"
"path/filepath"

"github.com/moby/sys/mountinfo"
)

func gitPath(wd string) (string, error) {
// On WSL2 we need to check if the current working directory is mounted on
// a Windows drive and if so, we need to use the Windows git executable.
if os.Getenv("WSL_DISTRO_NAME") != "" && wd != "" {
// ensure any symlinks are resolved
wdPath, err := filepath.EvalSymlinks(wd)
if err != nil {
return "", err
}
mi, err := mountinfo.GetMounts(mountinfo.ParentsFilter(wdPath))
if err != nil {
return "", err
}
// find the longest mount point
var idx, maxlen int
for i := range mi {
if len(mi[i].Mountpoint) > maxlen {
maxlen = len(mi[i].Mountpoint)
idx = i
}
}
if mi[idx].FSType == "9p" {
if p, err := exec.LookPath("git.exe"); err == nil {
return p, nil
}
}
}
return exec.LookPath("git")
}
9 changes: 9 additions & 0 deletions util/gitutil/gitpath_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package gitutil

import (
"os/exec"
)

func gitPath(wd string) (string, error) {
return exec.LookPath("git.exe")
}
Loading

0 comments on commit 64e4c19

Please sign in to comment.