diff --git a/build/opt.go b/build/opt.go index db5caf901..1c6d429b8 100644 --- a/build/opt.go +++ b/build/opt.go @@ -876,11 +876,7 @@ func CreateExports(entries []*buildflags.ExportEntry) ([]client.ExportEntry, []s if err == nil && fi.IsDir() { return nil, nil, errors.Errorf("destination file %s is a directory", entry.Destination) } - f, err := os.Create(entry.Destination) - if err != nil { - return nil, nil, errors.Errorf("failed to open %s", err) - } - out.Output = wrapWriteCloser(f) + out.Output = wrapWriteCloserLazy(entry.Destination) localPaths = append(localPaths, entry.Destination) } } @@ -896,6 +892,38 @@ func wrapWriteCloser(wc io.WriteCloser) func(map[string]string) (io.WriteCloser, } } +type lazyFileWriter struct { + path string + file *os.File +} + +func (w *lazyFileWriter) Write(p []byte) (int, error) { + if w.file == nil { + if err := os.MkdirAll(filepath.Dir(w.path), 0755); err != nil { + return 0, err + } + f, err := os.Create(w.path) + if err != nil { + return 0, err + } + w.file = f + } + return w.file.Write(p) +} + +func (w *lazyFileWriter) Close() error { + if w.file != nil { + return w.file.Close() + } + return nil +} + +func wrapWriteCloserLazy(path string) func(map[string]string) (io.WriteCloser, error) { + return func(map[string]string) (io.WriteCloser, error) { + return &lazyFileWriter{path: path}, nil + } +} + func CreateCaches(entries []*buildflags.CacheOptionsEntry) []client.CacheOptionsEntry { var outs []client.CacheOptionsEntry if len(entries) == 0 { diff --git a/tests/bake.go b/tests/bake.go index c96819889..5707c8cf8 100644 --- a/tests/bake.go +++ b/tests/bake.go @@ -1359,17 +1359,19 @@ target "default" { dirDest := t.TempDir() + envs := []string{"BUILDX_METADATA_PROVENANCE=" + metadataMode} outFlag := "default.output=type=docker" if sb.DockerAddress() == "" { // there is no Docker atm to load the image outFlag += ",dest=" + dirDest + "/image.tar" + envs = append(envs, "BUILDX_BAKE_ENTITLEMENTS_FS=0") } cmd := buildxCmd( sb, withDir(dir), withArgs("bake", "--metadata-file", filepath.Join(dirDest, "md.json"), "--set", outFlag), - withEnv("BUILDX_METADATA_PROVENANCE="+metadataMode), + withEnv(envs...), ) out, err := cmd.CombinedOutput() require.NoError(t, err, string(out)) diff --git a/tests/build.go b/tests/build.go index 557c63b00..07b12d599 100644 --- a/tests/build.go +++ b/tests/build.go @@ -417,10 +417,11 @@ func testBuildLocalExport(t *testing.T, sb integration.Sandbox) { func testBuildTarExport(t *testing.T, sb integration.Sandbox) { dir := createTestProject(t) - out, err := buildCmd(sb, withArgs(fmt.Sprintf("--output=type=tar,dest=%s/result.tar", dir), dir)) + outdir := path.Join(dir, "out") + out, err := buildCmd(sb, withArgs(fmt.Sprintf("--output=type=tar,dest=%s/result.tar", outdir), dir)) require.NoError(t, err, string(out)) - dt, err := os.ReadFile(fmt.Sprintf("%s/result.tar", dir)) + dt, err := os.ReadFile(fmt.Sprintf("%s/result.tar", outdir)) require.NoError(t, err) m, err := testutil.ReadTarToMap(dt, false) require.NoError(t, err)