core

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DefaultChunkMinSize     = 128 * 1024 // 128KB
	DefaultChunkAvgSize     = 256 * 1024 // 256KB
	DefaultChunkMaxSize     = 512 * 1024 // 512KB
	DefaultIgnoreFile       = ".driftignore"
	DefaultAutoSaveInterval = 300
	DefaultAutoSaveKeep     = 10
)

Default configuration values. Centralized here so that both DefaultConfig(), storage-layer normalization, and downstream consumers (chunker, fsutil) all reference the same source of truth instead of repeating magic literals.

View Source
const (
	DefaultZstdLevel = 3
	MinZstdLevel     = 1
	MaxZstdLevel     = 19
)

Zstd compression level bounds. DefaultZstdLevel is used when compression is enabled but no explicit level is configured; MinZstdLevel and MaxZstdLevel clamp out-of-range values in ZstdLevel().

View Source
const ConfigVersion = 1

ConfigVersion is the current on-disk config schema version. Bump when the config struct gains a field that requires migration logic; loaders can then branch on Version to apply transforms. Version 1 is the first versioned schema; a missing version (zero value) is read as a legacy file.

View Source
const HashSize = 32

HashSize is the length of a Hash in bytes.

View Source
const HeaderPeekSize = 512

Variables

View Source
var ErrCorrupted = errors.New("drift: corrupted data")

ErrCorrupted is returned when protobuf data fails a length or integrity check during decoding. It indicates truncated or malformed hash fields that would otherwise be silently zero-padded by BytesToHash.

View Source
var File_index_proto protoreflect.FileDescriptor
View Source
var File_snapshot_proto protoreflect.FileDescriptor

Functions

This section is empty.

Types

type Chunk

type Chunk struct {
	Hash  Hash
	Size  uint32
	Data  []byte
	Flags ChunkFlag
}

Chunk represents a content-addressed chunk of data.

type ChunkFlag

type ChunkFlag uint8

ChunkFlag represents flags for a chunk.

const (
	ChunkFlagNone       ChunkFlag = 0
	ChunkFlagCompressed ChunkFlag = 1
)

type Config

type Config struct {
	// Version is the schema version of the config file. Omitted from JSON
	// when zero (legacy files) so existing config.json files load unchanged.
	Version int        `json:"version,omitempty"`
	User    UserConfig `json:"user"`
	Core    CoreConfig `json:"core"`
}

func DefaultConfig

func DefaultConfig() *Config

func (*Config) ApplyEnvOverrides

func (c *Config) ApplyEnvOverrides()

ApplyEnvOverrides replaces config fields with the corresponding DRIFT_* environment variable when it is set to a parseable value. Unset or unparseable values are ignored (the file value is kept) so a typo cannot wipe a valid config. Out-of-range clamping is left to Normalize, which runs immediately after this in NormalizeConfig.

func (*Config) Validate

func (c *Config) Validate() error

Validate checks semantic validity of the config AFTER Normalize has clamped out-of-range-low values to defaults. It catches values that are syntactically legal but operationally wrong — e.g. an IgnoreFile path containing ".." (path-traversal risk) or an absurdly large AutoSaveKeep that would exhaust disk. Validate is non-mutating; callers decide how to react (NormalizeConfig logs a warning and keeps the clamped value rather than failing the whole operation, since a clamped-but-suspicious value is usually preferable to aborting a workspace command).

type CoreConfig

type CoreConfig struct {
	Compression      bool   `json:"compression"`
	CompressionLevel int    `json:"compression_level"`
	IgnoreFile       string `json:"ignore_file"`
	AutoSaveInterval int    `json:"auto_save_interval"`
	AutoSaveKeep     int    `json:"auto_save_keep"`
	// TrustMtime, when true, enables the (size, mtime) fast path in
	// CreateSnapshot: a file whose size and mtime match the index entry is
	// reused without re-chunking. This is a performance optimization that
	// trades correctness for speed — tools that preserve mtime while
	// changing content (cp -p, rsync --times, editor atomic-save that
	// restores mtime) would silently cause stale chunks to be reused.
	// Defaults to false (safe): every save re-chunks every file. Users who
	// understand the risk and need the speedup can set this true via
	// config.json or DRIFT_TRUST_MTIME=1.
	TrustMtime bool `json:"trust_mtime,omitempty"`
}

