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

build: lookup the right git binary on WSL #1477

Merged
merged 3 commits into from
Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions build/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,14 @@ 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))
gitc, err := gitutil.New(gitutil.WithContext(ctx), gitutil.WithWorkingDir(wd))
if err != nil {
logrus.Warnf("Failed to initialize git: %v", err)
crazy-max marked this conversation as resolved.
Show resolved Hide resolved
return
}

if !gitc.IsInsideWorkTree() {
crazy-max marked this conversation as resolved.
Show resolved Hide resolved
logrus.Warnf("Unable to determine Git information")
logrus.Warnf("Unable to determine git information")
return
}

Expand Down
21 changes: 12 additions & 9 deletions build/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,20 @@ import (
"github.com/stretchr/testify/assert"
)

func setupTest(tb testing.TB) {
func setupTest(tb testing.TB) *gitutil.Git {
c, err := gitutil.New()
assert.NoError(tb, err)
gitutil.Mktmp(tb)
gitutil.GitInit(tb)
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")
return c
}

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

gitattrs := getGitAttributes(context.Background(), "", "Dockerfile")
assert.Empty(t, gitattrs)
Expand Down Expand Up @@ -80,7 +83,7 @@ func TestGetGitAttributes(t *testing.T) {
for _, tt := range cases {
tt := tt
t.Run(tt.name, func(t *testing.T) {
setupTest(t)
_ = setupTest(t)
if tt.envGitLabels != "" {
t.Setenv("BUILDX_GIT_LABELS", tt.envGitLabels)
}
Expand All @@ -100,8 +103,8 @@ func TestGetGitAttributes(t *testing.T) {
}

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

t.Setenv("BUILDX_GIT_LABELS", "true")
gitattrs := getGitAttributes(context.Background(), ".", "Dockerfile")
Expand All @@ -119,7 +122,7 @@ func TestGetGitAttributesWithRemote(t *testing.T) {
}

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

// make a change to test dirty flag
df := []byte("FROM alpine:edge\n")
Expand Down
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")
}
23 changes: 14 additions & 9 deletions util/gitutil/gitutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import (

// Git represents an active git object
type Git struct {
ctx context.Context
wd string
ctx context.Context
wd string
gitpath string
}

// Option provides a variadic option for configuring the git client.
Expand All @@ -33,14 +34,22 @@ func WithWorkingDir(wd string) Option {
}

// New initializes a new git client
func New(opts ...Option) *Git {
func New(opts ...Option) (*Git, error) {
var err error
c := &Git{
ctx: context.Background(),
}

for _, opt := range opts {
opt(c)
}
return c

c.gitpath, err = gitPath(c.wd)
if err != nil {
return nil, errors.New("git not found in PATH")
}

return c, nil
}

func (c *Git) IsInsideWorkTree() bool {
Expand Down Expand Up @@ -89,16 +98,12 @@ func (c *Git) Tag() (string, error) {
}

func (c *Git) run(args ...string) (string, error) {
if _, err := exec.LookPath("git"); err != nil {
return "", errors.New("git not present in PATH")
}

var extraArgs = []string{
"-c", "log.showSignature=false",
}

args = append(extraArgs, args...)
cmd := exec.Command("git", args...)
cmd := exec.CommandContext(c.ctx, c.gitpath, args...)
if c.wd != "" {
cmd.Dir = c.wd
}
Expand Down
49 changes: 30 additions & 19 deletions util/gitutil/gitutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package gitutil
import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestGit(t *testing.T) {
c := New()
c, err := New()
assert.NoError(t, err)

out, err := c.run("status")
require.NoError(t, err)
require.NotEmpty(t, out)
Expand All @@ -19,50 +22,58 @@ func TestGit(t *testing.T) {
}

func TestGitFullCommit(t *testing.T) {
c, err := New()
assert.NoError(t, err)

Mktmp(t)
GitInit(t)
GitCommit(t, "bar")
GitInit(c, t)
GitCommit(c, t, "bar")

c := New()
out, err := c.FullCommit()
require.NoError(t, err)
require.Equal(t, 40, len(out))
}

func TestGitShortCommit(t *testing.T) {
c, err := New()
assert.NoError(t, err)

Mktmp(t)
GitInit(t)
GitCommit(t, "bar")
GitInit(c, t)
GitCommit(c, t, "bar")

c := New()
out, err := c.ShortCommit()
require.NoError(t, err)
require.Equal(t, 7, len(out))
}

func TestGitTagsPointsAt(t *testing.T) {
c, err := New()
assert.NoError(t, err)

Mktmp(t)
GitInit(t)
GitCommit(t, "bar")
GitTag(t, "v0.8.0")
GitCommit(t, "foo")
GitTag(t, "v0.9.0")
GitInit(c, t)
GitCommit(c, t, "bar")
GitTag(c, t, "v0.8.0")
GitCommit(c, t, "foo")
GitTag(c, t, "v0.9.0")

c := New()
out, err := c.clean(c.run("tag", "--points-at", "HEAD", "--sort", "-version:creatordate"))
require.NoError(t, err)
require.Equal(t, "v0.9.0", out)
}

func TestGitDescribeTags(t *testing.T) {
c, err := New()
assert.NoError(t, err)

Mktmp(t)
GitInit(t)
GitCommit(t, "bar")
GitTag(t, "v0.8.0")
GitCommit(t, "foo")
GitTag(t, "v0.9.0")
GitInit(c, t)
GitCommit(c, t, "bar")
GitTag(c, t, "v0.8.0")
GitCommit(c, t, "foo")
GitTag(c, t, "v0.9.0")

c := New()
out, err := c.clean(c.run("describe", "--tags", "--abbrev=0"))
require.NoError(t, err)
require.Equal(t, "v0.9.0", out)
Expand Down
31 changes: 15 additions & 16 deletions util/gitutil/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,46 @@ import (
"github.com/stretchr/testify/require"
)

func GitInit(tb testing.TB) {
func GitInit(c *Git, tb testing.TB) {
tb.Helper()
out, err := fakeGit("init")
out, err := fakeGit(c, "init")
require.NoError(tb, err)
require.Contains(tb, out, "Initialized empty Git repository")
require.NoError(tb, err)
GitCheckoutBranch(tb, "main")
_, _ = fakeGit("branch", "-D", "master")
GitCheckoutBranch(c, tb, "main")
_, _ = fakeGit(c, "branch", "-D", "master")
}

func GitCommit(tb testing.TB, msg string) {
func GitCommit(c *Git, tb testing.TB, msg string) {
tb.Helper()
out, err := fakeGit("commit", "--allow-empty", "-m", msg)
out, err := fakeGit(c, "commit", "--allow-empty", "-m", msg)
require.NoError(tb, err)
require.Contains(tb, out, "main", msg)
}

func GitTag(tb testing.TB, tag string) {
func GitTag(c *Git, tb testing.TB, tag string) {
tb.Helper()
out, err := fakeGit("tag", tag)
out, err := fakeGit(c, "tag", tag)
require.NoError(tb, err)
require.Empty(tb, out)
}

func GitCheckoutBranch(tb testing.TB, name string) {
func GitCheckoutBranch(c *Git, tb testing.TB, name string) {
tb.Helper()
out, err := fakeGit("checkout", "-b", name)
out, err := fakeGit(c, "checkout", "-b", name)
require.NoError(tb, err)
require.Empty(tb, out)
}

func GitAdd(tb testing.TB, file string) {
func GitAdd(c *Git, tb testing.TB, file string) {
tb.Helper()
_, err := fakeGit("add", file)
_, err := fakeGit(c, "add", file)
require.NoError(tb, err)
}

func GitSetRemote(tb testing.TB, url string) {
func GitSetRemote(c *Git, tb testing.TB, url string) {
tb.Helper()
_, err := fakeGit("remote", "add", "origin", url)
_, err := fakeGit(c, "remote", "add", "origin", url)
require.NoError(tb, err)
}

Expand All @@ -62,7 +62,7 @@ func Mktmp(tb testing.TB) string {
return folder
}

func fakeGit(args ...string) (string, error) {
func fakeGit(c *Git, args ...string) (string, error) {
allArgs := []string{
"-c", "user.name=buildx",
"-c", "user.email=buildx@docker.com",
Expand All @@ -71,6 +71,5 @@ func fakeGit(args ...string) (string, error) {
"-c", "log.showSignature=false",
}
allArgs = append(allArgs, args...)
c := New()
return c.clean(c.run(allArgs...))
}
Loading