diff options
| -rw-r--r-- | pack_pack.go | 24 | ||||
| -rw-r--r-- | repo.go | 38 |
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 +} @@ -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) { |
