aboutsummaryrefslogtreecommitdiffhomepage
path: root/pkg/tar.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-09-16 13:39:20 +0900
committerOphestra <cat@gensokyo.uk>2026-09-16 13:39:20 +0900
commit56572324956cfaa9039f7d7b7885cb3fec22f3fb (patch)
tree49bce72a226c7162695e46c9ec22d68f5a51969b /pkg/tar.go
parentbbb6f349d3cf790fbd4f400201b816a2206b1769 (diff)
pkg: write tar status
This serves as a status indicator while fetching large tarballs, and preserves information otherwise stripped during unpacking. This is a revision of the tarArtifact to avoid inconsistent state from previously cured tarArtifact lacking their status files. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'pkg/tar.go')
-rw-r--r--pkg/tar.go57
1 files changed, 52 insertions, 5 deletions
diff --git a/pkg/tar.go b/pkg/tar.go
index 9a8c4b76..33952b05 100644
--- a/pkg/tar.go
+++ b/pkg/tar.go
@@ -66,6 +66,9 @@ func (a *tarArtifact) Inputs() []Artifact {
// IsExclusive returns false: decompressor and tar reader are fully sequential.
func (a *tarArtifact) IsExclusive() bool { return false }
+// Revision satisfies [RevisionArtifact] for status behaviour.
+func (*tarArtifact) Revision() uint64 { return 0 }
+
// A DisallowedTypeflagError describes a disallowed typeflag encountered while
// unpacking a tarball.
type DisallowedTypeflagError byte
@@ -76,6 +79,11 @@ func (e DisallowedTypeflagError) Error() string {
// Cure cures the [Artifact], producing a directory located at work.
func (a *tarArtifact) 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
@@ -110,6 +118,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
var header *tar.Header
tr := tar.NewReader(r)
+ msg := t.GetMessage()
for header, err = tr.Next(); err == nil; header, err = tr.Next() {
typeflag := header.Typeflag
if typeflag == 0 {
@@ -126,6 +135,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
}
}
+ var m string
switch typeflag {
case tar.TypeReg:
var f *os.File
@@ -142,6 +152,13 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
} else if err = f.Close(); err != nil {
return
}
+
+ m = fmt.Sprintf(
+ "%s %s (%d bytes)",
+ header.FileInfo().Mode(),
+ header.Name,
+ header.Size,
+ )
break
case tar.TypeLink:
@@ -151,6 +168,13 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
); err != nil {
return
}
+
+ m = fmt.Sprintf(
+ "%s %s linkname %s",
+ header.FileInfo().Mode(),
+ header.Name,
+ header.Linkname,
+ )
break
case tar.TypeSymlink:
@@ -160,6 +184,13 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
); err != nil {
return
}
+
+ m = fmt.Sprintf(
+ "%s %s linkname %s",
+ header.FileInfo().Mode(),
+ header.Name,
+ header.Linkname,
+ )
break
case tar.TypeDir:
@@ -170,21 +201,37 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
if err = root.MkdirAll(header.Name, 0700); err != nil {
return
}
+
+ m = fmt.Sprintf(
+ "%s %s",
+ header.FileInfo().Mode(),
+ header.Name,
+ )
break
case tar.TypeChar:
- t.GetMessage().Verbosef(
- "%sskipping character device %d, %d %q%s",
- t.cache.sgrWarn, header.Devmajor, header.Devminor, header.Name, t.cache.sgrRes,
+ m = fmt.Sprintf(
+ "skipping character device %d, %d %q",
+ header.Devmajor, header.Devminor, header.Name,
)
- continue
+ break
case tar.TypeXGlobalHeader:
- continue // ignore
+ m = "skipping PAX global key-value record"
+ break
default:
return DisallowedTypeflagError(typeflag)
}
+
+ if m != "" {
+ msg.Verbose(m)
+ if _, err = io.WriteString(status, m); err != nil {
+ return
+ } else if _, err = status.Write([]byte{'\n'}); err != nil {
+ return
+ }
+ }
}
if errors.Is(err, io.EOF) {
err = nil