func (*CoreConfig) Normalize

func (c *CoreConfig) Normalize()

Normalize clamps invalid fields to their defaults. It is idempotent and safe to call on any CoreConfig, including zero-value structs and configs loaded from JSON that may have partial/missing fields.

This logic lives in the core package so both filesystem and memory storage backends apply the same normalization, avoiding backend-specific drift. After Normalize, every field is guaranteed to hold a legal value, so callers can read CompressionLevel directly without going through ZstdLevel().

func (*CoreConfig) ZstdLevel

func (c *CoreConfig) ZstdLevel() int

type FileEntry

type FileEntry struct {
	Path     string
	Mode     FileMode
	Size     int64
	ModTime  int64 // unix timestamp in nanoseconds (time.UnixNano())
	Chunks   []Hash
	Hash     Hash
	Metadata *FileMetadata
}

FileEntry describes a file tracked in a snapshot.

type FileEntryProto

type FileEntryProto struct {
	Path        string            `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
	Mode        uint32            `protobuf:"varint,2,opt,name=mode,proto3" json:"mode,omitempty"`
	Size        int64             `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
	ModTime     int64             `protobuf:"varint,4,opt,name=mod_time,json=modTime,proto3" json:"mod_time,omitempty"`
	ChunkHashes [][]byte          `protobuf:"bytes,5,rep,name=chunk_hashes,json=chunkHashes,proto3" json:"chunk_hashes,omitempty"` // each is 32 bytes BLAKE3 hash
	MimeType    *string           `protobuf:"bytes,6,opt,name=mime_type,json=mimeType,proto3,oneof" json:"mime_type,omitempty"`
	FileHash    []byte            `protobuf:"bytes,7,opt,name=file_hash,json=fileHash,proto3" json:"file_hash,omitempty"` // 32 bytes BLAKE3 hash of the file
	Extra       map[string]string ``                                                                                      // optional metadata key-value pairs
	/* 137-byte string literal not displayed */
	// contains filtered or unexported fields
}

FileEntryProto is the protobuf representation of a file entry in a snapshot.

func (*FileEntryProto) Descriptor deprecated

func (*FileEntryProto) Descriptor() ([]byte, []int)

Deprecated: Use FileEntryProto.ProtoReflect.Descriptor instead.

func (*FileEntryProto) GetChunkHashes

func (x *FileEntryProto) GetChunkHashes() [][]byte

func (*FileEntryProto) GetExtra

func (x *FileEntryProto) GetExtra() map[string]string

func (*FileEntryProto) GetFileHash

func (x *FileEntryProto) GetFileHash() []byte

func (*FileEntryProto) GetMimeType

func (x *FileEntryProto) GetMimeType() string

func (*FileEntryProto) GetModTime

func (x *FileEntryProto) GetModTime() int64

func (*FileEntryProto) GetMode

func (x *FileEntryProto) GetMode() uint32

func (*FileEntryProto) GetPath

func (x *FileEntryProto) GetPath() string

func (*FileEntryProto) GetSize

func (x *FileEntryProto) GetSize() int64

func (*FileEntryProto) ProtoMessage

func (*FileEntryProto) ProtoMessage()

func (*FileEntryProto) ProtoReflect

func (x *FileEntryProto) ProtoReflect() protoreflect.Message

func (*FileEntryProto) Reset

func (x *FileEntryProto) Reset()

func (*FileEntryProto) String

func (x *FileEntryProto) String() string

type FileMetadata

type FileMetadata struct {
	MIMEType string
	Extra    map[string]string
}

FileMetadata holds optional metadata about a file.

type FileMode

type FileMode uint32

FileMode represents a file's mode/type.

const (
	// FileModeMask is the bitmask for file type bits.
	FileModeMask FileMode = 0o170000

	// File type bits (use with FileModeMask for type comparison)
	FileModeRegular   FileMode = 0o100000
	FileModeDir       FileMode = 0o040000
	FileModeSymlink   FileMode = 0o120000
	FileModeDevice    FileMode = 0o020000 // block or character device
	FileModeNamedPipe FileMode = 0o010000 // FIFO (named pipe)
	FileModeSocket    FileMode = 0o140000 // socket
)

func (FileMode) IsDevice

func (m FileMode) IsDevice() bool

IsDevice returns true if the file mode represents a block or character device.

func (FileMode) IsDir

