diff --git a/frontend/dockerfile/dockerignore/dockerignore_deprecated.go b/frontend/dockerfile/dockerignore/dockerignore_deprecated.go new file mode 100644 index 000000000000..c30712bf5007 --- /dev/null +++ b/frontend/dockerfile/dockerignore/dockerignore_deprecated.go @@ -0,0 +1,14 @@ +package dockerignore + +import ( + "io" + + "github.com/moby/patternmatcher/ignorefile" +) + +// ReadAll is an alias for [ignorefile.ReadAll]. +// +// Deprecated: use [ignorefile.ReadAll] instead. +func ReadAll(reader io.Reader) ([]string, error) { + return ignorefile.ReadAll(reader) +} diff --git a/frontend/dockerfile/dockerignore/dockerignore_test.go b/frontend/dockerfile/dockerignore/dockerignore_test.go deleted file mode 100644 index c3cd07884cf8..000000000000 --- a/frontend/dockerfile/dockerignore/dockerignore_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package dockerignore - -import ( - "os" - "path/filepath" - "testing" -) - -func TestReadAll(t *testing.T) { - di, err := ReadAll(nil) - if err != nil { - t.Fatalf("Expected not to have error, got %v", err) - } - - if diLen := len(di); diLen != 0 { - t.Fatalf("Expected to have zero dockerignore entry, got %d", diLen) - } - - diName := filepath.Join(t.TempDir(), ".dockerignore") - content := "test1\n/test2\n/a/file/here\n\nlastfile\n# this is a comment\n! /inverted/abs/path\n!\n! \n" - err = os.WriteFile(diName, []byte(content), 0600) - if err != nil { - t.Fatal(err) - } - - diFd, err := os.Open(diName) - if err != nil { - t.Fatal(err) - } - defer diFd.Close() - - di, err = ReadAll(diFd) - if err != nil { - t.Fatal(err) - } - - if len(di) != 7 { - t.Fatalf("Expected 7 entries, got %v", len(di)) - } - if di[0] != "test1" { - t.Fatal("First element is not test1") - } - if di[1] != "test2" { // according to https://docs.docker.com/engine/reference/builder/#dockerignore-file, /foo/bar should be treated as foo/bar - t.Fatal("Second element is not test2") - } - if di[2] != "a/file/here" { // according to https://docs.docker.com/engine/reference/builder/#dockerignore-file, /foo/bar should be treated as foo/bar - t.Fatal("Third element is not a/file/here") - } - if di[3] != "lastfile" { - t.Fatal("Fourth element is not lastfile") - } - if di[4] != "!inverted/abs/path" { - t.Fatal("Fifth element is not !inverted/abs/path") - } - if di[5] != "!" { - t.Fatalf("Sixth element is not !, but %s", di[5]) - } - if di[6] != "!" { - t.Fatalf("Seventh element is not !, but %s", di[6]) - } -} diff --git a/frontend/dockerui/config.go b/frontend/dockerui/config.go index 12ec2c6880e0..0ae30245ed64 100644 --- a/frontend/dockerui/config.go +++ b/frontend/dockerui/config.go @@ -15,10 +15,10 @@ import ( "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/exporter/containerimage/image" "github.com/moby/buildkit/frontend/attestations" - "github.com/moby/buildkit/frontend/dockerfile/dockerignore" "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/flightcontrol" + "github.com/moby/patternmatcher/ignorefile" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" @@ -80,7 +80,8 @@ type Client struct { g flightcontrol.Group[*buildContext] bopts client.BuildOpts - dockerignore []byte + dockerignore []byte + dockerignoreName string } type SBOM struct { @@ -375,6 +376,7 @@ func (bc *Client) ReadEntrypoint(ctx context.Context, lang string, opts ...llb.L }) if err == nil { bc.dockerignore = dt + bc.dockerignoreName = bctx.filename + ".dockerignore" } return &Source{ @@ -435,13 +437,14 @@ func (bc *Client) MainContext(ctx context.Context, opts ...llb.LocalOption) (*ll dt = []byte{} } bc.dockerignore = dt + bc.dockerignoreName = DefaultDockerignoreName } var excludes []string if len(bc.dockerignore) != 0 { - excludes, err = dockerignore.ReadAll(bytes.NewBuffer(bc.dockerignore)) + excludes, err = ignorefile.ReadAll(bytes.NewBuffer(bc.dockerignore)) if err != nil { - return nil, errors.Wrap(err, "failed to parse dockerignore") + return nil, errors.Wrapf(err, "failed parsing %s", bc.dockerignoreName) } } diff --git a/frontend/dockerui/namedcontext.go b/frontend/dockerui/namedcontext.go index 6a441c50822e..dd44b7d8fe89 100644 --- a/frontend/dockerui/namedcontext.go +++ b/frontend/dockerui/namedcontext.go @@ -11,9 +11,9 @@ import ( "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/exporter/containerimage/image" - "github.com/moby/buildkit/frontend/dockerfile/dockerignore" "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/util/imageutil" + "github.com/moby/patternmatcher/ignorefile" "github.com/pkg/errors" ) @@ -206,9 +206,9 @@ func (bc *Client) namedContextRecursive(ctx context.Context, name string, nameWi }) // error ignored if len(dt) != 0 { - excludes, err = dockerignore.ReadAll(bytes.NewBuffer(dt)) + excludes, err = ignorefile.ReadAll(bytes.NewBuffer(dt)) if err != nil { - return nil, nil, err + return nil, nil, errors.Wrapf(err, "failed parsing %s", DefaultDockerignoreName) } } } diff --git a/go.mod b/go.mod index 3a0f30b56ebf..cae356e8498e 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/klauspost/compress v1.16.3 github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/moby/locker v1.0.1 - github.com/moby/patternmatcher v0.5.0 + github.com/moby/patternmatcher v0.6.0 github.com/moby/sys/mountinfo v0.6.2 github.com/moby/sys/signal v0.7.0 github.com/morikuni/aec v1.0.0 diff --git a/go.sum b/go.sum index 8d45ddd3c5af..cdeadc543062 100644 --- a/go.sum +++ b/go.sum @@ -906,8 +906,8 @@ github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQ github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= -github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74= github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74= github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= diff --git a/frontend/dockerfile/dockerignore/dockerignore.go b/vendor/github.com/moby/patternmatcher/ignorefile/ignorefile.go similarity index 65% rename from frontend/dockerfile/dockerignore/dockerignore.go rename to vendor/github.com/moby/patternmatcher/ignorefile/ignorefile.go index e7f29ae8df68..94ea5a0ef550 100644 --- a/frontend/dockerfile/dockerignore/dockerignore.go +++ b/vendor/github.com/moby/patternmatcher/ignorefile/ignorefile.go @@ -1,4 +1,4 @@ -package dockerignore +package ignorefile import ( "bufio" @@ -6,23 +6,31 @@ import ( "io" "path/filepath" "strings" - - "github.com/pkg/errors" ) -// ReadAll reads a .dockerignore file and returns the list of file patterns -// to ignore. Note this will trim whitespace from each line as well -// as use GO's "clean" func to get the shortest/cleanest path for each. +// ReadAll reads an ignore file from a reader and returns the list of file +// patterns to ignore, applying the following rules: +// +// - An UTF8 BOM header (if present) is stripped. +// - Lines starting with "#" are considered comments and are skipped. +// +// For remaining lines: +// +// - Leading and trailing whitespace is removed from each ignore pattern. +// - It uses [filepath.Clean] to get the shortest/cleanest path for +// ignore patterns. +// - Leading forward-slashes ("/") are removed from ignore patterns, +// so "/some/path" and "some/path" are considered equivalent. func ReadAll(reader io.Reader) ([]string, error) { if reader == nil { return nil, nil } - scanner := bufio.NewScanner(reader) var excludes []string currentLine := 0 - utf8bom := []byte{0xEF, 0xBB, 0xBF} + + scanner := bufio.NewScanner(reader) for scanner.Scan() { scannedBytes := scanner.Bytes() // We trim UTF8 BOM @@ -59,7 +67,7 @@ func ReadAll(reader io.Reader) ([]string, error) { excludes = append(excludes, pattern) } if err := scanner.Err(); err != nil { - return nil, errors.Wrap(err, "error reading .dockerignore") + return nil, err } return excludes, nil } diff --git a/vendor/modules.txt b/vendor/modules.txt index 76695844bad4..500dad70b301 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -632,9 +632,10 @@ github.com/mitchellh/hashstructure/v2 # github.com/moby/locker v1.0.1 ## explicit; go 1.13 github.com/moby/locker -# github.com/moby/patternmatcher v0.5.0 +# github.com/moby/patternmatcher v0.6.0 ## explicit; go 1.19 github.com/moby/patternmatcher +github.com/moby/patternmatcher/ignorefile # github.com/moby/sys/mount v0.3.3 ## explicit; go 1.16 github.com/moby/sys/mount