aboutsummaryrefslogtreecommitdiff
path: root/object
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-30 13:53:54 +0000
committerGravatar Runxi Yu2026-03-30 13:54:27 +0000
commit238b2caf83dde3c4395109c51b8c9affa6e11890 (patch)
treee9d946bea08515c2d86954ea617a237710f9f2bf /object
parentobject/store/memory: Remove AddObject, fix lints (diff)
signatureNo signature
object/store/packed: Start the internal/reading split
Diffstat (limited to 'object')
-rw-r--r--object/store/packed/doc.go3
-rw-r--r--object/store/packed/internal/doc.go6
-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.go6
-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.go33
-rw-r--r--object/store/packed/internal/reading/options.go16
-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.go52
-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.go23
-rw-r--r--object/store/packed/options.go10
-rw-r--r--object/store/packed/options_refresh.go11
-rw-r--r--object/store/packed/reader.go65
-rw-r--r--object/store/packed/store.go48
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()
+}