From 108038ef47a808df9f1bbd4ccefc9e99cf9e635b 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=D1=8B=D1=87=D0=AA=20=D0=A5=D1=80=D0=B0=D0=BC=D0=BE?= =?UTF-8?q?=D0=B2?= Date: Thu, 12 Feb 2026 17:58:28 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D0=B0=D0=BA=D0=B5=D1=82=D0=BE=D0=B2=20=D0=B4?= =?UTF-8?q?=D1=80=D1=83=D0=B3=D0=BE=D0=B9=20=D0=B0=D1=80=D1=85=D0=B8=D1=82?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D1=83=D1=80=D1=8B=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B5=20RPM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/build/script_executor.go | 20 ++++++++++++++++---- internal/build/utils.go | 16 ++++++++++++++++ internal/build/utils_test.go | 23 +++++++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/internal/build/script_executor.go b/internal/build/script_executor.go index d73b200..f4513fa 100644 --- a/internal/build/script_executor.go +++ b/internal/build/script_executor.go @@ -35,6 +35,7 @@ import ( "mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/syntax" + "gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu" finddeps "gitea.plemya-x.ru/Plemya-x/ALR/internal/build/find_deps" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers" @@ -242,17 +243,28 @@ func buildPkgMetadata( pkgInfo.Homepage = vars.Homepage.Resolved() pkgInfo.License = strings.Join(vars.Licenses, ", ") pkgInfo.Maintainer = vars.Maintainer.Resolved() + + pkgFormat := input.PkgFormat() + info := input.OSRelease() + + // Для RPM на multilib-системах квалифицируем автоконфликт архитектурой (ISA), + // чтобы не удалять пакеты другой архитектуры. Например, установка + // libdrm+alr.x86_64 не должна конфликтовать с libdrm.i686. + autoConflictName := vars.Name + if pkgFormat == "rpm" { + if isa := goArchToRPMISA(cpu.Arch()); isa != "" { + autoConflictName = fmt.Sprintf("%s(%s)", vars.Name, isa) + } + } + pkgInfo.Overridables = nfpm.Overridables{ - Conflicts: append(vars.Conflicts, vars.Name), + Conflicts: append(vars.Conflicts, autoConflictName), Replaces: vars.Replaces, Provides: append(vars.Provides, vars.Name), Depends: deps, } pkgInfo.Section = vars.Group.Resolved() - pkgFormat := input.PkgFormat() - info := input.OSRelease() - if pkgFormat == "apk" { // Alpine отказывается устанавливать пакеты, которые предоставляют сами себя, поэтому удаляем такие элементы pkgInfo.Overridables.Provides = slices.DeleteFunc(pkgInfo.Overridables.Provides, func(s string) bool { diff --git a/internal/build/utils.go b/internal/build/utils.go index b30b1a9..0b66d98 100644 --- a/internal/build/utils.go +++ b/internal/build/utils.go @@ -180,6 +180,22 @@ func normalizeContents(contents []*files.Content) { var RegexpALRPackageName = regexp.MustCompile(`^(?P[^+]+)\+(?P.+)$`) +// goArchToRPMISA конвертирует Go-архитектуру в RPM ISA (Instruction Set Architecture) +// квалификатор, используемый в спецификациях зависимостей (например, "x86-64" для amd64). +// Возвращает пустую строку, если ISA квалификатор неизвестен для данной архитектуры. +func goArchToRPMISA(goarch string) string { + switch goarch { + case "amd64": + return "x86-64" + case "386": + return "x86-32" + case "arm64": + return "aarch-64" + default: + return "" + } +} + func getBasePkgInfo(vars *alrsh.Package, input interface { RepositoryProvider OsInfoProvider diff --git a/internal/build/utils_test.go b/internal/build/utils_test.go index cb0900e..d5e190f 100644 --- a/internal/build/utils_test.go +++ b/internal/build/utils_test.go @@ -157,6 +157,29 @@ func TestRegexpALRPackageName(t *testing.T) { } } +func TestGoArchToRPMISA(t *testing.T) { + tests := []struct { + goarch string + expected string + }{ + {"amd64", "x86-64"}, + {"386", "x86-32"}, + {"arm64", "aarch-64"}, + {"arm", ""}, + {"mips", ""}, + {"unknown", ""}, + } + + for _, tt := range tests { + t.Run(tt.goarch, func(t *testing.T) { + result := goArchToRPMISA(tt.goarch) + if result != tt.expected { + t.Errorf("goArchToRPMISA(%q) = %q, ожидается %q", tt.goarch, result, tt.expected) + } + }) + } +} + func TestExtractRepoNameFromPath(t *testing.T) { tests := []struct { name string