aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/pkg/exec.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/pkg/exec.go')
-rw-r--r--internal/pkg/exec.go140
1 files changed, 113 insertions, 27 deletions
diff --git a/internal/pkg/exec.go b/internal/pkg/exec.go
index f5270801..39955637 100644
--- a/internal/pkg/exec.go
+++ b/internal/pkg/exec.go
@@ -103,8 +103,7 @@ type execArtifact struct {
args []string
// Duration the initial process is allowed to run. The zero value is
- // equivalent to execTimeoutDefault. This value is never encoded in Params
- // because it cannot affect outcome.
+ // equivalent to [ExecTimeoutDefault].
timeout time.Duration
// Caller-supplied exclusivity value, returned as is by IsExclusive.
@@ -129,12 +128,6 @@ func (a *execNetArtifact) Checksum() Checksum { return a.checksum }
// Kind returns the hardcoded [Kind] constant.
func (*execNetArtifact) Kind() Kind { return KindExecNet }
-// Params is [Checksum] concatenated with [KindExec] params.
-func (a *execNetArtifact) Params(ctx *IContext) {
- ctx.GetHash().Write(a.checksum[:])
- a.execArtifact.Params(ctx)
-}
-
// Cure cures the [Artifact] in the container described by the caller. The
// container retains host networking.
func (a *execNetArtifact) Cure(f *FContext) error {
@@ -198,38 +191,131 @@ func (*execArtifact) Kind() Kind { return KindExec }
// Params writes paths, executable pathname and args.
func (a *execArtifact) Params(ctx *IContext) {
- h := ctx.GetHash()
+ ctx.WriteString(a.name)
- _0, _1 := []byte{0}, []byte{1}
+ ctx.WriteUint32(uint32(len(a.paths)))
for _, p := range a.paths {
- if p.W {
- h.Write(_1)
- } else {
- h.Write(_0)
- }
if p.P != nil {
- h.Write([]byte(p.P.String()))
+ ctx.WriteString(p.P.String())
} else {
- h.Write([]byte("invalid P\x00"))
+ ctx.WriteString("invalid P\x00")
}
- h.Write(_0)
+
+ ctx.WriteUint32(uint32(len(p.A)))
for _, d := range p.A {
ctx.WriteIdent(d)
}
- h.Write(_0)
+
+ if p.W {
+ ctx.WriteUint32(1)
+ } else {
+ ctx.WriteUint32(0)
+ }
}
- h.Write(_0)
- h.Write([]byte(a.dir.String()))
- h.Write(_0)
+
+ ctx.WriteString(a.dir.String())
+
+ ctx.WriteUint32(uint32(len(a.env)))
for _, e := range a.env {
- h.Write([]byte(e))
+ ctx.WriteString(e)
}
- h.Write(_0)
- h.Write([]byte(a.path.String()))
- h.Write(_0)
+
+ ctx.WriteString(a.path.String())
+
+ ctx.WriteUint32(uint32(len(a.args)))
for _, arg := range a.args {
- h.Write([]byte(arg))
+ ctx.WriteString(arg)
+ }
+
+ ctx.WriteUint32(uint32(a.timeout & 0xffffffff))
+ ctx.WriteUint32(uint32(a.timeout >> 32))
+
+ if a.exclusive {
+ ctx.WriteUint32(1)
+ } else {
+ ctx.WriteUint32(0)
+ }
+}
+
+// readExecArtifact interprets IR values and returns the address of execArtifact
+// or execNetArtifact.
+func readExecArtifact(r *IRReader, net bool) Artifact {
+ r.DiscardAll()
+
+ name := r.ReadString()
+
+ sz := r.ReadUint32()
+ if sz > irMaxDeps {
+ panic(ErrIRDepend)
+ }
+ paths := make([]ExecPath, sz)
+ for i := range paths {
+ paths[i].P = check.MustAbs(r.ReadString())
+
+ sz = r.ReadUint32()
+ if sz > irMaxDeps {
+ panic(ErrIRDepend)
+ }
+ paths[i].A = make([]Artifact, sz)
+ for j := range paths[i].A {
+ paths[i].A[j] = r.ReadIdent()
+ }
+
+ paths[i].W = r.ReadUint32() != 0
+ }
+
+ dir := check.MustAbs(r.ReadString())
+
+ sz = r.ReadUint32()
+ if sz > irMaxValues {
+ panic(ErrIRValues)
+ }
+ env := make([]string, sz)
+ for i := range env {
+ env[i] = r.ReadString()
+ }
+
+ pathname := check.MustAbs(r.ReadString())
+
+ sz = r.ReadUint32()
+ if sz > irMaxValues {
+ panic(ErrIRValues)
+ }
+ args := make([]string, sz)
+ for i := range args {
+ args[i] = r.ReadString()
}
+
+ timeout := time.Duration(r.ReadUint32())
+ timeout |= time.Duration(r.ReadUint32()) << 32
+
+ exclusive := r.ReadUint32() != 0
+
+ checksum, ok := r.Finalise()
+
+ var checksumP *Checksum
+ if net {
+ if !ok {
+ panic(ErrExpectedChecksum)
+ }
+ checksumVal := checksum.Value()
+ checksumP = &checksumVal
+ } else {
+ if ok {
+ panic(ErrUnexpectedChecksum)
+ }
+ }
+
+ return NewExec(
+ name, checksumP, timeout, exclusive, dir, env, pathname, args, paths...,
+ )
+}
+
+func init() {
+ register(KindExec,
+ func(r *IRReader) Artifact { return readExecArtifact(r, false) })
+ register(KindExecNet,
+ func(r *IRReader) Artifact { return readExecArtifact(r, true) })
}
// Dependencies returns a slice of all artifacts collected from caller-supplied