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