diff options
Diffstat (limited to 'internal/pkg/exec.go')
| -rw-r--r-- | internal/pkg/exec.go | 140 |
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 |
