snapshot of https://github.com/sqlc-dev/sqlc.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
kotlin / test (push) Has been skipped
python / test (push) Has been skipped
typescript / test (push) Has been skipped
go / build darwin/amd64 (push) Has been cancelled
go / build linux/amd64 (push) Has been cancelled
go / build windows/amd64 (push) Has been cancelled
go / build darwin/arm64 (push) Has been cancelled
go / build linux/arm64 (push) Has been cancelled
go / build windows/arm64 (push) Has been cancelled
go / test (push) Has been cancelled
go / vuln_check (push) Has been cancelled
Some checks failed
kotlin / test (push) Has been skipped
python / test (push) Has been skipped
typescript / test (push) Has been skipped
go / build darwin/amd64 (push) Has been cancelled
go / build linux/amd64 (push) Has been cancelled
go / build windows/amd64 (push) Has been cancelled
go / build darwin/arm64 (push) Has been cancelled
go / build linux/arm64 (push) Has been cancelled
go / build windows/arm64 (push) Has been cancelled
go / test (push) Has been cancelled
go / vuln_check (push) Has been cancelled
This commit is contained in:
100
internal/cache/digest.go
vendored
Normal file
100
internal/cache/digest.go
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"hash"
|
||||
)
|
||||
|
||||
// Digest identifies a blob by its SHA-256 hash and size, mirroring the
|
||||
// Digest message from Bazel's remote execution API. The size is stored
|
||||
// alongside the hash so that entries can be validated without reading blob
|
||||
// contents; a negative size means the size is unknown, as with a checksum
|
||||
// declared in a configuration file.
|
||||
type Digest struct {
|
||||
// Hash is the lowercase hex-encoded SHA-256 hash of the blob.
|
||||
Hash string `json:"hash"`
|
||||
// SizeBytes is the length of the blob in bytes, or negative if unknown.
|
||||
SizeBytes int64 `json:"size_bytes"`
|
||||
}
|
||||
|
||||
func (d Digest) String() string {
|
||||
return fmt.Sprintf("sha256:%s/%d", d.Hash, d.SizeBytes)
|
||||
}
|
||||
|
||||
func (d Digest) valid() bool {
|
||||
if len(d.Hash) != 64 {
|
||||
return false
|
||||
}
|
||||
_, err := hex.DecodeString(d.Hash)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// DigestOf returns the Digest of a blob.
|
||||
func DigestOf(data []byte) Digest {
|
||||
sum := sha256.Sum256(data)
|
||||
return Digest{
|
||||
Hash: hex.EncodeToString(sum[:]),
|
||||
SizeBytes: int64(len(data)),
|
||||
}
|
||||
}
|
||||
|
||||
// SHA256Digest returns a Digest referencing a blob by a declared SHA-256
|
||||
// checksum whose size is not known, suitable for looking up remotely fetched
|
||||
// content in the CAS.
|
||||
func SHA256Digest(hexhash string) Digest {
|
||||
return Digest{
|
||||
Hash: hexhash,
|
||||
SizeBytes: -1,
|
||||
}
|
||||
}
|
||||
|
||||
// An Action describes a unit of cacheable work, playing the role of Bazel's
|
||||
// Action message: a mnemonic naming the kind of work plus the complete set of
|
||||
// inputs that determine its outputs. Two actions with the same digest are
|
||||
// assumed to produce the same outputs.
|
||||
//
|
||||
// Inputs are hashed incrementally with length-prefixed framing so that the
|
||||
// boundary between inputs is unambiguous ("ab"+"c" hashes differently from
|
||||
// "a"+"bc").
|
||||
type Action struct {
|
||||
hasher hash.Hash
|
||||
}
|
||||
|
||||
// NewAction starts building an action key for the given mnemonic, e.g.
|
||||
// "QueryAnalysis". The sha256 of the sqlc binary itself is always the first
|
||||
// input: the tool that executes an action determines its outputs just as
|
||||
// much as the declared inputs do, so a rebuilt sqlc never reuses stale
|
||||
// entries. The binary's digest is memoized in the cache — see toolDigest —
|
||||
// which is why actions are created through a Cache.
|
||||
func (c *Cache) NewAction(mnemonic string) *Action {
|
||||
a := &Action{hasher: sha256.New()}
|
||||
a.write([]byte(mnemonic))
|
||||
a.AddInput("tool", c.toolDigest())
|
||||
return a
|
||||
}
|
||||
|
||||
// AddInput mixes a named input into the action key. Order matters: callers
|
||||
// must add inputs in a deterministic order.
|
||||
func (a *Action) AddInput(name string, data []byte) *Action {
|
||||
a.write([]byte(name))
|
||||
a.write(data)
|
||||
return a
|
||||
}
|
||||
|
||||
// Digest returns the action's digest, used as the action cache key.
|
||||
func (a *Action) Digest() Digest {
|
||||
return Digest{
|
||||
Hash: hex.EncodeToString(a.hasher.Sum(nil)),
|
||||
SizeBytes: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Action) write(data []byte) {
|
||||
var frame [8]byte
|
||||
binary.LittleEndian.PutUint64(frame[:], uint64(len(data)))
|
||||
a.hasher.Write(frame[:])
|
||||
a.hasher.Write(data)
|
||||
}
|
||||
Reference in New Issue
Block a user