func (m FileMode) IsDir() bool

IsDir returns true if the file mode represents a directory.

func (FileMode) IsNamedPipe

func (m FileMode) IsNamedPipe() bool

IsNamedPipe returns true if the file mode represents a FIFO (named pipe).

func (FileMode) IsRegular

func (m FileMode) IsRegular() bool

IsRegular returns true if the file mode represents a regular file.

func (FileMode) IsSocket

func (m FileMode) IsSocket() bool

IsSocket returns true if the file mode represents a socket.

func (m FileMode) IsSymlink() bool

IsSymlink returns true if the file mode represents a symbolic link.

func (FileMode) String

func (m FileMode) String() string

String returns a human-readable representation of the file mode.

type Hash

type Hash [32]byte

Hash is a BLAKE3 hash (32 bytes).

func BytesToHash

func BytesToHash(b []byte) Hash

BytesToHash copies a byte slice into a Hash. If len(b) < HashSize the remaining bytes are zero-filled; if len(b) > HashSize extra bytes are truncated. Callers decoding untrusted data (e.g. from protobuf) MUST validate len(b) == HashSize beforehand to avoid silently accepting a truncated hash. See SnapshotFromProto for the validated usage.

func (Hash) FullString

func (h Hash) FullString() string

FullString returns the full 64-character hex representation.

func (Hash) IsZero

func (h Hash) IsZero() bool

IsZero returns true if the hash is all zeros.

func (Hash) String

func (h Hash) String() string

String returns the hex representation truncated to the first 8 characters.

type Index

type Index struct {
	Entries   []IndexEntry
	UpdatedAt int64
}

Index represents the staging area for tracking file changes.

type IndexEntry

type IndexEntry struct {
	Path    string
	Hash    Hash
	Size    int64
	ModTime int64
	Chunks  []Hash
}

IndexEntry represents a single file entry in the staging index.

type IndexEntryProto

type IndexEntryProto struct {
	Path        string   `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
	Hash        []byte   `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` // 32 bytes BLAKE3 hash
	Size        int64    `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
	ModTime     int64    `protobuf:"varint,4,opt,name=mod_time,json=modTime,proto3" json:"mod_time,omitempty"`
	ChunkHashes [][]byte `protobuf:"bytes,5,rep,name=chunk_hashes,json=chunkHashes,proto3" json:"chunk_hashes,omitempty"` // each is 32 bytes BLAKE3 hash
	// contains filtered or unexported fields
}

IndexEntryProto is the protobuf representation of an index entry.

func (*IndexEntryProto) Descriptor deprecated

func (*IndexEntryProto) Descriptor() ([]byte, []int)

Deprecated: Use IndexEntryProto.ProtoReflect.Descriptor instead.

func (*IndexEntryProto) GetChunkHashes

func (x *IndexEntryProto) GetChunkHashes() [][]byte

func (*IndexEntryProto) GetHash

func (x *IndexEntryProto) GetHash() []byte

func (*IndexEntryProto) GetModTime

func (x *IndexEntryProto) GetModTime() int64

func (*IndexEntryProto) GetPath

func (x *IndexEntryProto) GetPath() string

func (*IndexEntryProto) GetSize

func (x *IndexEntryProto) GetSize() int64

func (*IndexEntryProto) ProtoMessage

func (*IndexEntryProto) ProtoMessage()

func (*IndexEntryProto) ProtoReflect

func (x *IndexEntryProto) ProtoReflect() protoreflect.Message

func (*IndexEntryProto) Reset

func (x *IndexEntryProto) Reset()

func (*IndexEntryProto) String

func (x *IndexEntryProto) String() string

type IndexProto

