aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/pkg/ir.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-07-23 16:21:20 +0900
committerOphestra <cat@gensokyo.uk>2026-07-23 16:39:34 +0900
commit67dbb68818026f3d7a64e9519cf1aac36468b7c9 (patch)
tree68f1e731242a9c8ef1912a195c2a6aefc53f6da5 /internal/pkg/ir.go
parent0e689d9983dee9f742c4ed4b2e716fbcb1b84e99 (diff)
internal/pkg: implementation revisions
This enables changing the behaviour of an artifact implementation without changing its IR structure. Unfortunately this changes the IR header structure resulting in many rebuilds. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg/ir.go')
-rw-r--r--internal/pkg/ir.go23
1 files changed, 20 insertions, 3 deletions
diff --git a/internal/pkg/ir.go b/internal/pkg/ir.go
index 5a7e7f56..d5e6bbdb 100644
--- a/internal/pkg/ir.go
+++ b/internal/pkg/ir.go
@@ -278,10 +278,11 @@ func (ic *irCache) encode(
return *a == *b
})
- // kind uint64 | deps_sz uint64
- var buf [wordSize * 2]byte
+ // kind uint64 | rev uint64 | deps_sz uint64
+ var buf [wordSize * 3]byte
binary.LittleEndian.PutUint64(buf[:], uint64(a.Kind()))
- binary.LittleEndian.PutUint64(buf[wordSize:], uint64(len(idents)))
+ binary.LittleEndian.PutUint64(buf[wordSize:], GetRevision(a))
+ binary.LittleEndian.PutUint64(buf[wordSize*2:], uint64(len(idents)))
if _, err = w.Write(buf[:]); err != nil {
return
}
@@ -740,6 +741,15 @@ func (ir *IRReader) ReadString() string {
return unsafe.String(unsafe.SliceData(p), len(p))
}
+// A RevisionError describes the first [Artifact] in an IR stream claiming a
+// revision not supported by the registered implementation.
+type RevisionError [2]uint64
+
+func (e RevisionError) Error() string {
+ return "claimed revision " + strconv.FormatUint(e[0], 10) +
+ " differs from implementation value " + strconv.FormatUint(e[1], 10)
+}
+
// decode decodes the next [Artifact] in the IR stream and returns any buffer
// originating from [Cache] before returning. decode returns [io.EOF] if and
// only if the underlying [io.Reader] is already read to EOF.
@@ -772,6 +782,9 @@ func (d *IRDecoder) decode() (a Artifact, err error) {
return
}
+ ir.mustRead(ir.buf[:])
+ rev := binary.LittleEndian.Uint64(ir.buf[:])
+
defer ir.putAll()
ir.mustRead(ir.buf[:])
sz := binary.LittleEndian.Uint64(ir.buf[:])
@@ -792,6 +805,10 @@ func (d *IRDecoder) decode() (a Artifact, err error) {
err = syscall.ENOTRECOVERABLE
return
}
+ if _rev := GetRevision(a); _rev != rev {
+ err = RevisionError{rev, _rev}
+ return
+ }
if ir.count != -1 {
err = ErrRemainingIR