aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pack_pack.go24
-rw-r--r--repo.go38
2 files changed, 37 insertions, 25 deletions
diff --git a/pack_pack.go b/pack_pack.go
index 5c2c8628..d7b565f5 100644
--- a/pack_pack.go
+++ b/pack_pack.go
@@ -570,3 +570,27 @@ func (pf *packFile) cursor(ofs uint64) (io.Reader, error) {
}
return bytes.NewReader(pf.data[ofs:]), nil
}
+
+func (repo *Repository) packFile(rel string) (*packFile, error) {
+ repo.packFilesMu.RLock()
+ pf, ok := repo.packFiles[rel]
+ repo.packFilesMu.RUnlock()
+ if ok {
+ return pf, nil
+ }
+
+ pf, err := openPackFile(repo.repoPath(rel), rel)
+ if err != nil {
+ return nil, err
+ }
+
+ repo.packFilesMu.Lock()
+ if existing, ok := repo.packFiles[rel]; ok {
+ repo.packFilesMu.Unlock()
+ _ = pf.Close()
+ return existing, nil
+ }
+ repo.packFiles[rel] = pf
+ repo.packFilesMu.Unlock()
+ return pf, nil
+}
diff --git a/repo.go b/repo.go
index 0fdfa5dd..85b4af6b 100644
--- a/repo.go
+++ b/repo.go
@@ -31,8 +31,9 @@ type Repository struct {
midx *multiPackIndex
midxErr error
- packFiles sync.Map // string, *packFile
- closeOnce sync.Once
+ packFiles map[string]*packFile
+ packFilesMu sync.RWMutex
+ closeOnce sync.Once
}
// OpenRepository opens the repository at the provided path.
@@ -82,7 +83,11 @@ func OpenRepository(path string) (*Repository, error) {
return nil, fmt.Errorf("furgit: hash algorithm %q is not supported by the hash functions provided by this build", algo)
}
- return &Repository{rootPath: path, hashSize: hashSize}, nil
+ return &Repository{
+ rootPath: path,
+ hashSize: hashSize,
+ packFiles: make(map[string]*packFile),
+ }, nil
}
// Close closes the repository, releasing any resources associated with it.
@@ -95,16 +100,15 @@ func OpenRepository(path string) (*Repository, error) {
func (repo *Repository) Close() error {
var closeErr error
repo.closeOnce.Do(func() {
- repo.packFiles.Range(func(keya any, pfa any) bool {
- key := keya.(string)
- pf := pfa.(*packFile)
+ repo.packFilesMu.Lock()
+ for key, pf := range repo.packFiles {
err := pf.Close()
if err != nil && closeErr == nil {
closeErr = err
}
- repo.packFiles.Delete(key)
- return true
- })
+ delete(repo.packFiles, key)
+ }
+ repo.packFilesMu.Unlock()
if len(repo.packIdx) > 0 {
for _, idx := range repo.packIdx {
err := idx.Close()
@@ -128,22 +132,6 @@ func (repo *Repository) repoPath(rel string) string {
return filepath.Join(repo.rootPath, rel)
}
-func (repo *Repository) packFile(rel string) (*packFile, error) {
- if pf, ok := repo.packFiles.Load(rel); ok {
- return pf.(*packFile), nil
- }
- pf, err := openPackFile(repo.repoPath(rel), rel)
- if err != nil {
- return nil, err
- }
- actual, loaded := repo.packFiles.LoadOrStore(rel, pf)
- if loaded {
- _ = pf.Close()
- return actual.(*packFile), nil
- }
- return pf, nil
-}
-
// ParseHash converts a hex string into a Hash, validating
// it matches the repository's hash size.
func (repo *Repository) ParseHash(s string) (Hash, error) {