aboutsummaryrefslogtreecommitdiffhomepage
path: root/pkg/archive.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/archive.go')
-rw-r--r--pkg/archive.go67
1 files changed, 40 insertions, 27 deletions
diff --git a/pkg/archive.go b/pkg/archive.go
index e9f76f5b..ba7c61b9 100644
--- a/pkg/archive.go
+++ b/pkg/archive.go
@@ -314,36 +314,25 @@ func (archiveArtifact) IsExclusive() bool { return false }
// Revision satisfies [RevisionArtifact] for status behaviour.
func (archiveArtifact) Revision() uint64 { return 0 }
-// Cure cures the [Artifact], producing a directory located at work.
-func (a archiveArtifact) Cure(t *TContext) (err error) {
- var status io.Writer
- if status, err = t.GetStatusWriter(); err != nil {
- return
- }
-
- var r io.ReadCloser
- if r, err = t.Open(a.f); err != nil {
- return
- }
-
- defer func() {
- closeErr := r.Close()
- if err == nil {
- err = closeErr
- }
- }()
-
+// Extract reads an archive stream from r and writes its contents to dir. If
+// writeStatus is non-nil, it is called with a user-facing message after
+// each successfully extracted entry.
+func Extract(
+ r io.Reader,
+ dir string,
+ writeStatus func(s string) error,
+) (err error) {
type dirTargetPerm struct {
path string
mode fs.FileMode
}
var madeDirectories []dirTargetPerm
- if err = os.MkdirAll(t.GetWorkDir().String(), 0700); err != nil {
+ if err = os.MkdirAll(dir, 0700); err != nil {
return
}
var root *os.Root
- if root, err = os.OpenRoot(t.GetWorkDir().String()); err != nil {
+ if root, err = os.OpenRoot(dir); err != nil {
return
}
defer func() {
@@ -355,7 +344,6 @@ func (a archiveArtifact) Cure(t *TContext) (err error) {
var header *ArchiveHeader
ar := NewReader(r)
- msg := t.GetMessage()
for header, err = ar.Next(); err == nil; header, err = ar.Next() {
var m string
if header.Mode.IsRegular() {
@@ -422,11 +410,8 @@ func (a archiveArtifact) Cure(t *TContext) (err error) {
return InvalidFileModeError(header.Mode)
}
- if m != "" {
- msg.Verbose(m)
- if _, err = io.WriteString(status, m); err != nil {
- return
- } else if _, err = status.Write([]byte{'\n'}); err != nil {
+ if writeStatus != nil && m != "" {
+ if err = writeStatus(m); err != nil {
return
}
}
@@ -446,6 +431,34 @@ func (a archiveArtifact) Cure(t *TContext) (err error) {
return
}
+// Cure cures the [Artifact], producing a directory located at work.
+func (a archiveArtifact) Cure(t *TContext) (err error) {
+ var status io.Writer
+ if status, err = t.GetStatusWriter(); err != nil {
+ return
+ }
+
+ var r io.ReadCloser
+ if r, err = t.Open(a.f); err != nil {
+ return
+ }
+
+ msg := t.GetMessage()
+ err = Extract(r, t.GetWorkDir().String(), func(s string) (err error) {
+ msg.Verbose(s)
+ if _, err = io.WriteString(status, s); err != nil {
+ return
+ }
+ _, err = status.Write([]byte{'\n'})
+ return
+ })
+
+ if closeErr := r.Close(); err == nil {
+ err = closeErr
+ }
+ return
+}
+
// CuresExempt exempts the cheap [KindArchive] implementation often found at
// the end of a [FileArtifact] pipeline.
func (archiveArtifact) CuresExempt() {}