aboutsummaryrefslogtreecommitdiffhomepage
path: root/pkg/file.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/file.go')
-rw-r--r--pkg/file.go100
1 files changed, 100 insertions, 0 deletions
diff --git a/pkg/file.go b/pkg/file.go
new file mode 100644
index 00000000..14467153
--- /dev/null
+++ b/pkg/file.go
@@ -0,0 +1,100 @@
+package pkg
+
+import (
+ "bytes"
+ "crypto/sha512"
+ "fmt"
+ "io"
+)
+
+// A fileArtifact is an [Artifact] that cures into data known ahead of time.
+type fileArtifact []byte
+
+var _ KnownChecksum = new(fileArtifact)
+var _ CuresExempt = new(fileArtifact)
+var _ RevisionArtifact = new(fileArtifact)
+
+// fileArtifactNamed embeds fileArtifact alongside a caller-supplied name.
+type fileArtifactNamed struct {
+ fileArtifact
+ // Caller-supplied user-facing reporting name.
+ name string
+}
+
+var _ fmt.Stringer = new(fileArtifactNamed)
+var _ KnownChecksum = new(fileArtifactNamed)
+
+// String returns the caller-supplied reporting name.
+func (a *fileArtifactNamed) String() string { return a.name }
+
+// Params writes the caller-supplied reporting name and the file body.
+func (a *fileArtifactNamed) Params(ctx *IContext) {
+ ctx.WriteString(a.name)
+ ctx.Write(a.fileArtifact)
+}
+
+// NewFile returns a [FileArtifact] that cures into a caller-supplied byte slice.
+//
+// Caller must not modify data after NewFile returns.
+func NewFile(name string, data []byte) FileArtifact {
+ f := fileArtifact(data)
+ if name != "" {
+ return &fileArtifactNamed{f, name}
+ }
+ return &f
+}
+
+// Kind returns the hardcoded [Kind] constant.
+func (*fileArtifact) Kind() Kind { return KindFile }
+
+// Params writes an empty string and the file body.
+func (a *fileArtifact) Params(ctx *IContext) {
+ ctx.WriteString("")
+ ctx.Write(*a)
+}
+
+func init() {
+ register(KindFile, func(r *IRReader) Artifact {
+ name := r.ReadString()
+ data := r.ReadStringBytes()
+ if _, ok := r.Finalise(); !ok {
+ panic(ErrExpectedChecksum)
+ }
+ return NewFile(name, data)
+ })
+}
+
+// Inputs returns a nil slice.
+func (*fileArtifact) Inputs() []Artifact { return nil }
+
+// IsExclusive returns false: Cure returns a prepopulated buffer.
+func (*fileArtifact) IsExclusive() bool { return false }
+
+// Checksum computes and returns the checksum of caller-supplied data.
+func (a *fileArtifact) Checksum() Checksum {
+ h := sha512.New384()
+ h.Write(*a)
+ return Checksum(h.Sum(nil))
+}
+
+// Revision satisfies [RevisionArtifact] for incompatible IsExecutable behaviour.
+func (*fileArtifact) Revision() uint64 { return 0 }
+
+// IsExecutable returns whether the contents begin with shebang or the ELF
+// magic number.
+func (a *fileArtifact) IsExecutable() bool {
+ return a != nil &&
+ (bytes.HasPrefix(
+ *a, []byte{'#', '!'},
+ ) || bytes.HasPrefix(
+ *a, []byte{0x7f, 'E', 'L', 'F'},
+ ))
+}
+
+// Cure returns the caller-supplied data.
+func (a *fileArtifact) Cure(*RContext) (io.ReadCloser, error) {
+ return io.NopCloser(bytes.NewReader(*a)), nil
+}
+
+// CuresExempt exempts the cheap [KindFile] implementation.
+func (*fileArtifact) CuresExempt() {}