// SPDX-FileCopyrightText: 2025 Romain Maneschi // // SPDX-License-Identifier: EUPL-1.2 package repository import ( "sync" "gitroot.dev/server/logger" ) type repoLocks struct { logger *logger.Logger locks map[string]*repoLock lock sync.Mutex } type repoLock struct { repoName string logger *logger.Logger willWrite sync.Mutex write sync.RWMutex } func newRepoLocks() *repoLocks { return &repoLocks{ logger: logger.NewLogger(logger.REPOSITORY_LOCK), locks: make(map[string]*repoLock), lock: sync.Mutex{}, } } func (rl *repoLocks) get(repoName string) *repoLock { rl.lock.Lock() defer rl.lock.Unlock() _, ok := rl.locks[repoName] if !ok { rl.locks[repoName] = &repoLock{ repoName: repoName, logger: rl.logger, willWrite: sync.Mutex{}, write: sync.RWMutex{}, } } return rl.locks[repoName] } func (rl *repoLocks) Read(repoName string) func() { rl.logger.Debug("ReadLock", logger.NewLoggerPair("repoName", repoName)) l := rl.get(repoName) l.write.RLock() return func() { rl.logger.Debug("ReadUnlock", logger.NewLoggerPair("repoName", repoName)) l.write.RUnlock() } } func (rl *repoLocks) WillWrite(repoName string) *repoLock { l := rl.get(repoName) rl.logger.Debug("WillWrite", logger.NewLoggerPair("repoName", repoName)) l.willWrite.Lock() return l } func (l *repoLock) Close() { l.logger.Debug("WillWrite close", logger.NewLoggerPair("repoName", l.repoName)) l.willWrite.Unlock() } func (l *repoLock) Write() func() { l.logger.Debug("WriteLock", logger.NewLoggerPair("repoName", l.repoName)) l.write.Lock() return func() { l.logger.Debug("WriteUnlock", logger.NewLoggerPair("repoName", l.repoName)) l.write.Unlock() } }