diff options
| author | 2026-03-30 13:53:54 +0000 | |
|---|---|---|
| committer | 2026-03-30 13:54:27 +0000 | |
| commit | 238b2caf83dde3c4395109c51b8c9affa6e11890 (patch) | |
| tree | e9d946bea08515c2d86954ea617a237710f9f2bf | |
| parent | object/store/memory: Remove AddObject, fix lints (diff) | |
| signature | No signature | |
object/store/packed: Start the internal/reading split
| -rw-r--r-- | object/store/packed/doc.go | 3 | ||||
| -rw-r--r-- | object/store/packed/internal/doc.go | 6 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/TODO (renamed from object/store/packed/TODO) | 0 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/close.go (renamed from object/store/packed/close.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/delta_build_chain.go (renamed from object/store/packed/delta_build_chain.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/delta_cache.go (renamed from object/store/packed/delta_cache.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/delta_chain.go (renamed from object/store/packed/delta_chain.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/delta_node.go (renamed from object/store/packed/delta_node.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/delta_resolve_chain.go (renamed from object/store/packed/delta_resolve_chain.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/delta_resolve_chain_start.go (renamed from object/store/packed/delta_resolve_chain_start.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/delta_resolve_content.go (renamed from object/store/packed/delta_resolve_content.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/delta_size.go (renamed from object/store/packed/delta_size.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/doc.go | 6 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/entry_inflate.go (renamed from object/store/packed/entry_inflate.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/entry_meta.go (renamed from object/store/packed/entry_meta.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/entry_parse.go (renamed from object/store/packed/entry_parse.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/helpers_test.go (renamed from object/store/packed/helpers_test.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/idx.go (renamed from object/store/packed/idx.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/idx_candidates_mru.go (renamed from object/store/packed/idx_candidates_mru.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/idx_close.go (renamed from object/store/packed/idx_close.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/idx_lookup.go (renamed from object/store/packed/idx_lookup.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/idx_lookup_candidates.go (renamed from object/store/packed/idx_lookup_candidates.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/idx_open.go (renamed from object/store/packed/idx_open.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/idx_parse.go (renamed from object/store/packed/idx_parse.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/location.go (renamed from object/store/packed/location.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/new.go | 33 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/options.go | 16 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/pack.go (renamed from object/store/packed/pack.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/pack_idx_checksum.go (renamed from object/store/packed/pack_idx_checksum.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/read_bytes.go (renamed from object/store/packed/read_bytes.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/read_closer.go (renamed from object/store/packed/read_closer.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/read_header.go (renamed from object/store/packed/read_header.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/read_header_resolve.go (renamed from object/store/packed/read_header_resolve.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/read_reader.go (renamed from object/store/packed/read_reader.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/read_size.go (renamed from object/store/packed/read_size.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/read_test.go (renamed from object/store/packed/read_test.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/store.go | 52 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/store_lookup.go (renamed from object/store/packed/store_lookup.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/store_open_pack.go (renamed from object/store/packed/store_open_pack.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/internal/reading/trailer_match.go (renamed from object/store/packed/trailer_match.go) | 2 | ||||
| -rw-r--r-- | object/store/packed/new.go | 23 | ||||
| -rw-r--r-- | object/store/packed/options.go | 10 | ||||
| -rw-r--r-- | object/store/packed/options_refresh.go | 11 | ||||
| -rw-r--r-- | object/store/packed/reader.go | 65 | ||||
| -rw-r--r-- | object/store/packed/store.go | 48 |
45 files changed, 236 insertions, 103 deletions
diff --git a/object/store/packed/doc.go b/object/store/packed/doc.go new file mode 100644 index 00000000..252a2baf --- /dev/null +++ b/object/store/packed/doc.go @@ -0,0 +1,3 @@ +// Package packed provides Git object reading from pack/index files under an +// objects/pack directory. +package packed diff --git a/object/store/packed/internal/doc.go b/object/store/packed/internal/doc.go new file mode 100644 index 00000000..05a9c2be --- /dev/null +++ b/object/store/packed/internal/doc.go @@ -0,0 +1,6 @@ +// Package internal encapsulates packed store implementation details. +// +// We have separate internal subpackages for ingest vs read and such, +// because these operations are so different that they almost share +// no code. This makes things clearer. +package internal diff --git a/object/store/packed/TODO b/object/store/packed/internal/reading/TODO index f4a5f48e..f4a5f48e 100644 --- a/object/store/packed/TODO +++ b/object/store/packed/internal/reading/TODO diff --git a/object/store/packed/close.go b/object/store/packed/internal/reading/close.go index 6ad31aac..62c62025 100644 --- a/object/store/packed/close.go +++ b/object/store/packed/internal/reading/close.go @@ -1,4 +1,4 @@ -package packed +package reading // Close releases mapped pack/index resources associated with the store. // diff --git a/object/store/packed/delta_build_chain.go b/object/store/packed/internal/reading/delta_build_chain.go index a528f705..a0e3151d 100644 --- a/object/store/packed/delta_build_chain.go +++ b/object/store/packed/internal/reading/delta_build_chain.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "fmt" diff --git a/object/store/packed/delta_cache.go b/object/store/packed/internal/reading/delta_cache.go index 3bf3a035..4259eb81 100644 --- a/object/store/packed/delta_cache.go +++ b/object/store/packed/internal/reading/delta_cache.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "codeberg.org/lindenii/furgit/internal/lru" diff --git a/object/store/packed/delta_chain.go b/object/store/packed/internal/reading/delta_chain.go index 372e89cd..6e82873e 100644 --- a/object/store/packed/delta_chain.go +++ b/object/store/packed/internal/reading/delta_chain.go @@ -1,4 +1,4 @@ -package packed +package reading import objecttype "codeberg.org/lindenii/furgit/object/type" diff --git a/object/store/packed/delta_node.go b/object/store/packed/internal/reading/delta_node.go index 24ede1e0..56f7b078 100644 --- a/object/store/packed/delta_node.go +++ b/object/store/packed/internal/reading/delta_node.go @@ -1,4 +1,4 @@ -package packed +package reading // deltaNode describes one delta object in a reconstruction chain. type deltaNode struct { diff --git a/object/store/packed/delta_resolve_chain.go b/object/store/packed/internal/reading/delta_resolve_chain.go index 6347ee41..ec9c39e2 100644 --- a/object/store/packed/delta_resolve_chain.go +++ b/object/store/packed/internal/reading/delta_resolve_chain.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "fmt" diff --git a/object/store/packed/delta_resolve_chain_start.go b/object/store/packed/internal/reading/delta_resolve_chain_start.go index ac214576..17274027 100644 --- a/object/store/packed/delta_resolve_chain_start.go +++ b/object/store/packed/internal/reading/delta_resolve_chain_start.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "fmt" diff --git a/object/store/packed/delta_resolve_content.go b/object/store/packed/internal/reading/delta_resolve_content.go index 7b4d5319..71eb69cf 100644 --- a/object/store/packed/delta_resolve_content.go +++ b/object/store/packed/internal/reading/delta_resolve_content.go @@ -1,4 +1,4 @@ -package packed +package reading import objecttype "codeberg.org/lindenii/furgit/object/type" diff --git a/object/store/packed/delta_size.go b/object/store/packed/internal/reading/delta_size.go index e5ba3bb7..8a85fad9 100644 --- a/object/store/packed/delta_size.go +++ b/object/store/packed/internal/reading/delta_size.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "bufio" diff --git a/object/store/packed/internal/reading/doc.go b/object/store/packed/internal/reading/doc.go new file mode 100644 index 00000000..a513d3bd --- /dev/null +++ b/object/store/packed/internal/reading/doc.go @@ -0,0 +1,6 @@ +// Package reading implements the packed-store read path: pack and index +// discovery, lookup, caching, and object reads from existing packfiles. +// +// Obviously, this internal package is not meant to be used by anyone +// other than object/store/packed. +package reading diff --git a/object/store/packed/entry_inflate.go b/object/store/packed/internal/reading/entry_inflate.go index f79d86c0..82b2a7a8 100644 --- a/object/store/packed/entry_inflate.go +++ b/object/store/packed/internal/reading/entry_inflate.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "bytes" diff --git a/object/store/packed/entry_meta.go b/object/store/packed/internal/reading/entry_meta.go index 0bbe8bef..336dc3b9 100644 --- a/object/store/packed/entry_meta.go +++ b/object/store/packed/internal/reading/entry_meta.go @@ -1,4 +1,4 @@ -package packed +package reading // entryMetaAt parses one pack entry header at location. func (store *Store) entryMetaAt(loc location) (*packFile, entryMeta, error) { diff --git a/object/store/packed/entry_parse.go b/object/store/packed/internal/reading/entry_parse.go index 962e39df..ecbfb6cb 100644 --- a/object/store/packed/entry_parse.go +++ b/object/store/packed/internal/reading/entry_parse.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "fmt" diff --git a/object/store/packed/helpers_test.go b/object/store/packed/internal/reading/helpers_test.go index dc02e316..5a37d2f1 100644 --- a/object/store/packed/helpers_test.go +++ b/object/store/packed/internal/reading/helpers_test.go @@ -1,4 +1,4 @@ -package packed_test +package reading_test import ( "fmt" diff --git a/object/store/packed/idx.go b/object/store/packed/internal/reading/idx.go index 5024f2f3..3c91e1a2 100644 --- a/object/store/packed/idx.go +++ b/object/store/packed/internal/reading/idx.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "os" diff --git a/object/store/packed/idx_candidates_mru.go b/object/store/packed/internal/reading/idx_candidates_mru.go index d0cc7052..08ab6f85 100644 --- a/object/store/packed/idx_candidates_mru.go +++ b/object/store/packed/internal/reading/idx_candidates_mru.go @@ -1,4 +1,4 @@ -package packed +package reading // packCandidateNode is one node in the candidate MRU order list. type packCandidateNode struct { diff --git a/object/store/packed/idx_close.go b/object/store/packed/internal/reading/idx_close.go index 814ec987..1590854c 100644 --- a/object/store/packed/idx_close.go +++ b/object/store/packed/internal/reading/idx_close.go @@ -1,4 +1,4 @@ -package packed +package reading import "syscall" diff --git a/object/store/packed/idx_lookup.go b/object/store/packed/internal/reading/idx_lookup.go index 0bd11d1b..bb02fb20 100644 --- a/object/store/packed/idx_lookup.go +++ b/object/store/packed/internal/reading/idx_lookup.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "bytes" diff --git a/object/store/packed/idx_lookup_candidates.go b/object/store/packed/internal/reading/idx_lookup_candidates.go index a2de262a..c89ada7a 100644 --- a/object/store/packed/idx_lookup_candidates.go +++ b/object/store/packed/internal/reading/idx_lookup_candidates.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "fmt" diff --git a/object/store/packed/idx_open.go b/object/store/packed/internal/reading/idx_open.go index fabd0c00..8f73c867 100644 --- a/object/store/packed/idx_open.go +++ b/object/store/packed/internal/reading/idx_open.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "fmt" diff --git a/object/store/packed/idx_parse.go b/object/store/packed/internal/reading/idx_parse.go index 4da3bf42..d38aaf4d 100644 --- a/object/store/packed/idx_parse.go +++ b/object/store/packed/internal/reading/idx_parse.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "encoding/binary" diff --git a/object/store/packed/location.go b/object/store/packed/internal/reading/location.go index 82d17c17..f315dd1d 100644 --- a/object/store/packed/location.go +++ b/object/store/packed/internal/reading/location.go @@ -1,4 +1,4 @@ -package packed +package reading // location identifies one object entry in a specific pack file. type location struct { diff --git a/object/store/packed/internal/reading/new.go b/object/store/packed/internal/reading/new.go new file mode 100644 index 00000000..d8a12db3 --- /dev/null +++ b/object/store/packed/internal/reading/new.go @@ -0,0 +1,33 @@ +package reading + +import ( + "fmt" + "os" + + objectid "codeberg.org/lindenii/furgit/object/id" +) + +// New creates a packed-object store rooted at an objects/pack directory. +// +// Labels: Deps-Borrowed, Life-Parent. +func New(root *os.Root, algo objectid.Algorithm, opts Options) (*Store, error) { + if algo.Size() == 0 { + return nil, objectid.ErrInvalidAlgorithm + } + + switch opts.RefreshPolicy { + case RefreshPolicyOnMissing, RefreshPolicyNever: + default: + return nil, fmt.Errorf("objectstore/packed: invalid refresh policy %d", opts.RefreshPolicy) + } + + return &Store{ + root: root, + algo: algo, + refreshPolicy: opts.RefreshPolicy, + mruNodeByPack: make(map[string]*packCandidateNode), + idxByPack: make(map[string]*idxFile), + packs: make(map[string]*packFile), + deltaCache: newDeltaCache(defaultDeltaCacheMaxBytes), + }, nil +} diff --git a/object/store/packed/internal/reading/options.go b/object/store/packed/internal/reading/options.go new file mode 100644 index 00000000..0c5b76af --- /dev/null +++ b/object/store/packed/internal/reading/options.go @@ -0,0 +1,16 @@ +package reading + +// RefreshPolicy configures when candidate pack/index discovery refreshes. +type RefreshPolicy uint8 + +const ( + // RefreshPolicyOnMissing refreshes candidates once after a lookup miss. + RefreshPolicyOnMissing RefreshPolicy = iota + // RefreshPolicyNever disables automatic refresh after lookup misses. + RefreshPolicyNever +) + +// Options configures a packed object store. +type Options struct { + RefreshPolicy RefreshPolicy +} diff --git a/object/store/packed/pack.go b/object/store/packed/internal/reading/pack.go index 928ced70..431ed5f9 100644 --- a/object/store/packed/pack.go +++ b/object/store/packed/internal/reading/pack.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "encoding/binary" diff --git a/object/store/packed/pack_idx_checksum.go b/object/store/packed/internal/reading/pack_idx_checksum.go index 28d4c3db..b2ad09f1 100644 --- a/object/store/packed/pack_idx_checksum.go +++ b/object/store/packed/internal/reading/pack_idx_checksum.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "bytes" diff --git a/object/store/packed/read_bytes.go b/object/store/packed/internal/reading/read_bytes.go index 222d9a05..f0821687 100644 --- a/object/store/packed/read_bytes.go +++ b/object/store/packed/internal/reading/read_bytes.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "fmt" diff --git a/object/store/packed/read_closer.go b/object/store/packed/internal/reading/read_closer.go index c317d002..4ef4c039 100644 --- a/object/store/packed/read_closer.go +++ b/object/store/packed/internal/reading/read_closer.go @@ -1,4 +1,4 @@ -package packed +package reading import "io" diff --git a/object/store/packed/read_header.go b/object/store/packed/internal/reading/read_header.go index d774de7c..d627a6b3 100644 --- a/object/store/packed/read_header.go +++ b/object/store/packed/internal/reading/read_header.go @@ -1,4 +1,4 @@ -package packed +package reading import ( objectid "codeberg.org/lindenii/furgit/object/id" diff --git a/object/store/packed/read_header_resolve.go b/object/store/packed/internal/reading/read_header_resolve.go index 849cfbc7..a2916b73 100644 --- a/object/store/packed/read_header_resolve.go +++ b/object/store/packed/internal/reading/read_header_resolve.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "fmt" diff --git a/object/store/packed/read_reader.go b/object/store/packed/internal/reading/read_reader.go index 8539e0bf..3fa0f592 100644 --- a/object/store/packed/read_reader.go +++ b/object/store/packed/internal/reading/read_reader.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "bytes" diff --git a/object/store/packed/read_size.go b/object/store/packed/internal/reading/read_size.go index ffec8b13..3c1e05b1 100644 --- a/object/store/packed/read_size.go +++ b/object/store/packed/internal/reading/read_size.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "fmt" diff --git a/object/store/packed/read_test.go b/object/store/packed/internal/reading/read_test.go index 45ee8b01..8a92b603 100644 --- a/object/store/packed/read_test.go +++ b/object/store/packed/internal/reading/read_test.go @@ -1,4 +1,4 @@ -package packed_test +package reading_test import ( "bytes" diff --git a/object/store/packed/internal/reading/store.go b/object/store/packed/internal/reading/store.go new file mode 100644 index 00000000..cb4829ab --- /dev/null +++ b/object/store/packed/internal/reading/store.go @@ -0,0 +1,52 @@ +package reading + +import ( + "os" + "sync" + "sync/atomic" + + objectid "codeberg.org/lindenii/furgit/object/id" + objectstore "codeberg.org/lindenii/furgit/object/store" +) + +// Store reads Git objects from pack/index files under an objects/pack root. +// +// Cached pack/index mappings are retained until Close. +// +// Labels: Close-Caller. +type Store struct { + // root is the borrowed objects/pack capability used for all file access. + root *os.Root + // algo is the expected object ID algorithm for lookups. + algo objectid.Algorithm + // refreshPolicy controls automatic candidate refresh on lookup misses. + refreshPolicy RefreshPolicy + + // candidates stores the latest immutable candidate snapshot. + candidates atomic.Pointer[candidateSnapshot] + // refreshMu serializes candidate refresh. + refreshMu sync.Mutex + // mruMu guards candidate MRU linked-list state. + mruMu sync.RWMutex + // mruHead is the first pack in MRU order. + mruHead *packCandidateNode + // mruTail is the last pack in MRU order. + mruTail *packCandidateNode + // mruNodeByPack maps pack basename to MRU node. + mruNodeByPack map[string]*packCandidateNode + // idxByPack caches opened and parsed indexes by pack basename. + idxByPack map[string]*idxFile + + // stateMu guards pack cache and close state. + stateMu sync.RWMutex + // idxMu guards parsed index cache. + idxMu sync.RWMutex + // cacheMu guards delta cache operations. + cacheMu sync.RWMutex + // packs caches opened .pack handles by basename. + packs map[string]*packFile + // deltaCache caches resolved base objects by pack location. + deltaCache *deltaCache +} + +var _ objectstore.Reader = (*Store)(nil) diff --git a/object/store/packed/store_lookup.go b/object/store/packed/internal/reading/store_lookup.go index 0513caa7..9d863113 100644 --- a/object/store/packed/store_lookup.go +++ b/object/store/packed/internal/reading/store_lookup.go @@ -1,4 +1,4 @@ -package packed +package reading import ( "errors" diff --git a/object/store/packed/store_open_pack.go b/object/store/packed/internal/reading/store_open_pack.go index c621e08c..35cb960a 100644 --- a/object/store/packed/store_open_pack.go +++ b/object/store/packed/internal/reading/store_open_pack.go @@ -1,4 +1,4 @@ -package packed +package reading // openPack returns one opened and validated pack handle. func (store *Store) openPack(name string) (*packFile, error) { diff --git a/object/store/packed/trailer_match.go b/object/store/packed/internal/reading/trailer_match.go index dc43e37d..8c7500b9 100644 --- a/object/store/packed/trailer_match.go +++ b/object/store/packed/internal/reading/trailer_match.go @@ -1,4 +1,4 @@ -package packed +package reading import "fmt" diff --git a/object/store/packed/new.go b/object/store/packed/new.go index 96339f3d..efcdd602 100644 --- a/object/store/packed/new.go +++ b/object/store/packed/new.go @@ -1,33 +1,20 @@ package packed import ( - "fmt" "os" objectid "codeberg.org/lindenii/furgit/object/id" + "codeberg.org/lindenii/furgit/object/store/packed/internal/reading" ) // New creates a packed-object store rooted at an objects/pack directory. // // Labels: Deps-Borrowed, Life-Parent. func New(root *os.Root, algo objectid.Algorithm, opts Options) (*Store, error) { - if algo.Size() == 0 { - return nil, objectid.ErrInvalidAlgorithm + reader, err := reading.New(root, algo, opts.toReadingOptions()) + if err != nil { + return nil, err } - switch opts.RefreshPolicy { - case RefreshPolicyOnMissing, RefreshPolicyNever: - default: - return nil, fmt.Errorf("objectstore/packed: invalid refresh policy %d", opts.RefreshPolicy) - } - - return &Store{ - root: root, - algo: algo, - refreshPolicy: opts.RefreshPolicy, - mruNodeByPack: make(map[string]*packCandidateNode), - idxByPack: make(map[string]*idxFile), - packs: make(map[string]*packFile), - deltaCache: newDeltaCache(defaultDeltaCacheMaxBytes), - }, nil + return &Store{reader: reader}, nil } diff --git a/object/store/packed/options.go b/object/store/packed/options.go index 05cbee30..72c153a1 100644 --- a/object/store/packed/options.go +++ b/object/store/packed/options.go @@ -1,15 +1,5 @@ package packed -// RefreshPolicy configures when candidate pack/index discovery refreshes. -type RefreshPolicy uint8 - -const ( - // RefreshPolicyOnMissing refreshes candidates once after a lookup miss. - RefreshPolicyOnMissing RefreshPolicy = iota - // RefreshPolicyNever disables automatic refresh after lookup misses. - RefreshPolicyNever -) - // Options configures a packed object store. type Options struct { RefreshPolicy RefreshPolicy diff --git a/object/store/packed/options_refresh.go b/object/store/packed/options_refresh.go new file mode 100644 index 00000000..ee3d5f2e --- /dev/null +++ b/object/store/packed/options_refresh.go @@ -0,0 +1,11 @@ +package packed + +// RefreshPolicy configures when candidate pack/index discovery refreshes. +type RefreshPolicy uint8 + +const ( + // RefreshPolicyOnMissing refreshes candidates once after a lookup miss. + RefreshPolicyOnMissing RefreshPolicy = iota + // RefreshPolicyNever disables automatic refresh after lookup misses. + RefreshPolicyNever +) diff --git a/object/store/packed/reader.go b/object/store/packed/reader.go new file mode 100644 index 00000000..45b9e8d9 --- /dev/null +++ b/object/store/packed/reader.go @@ -0,0 +1,65 @@ +package packed + +import ( + "io" + + objectid "codeberg.org/lindenii/furgit/object/id" + objectstore "codeberg.org/lindenii/furgit/object/store" + "codeberg.org/lindenii/furgit/object/store/packed/internal/reading" + objecttype "codeberg.org/lindenii/furgit/object/type" +) + +var _ objectstore.Reader = (*Store)(nil) + +// ReadBytesFull reads a full serialized object as "type size\0content". +func (store *Store) ReadBytesFull(id objectid.ObjectID) ([]byte, error) { + return store.reader.ReadBytesFull(id) +} + +// ReadBytesContent reads an object's type and content bytes. +func (store *Store) ReadBytesContent(id objectid.ObjectID) (objecttype.Type, []byte, error) { + return store.reader.ReadBytesContent(id) +} + +// ReadReaderFull reads a full serialized object stream as "type size\0content". +func (store *Store) ReadReaderFull(id objectid.ObjectID) (io.ReadCloser, error) { + return store.reader.ReadReaderFull(id) +} + +// ReadReaderContent reads an object's type, declared content length, and +// content stream. +func (store *Store) ReadReaderContent(id objectid.ObjectID) (objecttype.Type, int64, io.ReadCloser, error) { + return store.reader.ReadReaderContent(id) +} + +// ReadSize reads an object's declared content length. +func (store *Store) ReadSize(id objectid.ObjectID) (int64, error) { + return store.reader.ReadSize(id) +} + +// ReadHeader reads an object's type and declared content length. +func (store *Store) ReadHeader(id objectid.ObjectID) (objecttype.Type, int64, error) { + return store.reader.ReadHeader(id) +} + +// Refresh updates the packed-store view of on-disk pack/index candidates. +func (store *Store) Refresh() error { + return store.reader.Refresh() +} + +func (opts Options) toReadingOptions() reading.Options { + var refreshPolicy reading.RefreshPolicy + + switch opts.RefreshPolicy { + case RefreshPolicyOnMissing: + refreshPolicy = reading.RefreshPolicyOnMissing + case RefreshPolicyNever: + refreshPolicy = reading.RefreshPolicyNever + default: + refreshPolicy = reading.RefreshPolicy(opts.RefreshPolicy) + } + + return reading.Options{ + RefreshPolicy: refreshPolicy, + } +} diff --git a/object/store/packed/store.go b/object/store/packed/store.go index 233b3fec..321e0c2c 100644 --- a/object/store/packed/store.go +++ b/object/store/packed/store.go @@ -1,53 +1,17 @@ -// Package packed provides packfile reading and associated indexes. package packed import ( - "os" - "sync" - "sync/atomic" - - objectid "codeberg.org/lindenii/furgit/object/id" - objectstore "codeberg.org/lindenii/furgit/object/store" + "codeberg.org/lindenii/furgit/object/store/packed/internal/reading" ) // Store reads Git objects from pack/index files under an objects/pack root. // -// Cached pack/index mappings are retained until Close. -// // Labels: Close-Caller. type Store struct { - // root is the borrowed objects/pack capability used for all file access. - root *os.Root - // algo is the expected object ID algorithm for lookups. - algo objectid.Algorithm - // refreshPolicy controls automatic candidate refresh on lookup misses. - refreshPolicy RefreshPolicy - - // candidates stores the latest immutable candidate snapshot. - candidates atomic.Pointer[candidateSnapshot] - // refreshMu serializes candidate refresh. - refreshMu sync.Mutex - // mruMu guards candidate MRU linked-list state. - mruMu sync.RWMutex - // mruHead is the first pack in MRU order. - mruHead *packCandidateNode - // mruTail is the last pack in MRU order. - mruTail *packCandidateNode - // mruNodeByPack maps pack basename to MRU node. - mruNodeByPack map[string]*packCandidateNode - // idxByPack caches opened and parsed indexes by pack basename. - idxByPack map[string]*idxFile - - // stateMu guards pack cache and close state. - stateMu sync.RWMutex - // idxMu guards parsed index cache. - idxMu sync.RWMutex - // cacheMu guards delta cache operations. - cacheMu sync.RWMutex - // packs caches opened .pack handles by basename. - packs map[string]*packFile - // deltaCache caches resolved base objects by pack location. - deltaCache *deltaCache + reader *reading.Store } -var _ objectstore.Reader = (*Store)(nil) +// Close releases mapped pack/index resources associated with the store. +func (store *Store) Close() error { + return store.reader.Close() +} |
