From b8e35570f830ea83ed7cf2e037429e44ddf48135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=B2=D0=B3=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=A5=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=BE=D0=B2?= Date: Thu, 6 Nov 2025 20:03:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5:=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BC=D1=8C=D1=8E=D1=82=D0=B5=D0=BA=D1=81=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8=20=D0=B8=20=D0=BF=D1=80=D0=B0=D0=B2=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BE=D1=81=D1=82=D1=83=D0=BF=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/builtins/updater.go | 49 +++++++++++++++++++++-------- internal/permissions/permissions.go | 30 ++++++++++++++++-- 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/internal/builtins/updater.go b/internal/builtins/updater.go index 8b354d7..e634429 100644 --- a/internal/builtins/updater.go +++ b/internal/builtins/updater.go @@ -52,9 +52,23 @@ func updaterModule(cfg *config.Config) *starlarkstruct.Module { } } -// repoMtx makes sure two starlark threads can -// never access the repo at the same time -var repoMtx = &sync.Mutex{} +// repoMtxMap provides a mutex for each repository to avoid blocking +// operations on one repo from affecting another +var repoMtxMap = make(map[string]*sync.Mutex) +var repoMtxMapMtx = &sync.Mutex{} // protects the map itself + +func getRepoMutex(repoName string) *sync.Mutex { + repoMtxMapMtx.Lock() + defer repoMtxMapMtx.Unlock() + + mtx, exists := repoMtxMap[repoName] + if !exists { + mtx = &sync.Mutex{} + repoMtxMap[repoName] = mtx + } + + return mtx +} func updaterPull(cfg *config.Config) *starlark.Builtin { return starlark.NewBuiltin("updater.pull", func(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { @@ -69,8 +83,9 @@ func updaterPull(cfg *config.Config) *starlark.Builtin { return nil, fmt.Errorf("repository '%s' not found in configuration", repoName) } - repoMtx.Lock() - defer repoMtx.Unlock() + mtx := getRepoMutex(repoName) + mtx.Lock() + defer mtx.Unlock() repoDir := filepath.Join(cfg.ReposBaseDir, repoName) repo, err := git.PlainOpen(repoDir) @@ -113,8 +128,9 @@ func updaterPushChanges(cfg *config.Config) *starlark.Builtin { return nil, fmt.Errorf("repository '%s' not found in configuration", repoName) } - repoMtx.Lock() - defer repoMtx.Unlock() + mtx := getRepoMutex(repoName) + mtx.Lock() + defer mtx.Unlock() repoDir := filepath.Join(cfg.ReposBaseDir, repoName) repo, err := git.PlainOpen(repoDir) @@ -192,8 +208,12 @@ func getPackageFile(cfg *config.Config) *starlark.Builtin { return nil, fmt.Errorf("repository '%s' not found in configuration", repoName) } - repoMtx.Lock() - defer repoMtx.Unlock() + // Для этой функции мы не обязательно нуждаемся в мьютексе Git, + // так как это только чтение файлов, а не Git операции + // Но для консистентности и безопасности будем использовать мьютекс + mtx := getRepoMutex(repoName) + mtx.Lock() + defer mtx.Unlock() repoDir := filepath.Join(cfg.ReposBaseDir, repoName) path := filepath.Join(repoDir, pkg, filename) @@ -220,8 +240,10 @@ func writePackageFile(cfg *config.Config) *starlark.Builtin { return nil, fmt.Errorf("repository '%s' not found in configuration", repoName) } - repoMtx.Lock() - defer repoMtx.Unlock() + // Используем мьютекс для согласованности с другими операциями + mtx := getRepoMutex(repoName) + mtx.Lock() + defer mtx.Unlock() repoDir := filepath.Join(cfg.ReposBaseDir, repoName) path := filepath.Join(repoDir, pkg, filename) @@ -345,8 +367,9 @@ func updateChecksums(cfg *config.Config) *starlark.Builtin { updatedContent := updateChecksumsInContent(content, checksumStrings) // Автоматически сбрасываем release='1' при изменении версии - repoMtx.Lock() - defer repoMtx.Unlock() + mtx := getRepoMutex(repoName) + mtx.Lock() + defer mtx.Unlock() repoDir := filepath.Join(cfg.ReposBaseDir, repoName) path := filepath.Join(repoDir, pkg, filename) diff --git a/internal/permissions/permissions.go b/internal/permissions/permissions.go index 6c9c082..2a28102 100644 --- a/internal/permissions/permissions.go +++ b/internal/permissions/permissions.go @@ -103,7 +103,26 @@ func FixRepoPermissions(path string) error { // Получаем UID и GID для alr-updater:wheel uid, gid, err := getAlrUpdaterIDs() if err != nil { - return fmt.Errorf("failed to get alr-updater IDs: %w", err) + // Если не можем получить ID (например, в dev-окружении), только устанавливаем права + return filepath.Walk(path, func(filePath string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() { + // Устанавливаем права 2775 для директорий (setgid) + if err := os.Chmod(filePath, 0o2775); err != nil { + return fmt.Errorf("failed to chmod directory %s: %w", filePath, err) + } + } else { + // Устанавливаем права 664 для файлов + if err := os.Chmod(filePath, 0o664); err != nil { + return fmt.Errorf("failed to chmod file %s: %w", filePath, err) + } + } + + return nil + }) } return filepath.Walk(path, func(filePath string, info os.FileInfo, err error) error { @@ -113,7 +132,14 @@ func FixRepoPermissions(path string) error { // Изменяем владельца на alr-updater:wheel if err := os.Chown(filePath, uid, gid); err != nil { - return fmt.Errorf("failed to chown %s: %w", filePath, err) + // Если не удалось изменить владельца (недостаточно прав), всё равно устанавливаем права + if info.IsDir() { + _ = os.Chmod(filePath, 0o2775) + return fmt.Errorf("failed to chown directory %s: %w", filePath, err) + } else { + _ = os.Chmod(filePath, 0o664) + return fmt.Errorf("failed to chown file %s: %w", filePath, err) + } } if info.IsDir() {