blob

package
v0.11.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 12, 2025 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package blob implements a content-addressable disk cache for blobs and manifests.

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidDigest = errors.New("invalid digest")

Functions

func PutBytes

func PutBytes[S string | []byte](c *DiskCache, d Digest, data S) error

PutBytes is a convenience function for c.Put(d, strings.NewReader(s), int64(len(s))).

Types

type Chunk added in v0.6.1

type Chunk struct {
	Start int64
	End   int64
}

Chunk represents a range of bytes in a blob.

func (Chunk) Size added in v0.6.1

func (c Chunk) Size() int64

Size returns end minus start plus one.

type Chunker added in v0.6.1

type Chunker struct {
	// contains filtered or unexported fields
}

Chunker writes to a blob in chunks. Its zero value is invalid. Use DiskCache.Chunked to create a new Chunker.

func (*Chunker) Close added in v0.6.1

func (c *Chunker) Close() error

Close closes the underlying file.

func (*Chunker) Put added in v0.6.1

func (c *Chunker) Put(chunk Chunk, d Digest, r io.Reader) error

Put copies chunk.Size() bytes from r to the blob at the given offset, merging the data with the existing blob. It returns an error if any. As a special case, if r has less than chunk.Size() bytes, Put returns io.ErrUnexpectedEOF.

type Digest

type Digest struct {
	// contains filtered or unexported fields
}

Digest is a blob identifier that is the SHA-256 hash of a blob's content.

It is comparable and can be used as a map key.

func DigestFromBytes

func DigestFromBytes[S ~[]byte | ~string](v S) Digest

func ParseDigest

func ParseDigest[S ~[]byte | ~string](v S) (Digest, error)

ParseDigest parses a digest from a string. If the string is not a valid digest, a call to the returned digest's IsValid method will return false.

The input string may be in one of two forms:

  • ("sha256-<hex>"), where <hex> is a 64-character hexadecimal string.
  • ("sha256:<hex>"), where <hex> is a 64-character hexadecimal string.

The Digest.String method will return the canonical form of the digest, "sha256:<hex>".

func (Digest) Compare

func (d Digest) Compare(other Digest) int

func (Digest) IsValid

func (d Digest) IsValid() bool

IsValid returns true if the digest is valid, i.e. if it is the SHA-256 hash of some content.

func (Digest) MarshalText

func (d Digest) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface. It returns an error if Digest.IsValid returns false.

func (Digest) Short

func (d Digest) Short() string

func (Digest) String

func (d Digest) String() string

String returns the string representation of the digest in the conventional form "sha256:<hex>".

func (Digest) Sum added in v0.6.1

func (d Digest) Sum() [32]byte

func (*Digest) UnmarshalText

func (d *Digest) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface, and only works for a zero digest. If Digest.IsValid returns true, it returns an error.

type DiskCache

type DiskCache struct {
	// contains filtered or unexported fields
}

DiskCache caches blobs and manifests on disk.

The cache is rooted at a directory, which is created if it does not exist.

Blobs are stored in the "blobs" subdirectory, and manifests are stored in the "manifests" subdirectory. A example directory structure might look like:

<dir>/
  blobs/
    sha256-<digest> - <blob data>
  manifests/
    <host>/
      <namespace>/
        <name>/
          <tag> - <manifest data>

The cache is safe for concurrent use.

Name casing is preserved in the cache, but is not significant when resolving names. For example, "Foo" and "foo" are considered the same name.

The cache is not safe for concurrent use. It guards concurrent writes, but does not prevent duplicated effort. Because blobs are immutable, duplicate writes should result in the same file being written to disk.

func Open

func Open(dir string) (*DiskCache, error)

Open opens a cache rooted at the given directory. If the directory does not exist, it is created. If the directory is not a directory, an error is returned.

func (*DiskCache) Chunked added in v0.6.1

func (c *DiskCache) Chunked(d Digest, size int64) (*Chunker, error)

Chunked returns a new Chunker, ready for use storing a blob of the given size in chunks.

Use Chunker.Put to write data to the blob at specific offsets.

func (*DiskCache) Get

func (c *DiskCache) Get(d Digest) (Entry, error)

Get retrieves a blob from the cache using the provided digest. The operation fails if the digest is malformed or if any errors occur during blob retrieval.

func (*DiskCache) GetFile

func (c *DiskCache) GetFile(d Digest) string

GetFile returns the absolute path to the file, in the cache, for the given digest. It does not check if the file exists.

The returned path should not be stored, used outside the lifetime of the cache, or interpreted in any way.

func (*DiskCache) Import

func (c *DiskCache) Import(r io.Reader, size int64) (Digest, error)

Import imports a blob from the provided reader into the cache. It reads the entire content of the reader, calculates its digest, and stores it in the cache.

Import should be considered unsafe for use with untrusted data, such as data read from a network. The caller is responsible for ensuring the integrity of the data being imported.

func (c *DiskCache) Link(name string, d Digest) error

Link creates a symbolic reference in the cache that maps the provided name to a blob identified by its digest, making it retrievable by name using [Resolve].

It returns an error if either the name or digest is invalid, or if link creation encounters any issues.

func (c *DiskCache) Links() iter.Seq2[string, error]

Links returns a sequence of link names. The sequence is in lexical order. Names are converted from their relative path form to their name form but are not guaranteed to be valid. Callers should validate the names before using.

func (*DiskCache) Put

func (c *DiskCache) Put(d Digest, r io.Reader, size int64) error

Put writes a new blob to the cache, identified by its digest. The operation reads content from r, which must precisely match both the specified size and digest.

Concurrent write safety is achieved through file locking. The implementation guarantees write integrity by enforcing size limits and content validation before allowing the file to reach its final state.

func (*DiskCache) Resolve

func (c *DiskCache) Resolve(name string) (Digest, error)

Resolve resolves a name to a digest. The name is expected to be in either of the following forms:

@<digest>
<name>@<digest>
<name>

If a digest is provided, it is returned as is and nothing else happens.

If a name is provided for a manifest that exists in the cache, the digest of the manifest is returned. If there is no manifest in the cache, it returns fs.ErrNotExist.

To cover the case where a manifest may change without the cache knowing (e.g. it was reformatted or modified by hand), the manifest data read and hashed is passed to a PutBytes call to ensure that the manifest is in the blob store. This is done to ensure that future calls to [Get] succeed in these cases.

func (c *DiskCache) Unlink(name string) (ok bool, _ error)

Unlink unlinks the manifest by name from the cache. If the name is not found. If a manifest is removed ok will be true, otherwise false. If an error occurs, it returns ok false, and the error.

type Entry

type Entry struct {
	Digest Digest
	Size   int64
	Time   time.Time // when added to the cache
}

Entry contains metadata about a blob in the cache.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL