diff --git a/internal/pkg/net.go b/internal/pkg/net.go index 737dfd8..b8d85b9 100644 --- a/internal/pkg/net.go +++ b/internal/pkg/net.go @@ -3,8 +3,10 @@ package pkg import ( "context" "crypto/sha512" + "fmt" "io" "net/http" + "path" "sync" ) @@ -30,6 +32,7 @@ type httpArtifact struct { } var _ KnownChecksum = new(httpArtifact) +var _ fmt.Stringer = new(httpArtifact) // NewHTTPGet returns a new [File] backed by the supplied client. A GET request // is set up for url. If c is nil, [http.DefaultClient] is used instead. @@ -57,6 +60,9 @@ func (a *httpArtifact) Dependencies() []Artifact { return nil } // Checksum returns the caller-supplied checksum. func (a *httpArtifact) Checksum() Checksum { return a.checksum } +// String returns [path.Base] over the backing url. +func (a *httpArtifact) String() string { return path.Base(a.url) } + // ResponseStatusError is returned for a response returned by an [http.Client] // with a status code other than [http.StatusOK]. type ResponseStatusError int diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go index 60898b4..c1a3f97 100644 --- a/internal/pkg/pkg.go +++ b/internal/pkg/pkg.go @@ -8,6 +8,7 @@ import ( "encoding/base64" "encoding/binary" "errors" + "fmt" "io" "io/fs" "os" @@ -278,6 +279,20 @@ func Ident(a Artifact) ID { return a.Kind().Ident(a.Params(), a.Dependencies()...) } +// reportNameIdent is like reportName but does not recompute [ID]. +func reportNameIdent(a Artifact, id ID) string { + r := Encode(id) + if s, ok := a.(fmt.Stringer); ok { + if name := s.String(); name != "" { + r += "-" + name + } + } + return r +} + +// reportName returns a string describing [Artifact] presented to the user. +func reportName(a Artifact) string { return reportNameIdent(a, Ident(a)) } + // Kind corresponds to the concrete type of [Artifact] and is used to create // identifier for an [Artifact] with dependencies. type Kind uint64 @@ -725,6 +740,9 @@ func (c *Cache) openFile(f File) (r io.ReadCloser, err error) { if !errors.Is(err, os.ErrNotExist) { return } + if c.msg.IsVerbose() { + c.msg.Verbosef("curing %s to memory...", reportName(f)) + } var data []byte if data, err = f.Cure(c.ctx); err != nil { return @@ -917,7 +935,7 @@ func (c *Cache) Cure(a Artifact) ( } if c.msg.IsVerbose() { - c.msg.Verbosef("curing %s...", Encode(id)) + c.msg.Verbosef("curing %s...", reportNameIdent(a, id)) } // cure File outside type switch to skip TContext initialisation diff --git a/internal/pkg/tar.go b/internal/pkg/tar.go index 624eafe..0aa8e3b 100644 --- a/internal/pkg/tar.go +++ b/internal/pkg/tar.go @@ -6,6 +6,7 @@ import ( "compress/gzip" "encoding/binary" "errors" + "fmt" "io" "io/fs" "net/http" @@ -32,11 +33,29 @@ type tarArtifact struct { compression uint64 } +// tarArtifactNamed embeds tarArtifact for a [fmt.Stringer] tarball. +type tarArtifactNamed struct { + tarArtifact + // Copied from tarArtifact.f. + name string +} + +var _ fmt.Stringer = new(tarArtifactNamed) + +// String returns the name of the underlying [Artifact] suffixed with unpack. +func (a *tarArtifactNamed) String() string { return a.name + "-unpack" } + // NewTar returns a new [Artifact] backed by the supplied [Artifact] and // compression method. The source [Artifact] must be compatible with // [TContext.Open]. func NewTar(a Artifact, compression uint64) Artifact { - return &tarArtifact{a, compression} + ta := tarArtifact{a, compression} + if s, ok := a.(fmt.Stringer); ok { + if name := s.String(); name != "" { + return &tarArtifactNamed{ta, name} + } + } + return &ta } // NewHTTPGetTar is abbreviation for NewHTTPGet passed to NewTar.