diff --git a/pkg/container/container_types.go b/pkg/container/container_types.go index a395432..767beb5 100644 --- a/pkg/container/container_types.go +++ b/pkg/container/container_types.go @@ -39,6 +39,7 @@ type FileEntry struct { type Container interface { Create(capAdd []string, capDrop []string) common.Executor Copy(destPath string, files ...*FileEntry) common.Executor + CopyTarStream(ctx context.Context, destPath string, tarStream io.Reader) error CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor GetContainerArchive(ctx context.Context, srcPath string) (io.ReadCloser, error) Pull(forcePull bool) common.Executor diff --git a/pkg/container/docker_run.go b/pkg/container/docker_run.go index 0abbf56..6eab90d 100644 --- a/pkg/container/docker_run.go +++ b/pkg/container/docker_run.go @@ -649,6 +649,14 @@ func (cr *containerReference) waitForCommand(ctx context.Context, isTerminal boo } } +func (cr *containerReference) CopyTarStream(ctx context.Context, destPath string, tarStream io.Reader) error { + err := cr.cli.CopyToContainer(ctx, cr.id, destPath, tarStream, types.CopyToContainerOptions{}) + if err != nil { + return fmt.Errorf("failed to copy content to container: %w", err) + } + return nil +} + func (cr *containerReference) copyDir(dstPath string, srcPath string, useGitIgnore bool) common.Executor { return func(ctx context.Context) error { logger := common.Logger(ctx) diff --git a/pkg/container/host_environment.go b/pkg/container/host_environment.go index a547db1..04ff12d 100644 --- a/pkg/container/host_environment.go +++ b/pkg/container/host_environment.go @@ -60,6 +60,33 @@ func (e *HostEnvironment) Copy(destPath string, files ...*FileEntry) common.Exec } } +func (e *HostEnvironment) CopyTarStream(ctx context.Context, destPath string, tarStream io.Reader) error { + if err := os.RemoveAll(destPath); err != nil { + return err + } + tr := tar.NewReader(tarStream) + cp := ©Collector{ + DstDir: destPath, + } + for { + ti, err := tr.Next() + if errors.Is(err, io.EOF) { + return nil + } else if err != nil { + return err + } + if ti.FileInfo().IsDir() { + continue + } + if ctx.Err() != nil { + return fmt.Errorf("CopyTarStream has been cancelled") + } + if err := cp.WriteFile(ti.Name, ti.FileInfo(), ti.Linkname, tr); err != nil { + return err + } + } +} + func (e *HostEnvironment) CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor { return func(ctx context.Context) error { logger := common.Logger(ctx)