type IndexProto struct {
	Entries   []*IndexEntryProto `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"`
	UpdatedAt int64              `protobuf:"varint,2,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
	// contains filtered or unexported fields
}

IndexProto is the protobuf representation of the staging index.

func (*IndexProto) Descriptor deprecated

func (*IndexProto) Descriptor() ([]byte, []int)

Deprecated: Use IndexProto.ProtoReflect.Descriptor instead.

func (*IndexProto) GetEntries

func (x *IndexProto) GetEntries() []*IndexEntryProto

func (*IndexProto) GetUpdatedAt

func (x *IndexProto) GetUpdatedAt() int64

func (*IndexProto) ProtoMessage

func (*IndexProto) ProtoMessage()

func (*IndexProto) ProtoReflect

func (x *IndexProto) ProtoReflect() protoreflect.Message

func (*IndexProto) Reset

func (x *IndexProto) Reset()

func (*IndexProto) String

func (x *IndexProto) String() string

type RefType

type RefType string

RefType represents the type of a reference.

const (
	RefTypeBranch RefType = "branch"
	RefTypeTag    RefType = "tag"
	RefTypeHead   RefType = "HEAD"
)

type Reference

type Reference struct {
	Name   string
	Type   RefType
	Target Hash
	SymRef string
}

Reference represents a named reference to a commit hash.

type Snapshot

type Snapshot struct {
	ID        SnapshotID
	PrevID    *SnapshotID // nil for the first commit
	Message   string
	Author    string
	Timestamp int64 // unix timestamp
	Files     []FileEntry
	Tags      []string
	TotalSize int64
}

Snapshot represents a point-in-time version of the tracked files.

func SnapshotFromProto

func SnapshotFromProto(p *SnapshotProto) (*Snapshot, error)

SnapshotFromProto rebuilds a Snapshot from its protobuf wire form. This is the inverse of SnapshotToProto and is shared between the storage layer (GetSnapshot) and the remote sync layer (pull), so both decode persisted snapshots identically.

Hash fields (IdHash, PrevIdHash, ChunkHashes) are validated to be exactly HashSize bytes when present. Truncated hashes return ErrCorrupted instead of being silently zero-padded by BytesToHash, which would produce a different hash and mask data corruption.

func (*Snapshot) FullID

func (s *Snapshot) FullID() string

FullID returns the full (64-char) hex representation of the snapshot ID.

func (*Snapshot) ShortID

func (s *Snapshot) ShortID() string

ShortID returns the short (8-char) hex representation of the snapshot ID.

type SnapshotID

type SnapshotID struct {
	Hash Hash
}

SnapshotID uniquely identifies a snapshot by its hash.

type SnapshotManifest

type SnapshotManifest struct {
	Id           []byte   `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`                       // SnapshotID.Hash (32 bytes)
	PrevId       []byte   `protobuf:"bytes,2,opt,name=prev_id,json=prevId,proto3" json:"prev_id,omitempty"` // optional, nil for first commit
	Message      string   `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
	Author       string   `protobuf:"bytes,4,opt,name=author,proto3" json:"author,omitempty"`
	Timestamp    int64    `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
	Tags         []string `protobuf:"bytes,6,rep,name=tags,proto3" json:"tags,omitempty"`
	TotalSize    int64    `protobuf:"varint,7,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"`
	FilesChanged int32    `protobuf:"varint,8,opt,name=files_changed,json=filesChanged,proto3" json:"files_changed,omitempty"` // file count
	// contains filtered or unexported fields
}

SnapshotManifest is a lightweight metadata index for a snapshot, stored separately so ListSnapshots can enumerate snapshots without deserializing the full file list. The Go implementation lives in core/manifest.go with hand-written protowire marshaling (no protoc toolchain required).

func SnapshotToManifest

func SnapshotToManifest(s *Snapshot) *SnapshotManifest

func (*SnapshotManifest) Descriptor deprecated

func (*SnapshotManifest) Descriptor() ([]byte, []int)

Deprecated: Use SnapshotManifest.ProtoReflect.Descriptor instead.

func (*SnapshotManifest) GetAuthor

func (x *SnapshotManifest) GetAuthor() string

func (*SnapshotManifest) GetFilesChanged

func (x *SnapshotManifest) GetFilesChanged() int32

func (*SnapshotManifest) GetId

func (x *SnapshotManifest) GetId() []byte

func (*SnapshotManifest) GetMessage

func (x *SnapshotManifest) GetMessage() string

func (*SnapshotManifest) GetPrevId

func (x *SnapshotManifest) GetPrevId() []byte

func (*SnapshotManifest) GetTags

func (x *SnapshotManifest) GetTags() []string

func (*SnapshotManifest) GetTimestamp

func (x *SnapshotManifest) GetTimestamp() int64

func (*SnapshotManifest) GetTotalSize

func (x *SnapshotManifest) GetTotalSize() int64

func (*SnapshotManifest) ProtoMessage

func (*SnapshotManifest) ProtoMessage()

func (*SnapshotManifest) ProtoReflect

func (x *SnapshotManifest) ProtoReflect() protoreflect.Message

func (*SnapshotManifest) Reset

func (x *SnapshotManifest) Reset()

func (*SnapshotManifest) String

func (x *SnapshotManifest) String() string

type SnapshotProto

type SnapshotProto struct {
	IdHash     []byte            `protobuf:"bytes,1,opt,name=id_hash,json=idHash,proto3" json:"id_hash,omitempty"`                     // 32 bytes
	PrevIdHash []byte            `protobuf:"bytes,2,opt,name=prev_id_hash,json=prevIdHash,proto3,oneof" json:"prev_id_hash,omitempty"` // 32 bytes, nil for first commit
	Message    string            `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
	Author     string            `protobuf:"bytes,4,opt,name=author,proto3" json:"author,omitempty"`
	Timestamp  int64             `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
	Files      []*FileEntryProto `protobuf:"bytes,6,rep,name=files,proto3" json:"files,omitempty"`
	Tags       []string          `protobuf:"bytes,7,rep,name=tags,proto3" json:"tags,omitempty"`
	TotalSize  int64             `protobuf:"varint,8,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"`
	// contains filtered or unexported fields
}

SnapshotProto is the protobuf representation of a snapshot.

func SnapshotToProto

func SnapshotToProto(s *Snapshot, withIDHash bool) *SnapshotProto

SnapshotToProto converts a Snapshot to its protobuf representation.

withIDHash controls whether the IdHash field is populated:

  • false: used when computing the snapshot ID hash (porcelain layer), where the ID is not yet known. Omitting IdHash keeps the hash stable regardless of the (still unassigned) ID.
  • true: used when persisting a snapshot (storage layer), where the ID has already been assigned.

All byte slices are defensively copied so the returned proto does not alias the caller's memory; mutating the proto afterwards cannot corrupt the source Snapshot and vice versa.

func (*SnapshotProto) Descriptor deprecated

func (*SnapshotProto) Descriptor() ([]byte, []int)

Deprecated: Use SnapshotProto.ProtoReflect.Descriptor instead.

func (*SnapshotProto) GetAuthor

func (x *SnapshotProto) GetAuthor() string

func (*SnapshotProto) GetFiles

func (x *SnapshotProto) GetFiles() []*FileEntryProto

func (*SnapshotProto) GetIdHash

func (x *SnapshotProto) GetIdHash() []byte

func (*SnapshotProto) GetMessage

func (x *SnapshotProto) GetMessage() string

func (*SnapshotProto) GetPrevIdHash

func (x *SnapshotProto) GetPrevIdHash() []byte

func (*SnapshotProto) GetTags

func (x *SnapshotProto) GetTags() []string

func (*SnapshotProto) GetTimestamp

func (x *SnapshotProto) GetTimestamp() int64

func (*SnapshotProto) GetTotalSize

func (x *SnapshotProto) GetTotalSize() int64

func (*SnapshotProto) ProtoMessage

func (*SnapshotProto) ProtoMessage()

func (*SnapshotProto) ProtoReflect

func (x *SnapshotProto) ProtoReflect() protoreflect.Message

func (*SnapshotProto) Reset

func (x *SnapshotProto) Reset()

func (*SnapshotProto) String

func (x *SnapshotProto) String() string

type SnapshotSummary

type SnapshotSummary struct {
	ID        SnapshotID
	PrevID    *SnapshotID // nil for the first commit
	Message   string
	Author    string
	Timestamp int64 // unix timestamp
	Tags      []string
	TotalSize int64
}

SnapshotSummary is lightweight snapshot metadata without a file list. ListSnapshots returns summaries so callers that need file details must call GetSnapshot with the summary's ID.

func ManifestToSummary

func ManifestToSummary(m *SnapshotManifest) *SnapshotSummary

ManifestToSummary converts a snapshot manifest to a lightweight summary.

func (*SnapshotSummary) FullID

func (ss *SnapshotSummary) FullID() string

FullID returns the full (64-char) hex representation of the snapshot ID.

func (*SnapshotSummary) ShortID

func (ss *SnapshotSummary) ShortID() string

ShortID returns the short (8-char) hex representation of the snapshot ID.

type UserConfig

type UserConfig struct {
	Name  string
	Email string
}

Jump to

Keyboard shortcuts

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