Documentation
¶
Index ¶
- Constants
- Variables
- type Chunk
- type ChunkFlag
- type Config
- type CoreConfig
- type FileEntry
- type FileEntryProto
- func (*FileEntryProto) Descriptor() ([]byte, []int)deprecated
- func (x *FileEntryProto) GetChunkHashes() [][]byte
- func (x *FileEntryProto) GetExtra() map[string]string
- func (x *FileEntryProto) GetFileHash() []byte
- func (x *FileEntryProto) GetMimeType() string
- func (x *FileEntryProto) GetModTime() int64
- func (x *FileEntryProto) GetMode() uint32
- func (x *FileEntryProto) GetPath() string
- func (x *FileEntryProto) GetSize() int64
- func (*FileEntryProto) ProtoMessage()
- func (x *FileEntryProto) ProtoReflect() protoreflect.Message
- func (x *FileEntryProto) Reset()
- func (x *FileEntryProto) String() string
- type FileMetadata
- type FileMode
- type Hash
- type Index
- type IndexEntry
- type IndexEntryProto
- func (*IndexEntryProto) Descriptor() ([]byte, []int)deprecated
- func (x *IndexEntryProto) GetChunkHashes() [][]byte
- func (x *IndexEntryProto) GetHash() []byte
- func (x *IndexEntryProto) GetModTime() int64
- func (x *IndexEntryProto) GetPath() string
- func (x *IndexEntryProto) GetSize() int64
- func (*IndexEntryProto) ProtoMessage()
- func (x *IndexEntryProto) ProtoReflect() protoreflect.Message
- func (x *IndexEntryProto) Reset()
- func (x *IndexEntryProto) String() string
- type IndexProto
- func (*IndexProto) Descriptor() ([]byte, []int)deprecated
- func (x *IndexProto) GetEntries() []*IndexEntryProto
- func (x *IndexProto) GetUpdatedAt() int64
- func (*IndexProto) ProtoMessage()
- func (x *IndexProto) ProtoReflect() protoreflect.Message
- func (x *IndexProto) Reset()
- func (x *IndexProto) String() string
- type RefType
- type Reference
- type Snapshot
- type SnapshotID
- type SnapshotManifest
- func (*SnapshotManifest) Descriptor() ([]byte, []int)deprecated
- func (x *SnapshotManifest) GetAuthor() string
- func (x *SnapshotManifest) GetFilesChanged() int32
- func (x *SnapshotManifest) GetId() []byte
- func (x *SnapshotManifest) GetMessage() string
- func (x *SnapshotManifest) GetPrevId() []byte
- func (x *SnapshotManifest) GetTags() []string
- func (x *SnapshotManifest) GetTimestamp() int64
- func (x *SnapshotManifest) GetTotalSize() int64
- func (*SnapshotManifest) ProtoMessage()
- func (x *SnapshotManifest) ProtoReflect() protoreflect.Message
- func (x *SnapshotManifest) Reset()
- func (x *SnapshotManifest) String() string
- type SnapshotProto
- func (*SnapshotProto) Descriptor() ([]byte, []int)deprecated
- func (x *SnapshotProto) GetAuthor() string
- func (x *SnapshotProto) GetFiles() []*FileEntryProto
- func (x *SnapshotProto) GetIdHash() []byte
- func (x *SnapshotProto) GetMessage() string
- func (x *SnapshotProto) GetPrevIdHash() []byte
- func (x *SnapshotProto) GetTags() []string
- func (x *SnapshotProto) GetTimestamp() int64
- func (x *SnapshotProto) GetTotalSize() int64
- func (*SnapshotProto) ProtoMessage()
- func (x *SnapshotProto) ProtoReflect() protoreflect.Message
- func (x *SnapshotProto) Reset()
- func (x *SnapshotProto) String() string
- type SnapshotSummary
- type UserConfig
Constants ¶
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.
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().
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.
const HashSize = 32
HashSize is the length of a Hash in bytes.
const HeaderPeekSize = 512
Variables ¶
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.
var File_index_proto protoreflect.FileDescriptor
var File_snapshot_proto protoreflect.FileDescriptor
Functions ¶
This section is empty.
Types ¶
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 ¶
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 ¶
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 ¶
IsDevice returns true if the file mode represents a block or character device.
func (FileMode) IsNamedPipe ¶
IsNamedPipe returns true if the file mode represents a FIFO (named pipe).
type Hash ¶
type Hash [32]byte
Hash is a BLAKE3 hash (32 bytes).
func BytesToHash ¶
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 ¶
FullString returns the full 64-character hex representation.
type Index ¶
type Index struct {
Entries []IndexEntry
UpdatedAt int64
}
Index represents the staging area for tracking file changes.
type IndexEntry ¶
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 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.
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.