diff --git a/assets/coverage-badge.svg b/assets/coverage-badge.svg
index ffdf7ae..2a6facc 100644
--- a/assets/coverage-badge.svg
+++ b/assets/coverage-badge.svg
@@ -11,7 +11,7 @@
coverage
coverage
- 19.4%
- 19.4%
+ 19.2%
+ 19.2%
diff --git a/e2e-tests/common_test.go b/e2e-tests/common_test.go
index 51466a1..e346a9f 100644
--- a/e2e-tests/common_test.go
+++ b/e2e-tests/common_test.go
@@ -100,13 +100,19 @@ func e2eSpawn(runnable e2e.Runnable, command e2e.Command, timeout time.Duration,
var ALL_SYSTEMS []string = []string{
"ubuntu-24.04",
- // "alt-sisyphus",
+ "alt-sisyphus",
+ "fedora-41",
// "archlinux",
// "alpine",
// "opensuse-leap",
// "redos-8",
}
+var AUTOREQ_AUTOPROV_SYSTEMS []string = []string{
+ "alt-sisyphus",
+ "fedora-41",
+}
+
var COMMON_SYSTEMS []string = []string{
"ubuntu-24.04",
}
diff --git a/e2e-tests/images/Dockerfile.alt-sisyphus b/e2e-tests/images/Dockerfile.alt-sisyphus
index 3f7cf1b..cc48dee 100644
--- a/e2e-tests/images/Dockerfile.alt-sisyphus
+++ b/e2e-tests/images/Dockerfile.alt-sisyphus
@@ -1,5 +1,6 @@
FROM registry.altlinux.org/sisyphus/alt:latest
-RUN apt-get update && apt-get install -y ca-certificates
+RUN apt-get update && apt-get install -y ca-certificates rpm-build
RUN useradd -m -s /bin/bash alr-user
USER alr-user
+WORKDIR /home/alr-user
ENTRYPOINT ["tail", "-f", "/dev/null"]
\ No newline at end of file
diff --git a/e2e-tests/images/Dockerfile.fedora-41 b/e2e-tests/images/Dockerfile.fedora-41
new file mode 100644
index 0000000..d213964
--- /dev/null
+++ b/e2e-tests/images/Dockerfile.fedora-41
@@ -0,0 +1,8 @@
+FROM fedora:41
+RUN dnf install -y ca-certificates sudo rpm-build
+RUN useradd -m -s /bin/bash alr-user && \
+ echo "alr-user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/alr-user && \
+ chmod 0440 /etc/sudoers.d/alr-user
+USER alr-user
+WORKDIR /home/alr-user
+ENTRYPOINT ["tail", "-f", "/dev/null"]
\ No newline at end of file
diff --git a/e2e-tests/issue_41_autoreq_skiplist_test.go b/e2e-tests/issue_41_autoreq_skiplist_test.go
new file mode 100644
index 0000000..79d2d3d
--- /dev/null
+++ b/e2e-tests/issue_41_autoreq_skiplist_test.go
@@ -0,0 +1,80 @@
+// ALR - Any Linux Repository
+// Copyright (C) 2025 Евгений Храмов
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+//go:build e2e
+
+package e2etests_test
+
+import (
+ "testing"
+
+ "github.com/alecthomas/assert/v2"
+ "github.com/efficientgo/e2e"
+)
+
+func TestE2EIssue41AutoreqSkiplist(t *testing.T) {
+ dockerMultipleRun(
+ t,
+ "issue-41-autoreq-skiplist",
+ AUTOREQ_AUTOPROV_SYSTEMS,
+ func(t *testing.T, r e2e.Runnable) {
+ err := r.Exec(e2e.NewCommand(
+ "alr",
+ "addrepo",
+ "--name",
+ "alr-repo",
+ "--url",
+ "https://gitea.plemya-x.ru/Maks1mS/repo-for-tests.git",
+ ))
+ assert.NoError(t, err)
+
+ err = r.Exec(e2e.NewCommand(
+ "alr",
+ "ref",
+ ))
+ assert.NoError(t, err)
+
+ err = r.Exec(e2e.NewCommand(
+ "alr",
+ "build",
+ "-p",
+ "alr-repo/test-autoreq-autoprov",
+ ))
+ assert.NoError(t, err)
+
+ err = r.Exec(e2e.NewCommand(
+ "sh",
+ "-c",
+ "rpm -qp --requires *.rpm | grep \"^/bin/sh$\"",
+ ))
+ assert.NoError(t, err)
+
+ err = r.Exec(e2e.NewCommand(
+ "sh",
+ "-c",
+ "rpm -qp --requires *.rpm | grep \"^/bin/bash$\"",
+ ))
+ assert.Error(t, err)
+
+ err = r.Exec(e2e.NewCommand(
+ "sh",
+ "-c",
+ "rpm -qp --requires *.rpm | grep \"^/bin/zsh$\"",
+ ))
+ assert.Error(t, err)
+ },
+ )
+}
diff --git a/internal/shutils/decoder/decoder.go b/internal/shutils/decoder/decoder.go
index c89bfb4..b6f7d05 100644
--- a/internal/shutils/decoder/decoder.go
+++ b/internal/shutils/decoder/decoder.go
@@ -123,15 +123,29 @@ func (d *Decoder) DecodeVars(val any) error {
}
rVal := reflect.ValueOf(val).Elem()
+ return d.decodeStruct(rVal)
+}
+func (d *Decoder) decodeStruct(rVal reflect.Value) error {
for i := 0; i < rVal.NumField(); i++ {
field := rVal.Field(i)
fieldType := rVal.Type().Field(i)
+ // Пропускаем неэкспортируемые поля
if !fieldType.IsExported() {
continue
}
+ // Обрабатываем встроенные поля рекурсивно
+ if fieldType.Anonymous {
+ if field.Kind() == reflect.Struct {
+ if err := d.decodeStruct(field); err != nil {
+ return err
+ }
+ }
+ continue
+ }
+
name := fieldType.Name
tag := fieldType.Tag.Get("sh")
required := false
@@ -160,7 +174,6 @@ func (d *Decoder) DecodeVars(val any) error {
field.Set(newVal.Elem())
}
-
return nil
}
diff --git a/internal/translations/default.pot b/internal/translations/default.pot
index e199ee8..19526d6 100644
--- a/internal/translations/default.pot
+++ b/internal/translations/default.pot
@@ -337,92 +337,92 @@ msgstr ""
msgid "Error while running app"
msgstr ""
-#: pkg/build/build.go:156
+#: pkg/build/build.go:157
msgid "Failed to prompt user to view build script"
msgstr ""
-#: pkg/build/build.go:160
+#: pkg/build/build.go:161
msgid "Building package"
msgstr ""
-#: pkg/build/build.go:208
+#: pkg/build/build.go:209
msgid "The checksums array must be the same length as sources"
msgstr ""
-#: pkg/build/build.go:235
+#: pkg/build/build.go:238
msgid "Downloading sources"
msgstr ""
-#: pkg/build/build.go:257
+#: pkg/build/build.go:260
msgid "Building package metadata"
msgstr ""
-#: pkg/build/build.go:279
+#: pkg/build/build.go:282
msgid "Compressing package"
msgstr ""
-#: pkg/build/build.go:438
+#: pkg/build/build.go:441
msgid ""
"Your system's CPU architecture doesn't match this package. Do you want to "
"build anyway?"
msgstr ""
-#: pkg/build/build.go:452
+#: pkg/build/build.go:455
msgid "This package is already installed"
msgstr ""
-#: pkg/build/build.go:476
+#: pkg/build/build.go:479
msgid "Installing build dependencies"
msgstr ""
-#: pkg/build/build.go:521
+#: pkg/build/build.go:524
msgid "Installing dependencies"
msgstr ""
-#: pkg/build/build.go:602
+#: pkg/build/build.go:605
msgid "Would you like to remove the build dependencies?"
msgstr ""
-#: pkg/build/build.go:665
+#: pkg/build/build.go:668
msgid "Executing prepare()"
msgstr ""
-#: pkg/build/build.go:675
+#: pkg/build/build.go:678
msgid "Executing build()"
msgstr ""
-#: pkg/build/build.go:705 pkg/build/build.go:725
+#: pkg/build/build.go:708 pkg/build/build.go:728
msgid "Executing %s()"
msgstr ""
-#: pkg/build/build.go:784
+#: pkg/build/build.go:787
msgid "Error installing native packages"
msgstr ""
-#: pkg/build/build.go:808
+#: pkg/build/build.go:811
msgid "Error installing package"
msgstr ""
-#: pkg/build/build.go:867
-msgid "AutoProv is not implemented for this package format, so it's skipped"
-msgstr ""
-
-#: pkg/build/build.go:878
-msgid "AutoReq is not implemented for this package format, so it's skipped"
-msgstr ""
-
-#: pkg/build/findDeps.go:35
+#: pkg/build/find_deps/alt_linux.go:35
msgid "Command not found on the system"
msgstr ""
-#: pkg/build/findDeps.go:82
+#: pkg/build/find_deps/alt_linux.go:86
msgid "Provided dependency found"
msgstr ""
-#: pkg/build/findDeps.go:89
+#: pkg/build/find_deps/alt_linux.go:93
msgid "Required dependency found"
msgstr ""
+#: pkg/build/find_deps/empty.go:32
+msgid "AutoProv is not implemented for this package format, so it's skipped"
+msgstr ""
+
+#: pkg/build/find_deps/empty.go:37
+msgid "AutoReq is not implemented for this package format, so it's skipped"
+msgstr ""
+
#: pkg/repos/pull.go:79
msgid "Pulling repository"
msgstr ""
diff --git a/internal/translations/po/ru/default.po b/internal/translations/po/ru/default.po
index bb2f1f1..3b242ed 100644
--- a/internal/translations/po/ru/default.po
+++ b/internal/translations/po/ru/default.po
@@ -349,31 +349,31 @@ msgstr "Показать справку"
msgid "Error while running app"
msgstr "Ошибка при запуске приложения"
-#: pkg/build/build.go:156
+#: pkg/build/build.go:157
msgid "Failed to prompt user to view build script"
msgstr "Не удалось предложить пользователю просмотреть скрипт сборки"
-#: pkg/build/build.go:160
+#: pkg/build/build.go:161
msgid "Building package"
msgstr "Сборка пакета"
-#: pkg/build/build.go:208
+#: pkg/build/build.go:209
msgid "The checksums array must be the same length as sources"
msgstr "Массив контрольных сумм должен быть той же длины, что и источники"
-#: pkg/build/build.go:235
+#: pkg/build/build.go:238
msgid "Downloading sources"
msgstr "Скачивание источников"
-#: pkg/build/build.go:257
+#: pkg/build/build.go:260
msgid "Building package metadata"
msgstr "Сборка метаданных пакета"
-#: pkg/build/build.go:279
+#: pkg/build/build.go:282
msgid "Compressing package"
msgstr "Сжатие пакета"
-#: pkg/build/build.go:438
+#: pkg/build/build.go:441
msgid ""
"Your system's CPU architecture doesn't match this package. Do you want to "
"build anyway?"
@@ -381,64 +381,64 @@ msgstr ""
"Архитектура процессора вашей системы не соответствует этому пакету. Вы все "
"равно хотите выполнить сборку?"
-#: pkg/build/build.go:452
+#: pkg/build/build.go:455
msgid "This package is already installed"
msgstr "Этот пакет уже установлен"
-#: pkg/build/build.go:476
+#: pkg/build/build.go:479
msgid "Installing build dependencies"
msgstr "Установка зависимостей сборки"
-#: pkg/build/build.go:521
+#: pkg/build/build.go:524
msgid "Installing dependencies"
msgstr "Установка зависимостей"
-#: pkg/build/build.go:602
+#: pkg/build/build.go:605
msgid "Would you like to remove the build dependencies?"
msgstr "Хотели бы вы удалить зависимости сборки?"
-#: pkg/build/build.go:665
+#: pkg/build/build.go:668
msgid "Executing prepare()"
msgstr "Исполнение prepare()"
-#: pkg/build/build.go:675
+#: pkg/build/build.go:678
msgid "Executing build()"
msgstr "Исполнение build()"
-#: pkg/build/build.go:705 pkg/build/build.go:725
+#: pkg/build/build.go:708 pkg/build/build.go:728
msgid "Executing %s()"
msgstr "Исполнение %s()"
-#: pkg/build/build.go:784
+#: pkg/build/build.go:787
msgid "Error installing native packages"
msgstr "Ошибка при установке нативных пакетов"
-#: pkg/build/build.go:808
+#: pkg/build/build.go:811
msgid "Error installing package"
msgstr "Ошибка при установке пакета"
-#: pkg/build/build.go:867
+#: pkg/build/find_deps/alt_linux.go:35
+msgid "Command not found on the system"
+msgstr "Команда не найдена в системе"
+
+#: pkg/build/find_deps/alt_linux.go:86
+msgid "Provided dependency found"
+msgstr "Найденная предоставленная зависимость"
+
+#: pkg/build/find_deps/alt_linux.go:93
+msgid "Required dependency found"
+msgstr "Найдена требуемая зависимость"
+
+#: pkg/build/find_deps/empty.go:32
msgid "AutoProv is not implemented for this package format, so it's skipped"
msgstr ""
"AutoProv не реализовано для этого формата пакета, поэтому будет пропущено"
-#: pkg/build/build.go:878
+#: pkg/build/find_deps/empty.go:37
msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr ""
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
-#: pkg/build/findDeps.go:35
-msgid "Command not found on the system"
-msgstr "Команда не найдена в системе"
-
-#: pkg/build/findDeps.go:82
-msgid "Provided dependency found"
-msgstr "Найденная предоставленная зависимость"
-
-#: pkg/build/findDeps.go:89
-msgid "Required dependency found"
-msgstr "Найдена требуемая зависимость"
-
#: pkg/repos/pull.go:79
msgid "Pulling repository"
msgstr "Скачивание репозитория"
diff --git a/internal/types/build.go b/internal/types/build.go
index 6b5c6c9..51999ef 100644
--- a/internal/types/build.go
+++ b/internal/types/build.go
@@ -31,79 +31,44 @@ type BuildOpts struct {
}
type BuildVarsPre struct {
- Version string `sh:"version,required"`
- Release int `sh:"release,required"`
- Epoch uint `sh:"epoch"`
- Description string `sh:"desc"`
- Homepage string `sh:"homepage"`
- Maintainer string `sh:"maintainer"`
- Architectures []string `sh:"architectures"`
- Licenses []string `sh:"license"`
- Provides []string `sh:"provides"`
- Conflicts []string `sh:"conflicts"`
- Depends []string `sh:"deps"`
- BuildDepends []string `sh:"build_deps"`
- OptDepends []string `sh:"opt_deps"`
- Replaces []string `sh:"replaces"`
- Sources []string `sh:"sources"`
- Checksums []string `sh:"checksums"`
- Backup []string `sh:"backup"`
- Scripts Scripts `sh:"scripts"`
- AutoReq []string `sh:"auto_req"`
- AutoProv []string `sh:"auto_prov"`
+ Version string `sh:"version,required"`
+ Release int `sh:"release,required"`
+ Epoch uint `sh:"epoch"`
+ Description string `sh:"desc"`
+ Homepage string `sh:"homepage"`
+ Maintainer string `sh:"maintainer"`
+ Architectures []string `sh:"architectures"`
+ Licenses []string `sh:"license"`
+ Provides []string `sh:"provides"`
+ Conflicts []string `sh:"conflicts"`
+ Depends []string `sh:"deps"`
+ BuildDepends []string `sh:"build_deps"`
+ OptDepends []string `sh:"opt_deps"`
+ Replaces []string `sh:"replaces"`
+ Sources []string `sh:"sources"`
+ Checksums []string `sh:"checksums"`
+ Backup []string `sh:"backup"`
+ Scripts Scripts `sh:"scripts"`
+ AutoReq []string `sh:"auto_req"`
+ AutoProv []string `sh:"auto_prov"`
+ AutoReqSkipList []string `sh:"auto_req_skiplist"`
+ AutoProvSkipList []string `sh:"auto_prov_skiplist"`
}
func (bv *BuildVarsPre) ToBuildVars() BuildVars {
return BuildVars{
- Name: "",
- Version: bv.Version,
- Release: bv.Release,
- Epoch: bv.Epoch,
- Description: bv.Description,
- Homepage: bv.Homepage,
- Maintainer: bv.Maintainer,
- Architectures: bv.Architectures,
- Licenses: bv.Licenses,
- Provides: bv.Provides,
- Conflicts: bv.Conflicts,
- Depends: bv.Depends,
- BuildDepends: bv.BuildDepends,
- OptDepends: bv.OptDepends,
- Replaces: bv.Replaces,
- Sources: bv.Sources,
- Checksums: bv.Checksums,
- Backup: bv.Backup,
- Scripts: bv.Scripts,
- AutoReq: bv.AutoReq,
- AutoProv: bv.AutoProv,
+ Name: "",
+ Base: "",
+ BuildVarsPre: *bv,
}
}
// BuildVars represents the script variables required
// to build a package
type BuildVars struct {
- Name string `sh:"name,required"`
- Version string `sh:"version,required"`
- Release int `sh:"release,required"`
- Epoch uint `sh:"epoch"`
- Description string `sh:"desc"`
- Homepage string `sh:"homepage"`
- Maintainer string `sh:"maintainer"`
- Architectures []string `sh:"architectures"`
- Licenses []string `sh:"license"`
- Provides []string `sh:"provides"`
- Conflicts []string `sh:"conflicts"`
- Depends []string `sh:"deps"`
- BuildDepends []string `sh:"build_deps"`
- OptDepends []string `sh:"opt_deps"`
- Replaces []string `sh:"replaces"`
- Sources []string `sh:"sources"`
- Checksums []string `sh:"checksums"`
- Backup []string `sh:"backup"`
- Scripts Scripts `sh:"scripts"`
- AutoReq []string `sh:"auto_req"`
- AutoProv []string `sh:"auto_prov"`
- Base string
+ Name string `sh:"name,required"`
+ Base string
+ BuildVarsPre
}
type Scripts struct {
diff --git a/pkg/build/build.go b/pkg/build/build.go
index 27fd2a1..7b5c5ff 100644
--- a/pkg/build/build.go
+++ b/pkg/build/build.go
@@ -50,6 +50,7 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/helpers"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
+ finddeps "gitea.plemya-x.ru/Plemya-x/ALR/pkg/build/find_deps"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
)
@@ -211,8 +212,10 @@ func (b *Builder) BuildPackage(ctx context.Context) ([]string, []string, error)
sources, checksums = removeDuplicatesSources(sources, checksums)
mergedVars := types.BuildVars{
- Sources: sources,
- Checksums: checksums,
+ BuildVarsPre: types.BuildVarsPre{
+ Sources: sources,
+ Checksums: checksums,
+ },
}
buildDeps, err := b.installBuildDeps(ctx, buildDepends) // Устанавливаем зависимости для сборки
@@ -858,24 +861,18 @@ func (b *Builder) buildPkgMetadata(
pkgInfo.Overridables.Contents = contents
if len(vars.AutoProv) == 1 && decoder.IsTruthy(vars.AutoProv[0]) {
- if pkgFormat == "rpm" {
- err = rpmFindProvides(ctx, pkgInfo, dirs)
- if err != nil {
- return nil, err
- }
- } else {
- slog.Info(gotext.Get("AutoProv is not implemented for this package format, so it's skipped"))
+ f := finddeps.New(b.info, pkgFormat)
+ err = f.FindProvides(ctx, pkgInfo, dirs, vars.AutoProvSkipList)
+ if err != nil {
+ return nil, err
}
}
if len(vars.AutoReq) == 1 && decoder.IsTruthy(vars.AutoReq[0]) {
- if pkgFormat == "rpm" {
- err = rpmFindRequires(ctx, pkgInfo, dirs)
- if err != nil {
- return nil, err
- }
- } else {
- slog.Info(gotext.Get("AutoReq is not implemented for this package format, so it's skipped"))
+ f := finddeps.New(b.info, pkgFormat)
+ err = f.FindRequires(ctx, pkgInfo, dirs, vars.AutoReqSkipList)
+ if err != nil {
+ return nil, err
}
}
diff --git a/pkg/build/findDeps.go b/pkg/build/find_deps/alt_linux.go
similarity index 67%
rename from pkg/build/findDeps.go
rename to pkg/build/find_deps/alt_linux.go
index 0090005..cc003af 100644
--- a/pkg/build/findDeps.go
+++ b/pkg/build/find_deps/alt_linux.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-package build
+package finddeps
import (
"bytes"
@@ -30,7 +30,7 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
)
-func rpmFindDependencies(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, command string, updateFunc func(string)) error {
+func rpmFindDependenciesALTLinux(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, command string, envs []string, updateFunc func(string)) error {
if _, err := exec.LookPath(command); err != nil {
slog.Info(gotext.Get("Command not found on the system"), "command", command)
return nil
@@ -49,8 +49,8 @@ func rpmFindDependencies(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Dir
return nil
}
- cmd := exec.Command(command)
- cmd.Stdin = bytes.NewBufferString(strings.Join(paths, "\n"))
+ cmd := exec.CommandContext(ctx, command)
+ cmd.Stdin = bytes.NewBufferString(strings.Join(paths, "\n") + "\n")
cmd.Env = append(cmd.Env,
"RPM_BUILD_ROOT="+dirs.PkgDir,
"RPM_FINDPROV_METHOD=",
@@ -58,6 +58,7 @@ func rpmFindDependencies(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Dir
"RPM_DATADIR=",
"RPM_SUBPACKAGE_NAME=",
)
+ cmd.Env = append(cmd.Env, envs...)
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
@@ -66,6 +67,7 @@ func rpmFindDependencies(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Dir
slog.Error(stderr.String())
return err
}
+ slog.Debug(stderr.String())
dependencies := strings.Split(strings.TrimSpace(out.String()), "\n")
for _, dep := range dependencies {
@@ -77,15 +79,17 @@ func rpmFindDependencies(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Dir
return nil
}
-func rpmFindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories) error {
- return rpmFindDependencies(ctx, pkgInfo, dirs, "/usr/lib/rpm/find-provides", func(dep string) {
+type ALTLinuxFindProvReq struct{}
+
+func (o *ALTLinuxFindProvReq) FindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
+ return rpmFindDependenciesALTLinux(ctx, pkgInfo, dirs, "/usr/lib/rpm/find-provides", []string{"RPM_FINDPROV_SKIPLIST=" + strings.Join(skiplist, "\n")}, func(dep string) {
slog.Info(gotext.Get("Provided dependency found"), "dep", dep)
pkgInfo.Overridables.Provides = append(pkgInfo.Overridables.Provides, dep)
})
}
-func rpmFindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories) error {
- return rpmFindDependencies(ctx, pkgInfo, dirs, "/usr/lib/rpm/find-requires", func(dep string) {
+func (o *ALTLinuxFindProvReq) FindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
+ return rpmFindDependenciesALTLinux(ctx, pkgInfo, dirs, "/usr/lib/rpm/find-requires", []string{"RPM_FINDREQ_SKIPLIST=" + strings.Join(skiplist, "\n")}, func(dep string) {
slog.Info(gotext.Get("Required dependency found"), "dep", dep)
pkgInfo.Overridables.Depends = append(pkgInfo.Overridables.Depends, dep)
})
diff --git a/pkg/build/find_deps/empty.go b/pkg/build/find_deps/empty.go
new file mode 100644
index 0000000..05b3a7a
--- /dev/null
+++ b/pkg/build/find_deps/empty.go
@@ -0,0 +1,39 @@
+// ALR - Any Linux Repository
+// Copyright (C) 2025 Евгений Храмов
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+package finddeps
+
+import (
+ "context"
+ "log/slog"
+
+ "github.com/goreleaser/nfpm/v2"
+ "github.com/leonelquinteros/gotext"
+
+ "gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
+)
+
+type EmptyFindProvReq struct{}
+
+func (o *EmptyFindProvReq) FindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
+ slog.Info(gotext.Get("AutoProv is not implemented for this package format, so it's skipped"))
+ return nil
+}
+
+func (o *EmptyFindProvReq) FindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
+ slog.Info(gotext.Get("AutoReq is not implemented for this package format, so it's skipped"))
+ return nil
+}
diff --git a/pkg/build/find_deps/fedora.go b/pkg/build/find_deps/fedora.go
new file mode 100644
index 0000000..c649aae
--- /dev/null
+++ b/pkg/build/find_deps/fedora.go
@@ -0,0 +1,118 @@
+// ALR - Any Linux Repository
+// Copyright (C) 2025 Евгений Храмов
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+package finddeps
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "log/slog"
+ "os/exec"
+ "path"
+ "strings"
+
+ "github.com/goreleaser/nfpm/v2"
+ "github.com/leonelquinteros/gotext"
+
+ "gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
+)
+
+type FedoraFindProvReq struct{}
+
+func rpmFindDependenciesFedora(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, command string, args []string, updateFunc func(string)) error {
+ if _, err := exec.LookPath(command); err != nil {
+ slog.Info(gotext.Get("Command not found on the system"), "command", command)
+ return nil
+ }
+
+ var paths []string
+ for _, content := range pkgInfo.Contents {
+ if content.Type != "dir" {
+ paths = append(paths,
+ path.Join(dirs.PkgDir, content.Destination),
+ )
+ }
+ }
+
+ if len(paths) == 0 {
+ return nil
+ }
+
+ cmd := exec.CommandContext(ctx, command, args...)
+ cmd.Stdin = bytes.NewBufferString(strings.Join(paths, "\n") + "\n")
+ cmd.Env = append(cmd.Env,
+ "RPM_BUILD_ROOT="+dirs.PkgDir,
+ )
+ var out bytes.Buffer
+ var stderr bytes.Buffer
+ cmd.Stdout = &out
+ cmd.Stderr = &stderr
+ if err := cmd.Run(); err != nil {
+ slog.Error(stderr.String())
+ return err
+ }
+ slog.Debug(stderr.String())
+
+ dependencies := strings.Split(strings.TrimSpace(out.String()), "\n")
+ for _, dep := range dependencies {
+ if dep != "" {
+ updateFunc(dep)
+ }
+ }
+
+ return nil
+}
+
+func (o *FedoraFindProvReq) FindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
+ return rpmFindDependenciesFedora(
+ ctx,
+ pkgInfo,
+ dirs,
+ "/usr/lib/rpm/rpmdeps",
+ []string{
+ "--define=_use_internal_dependency_generator 1",
+ "--provides",
+ fmt.Sprintf(
+ "--define=__provides_exclude_from %s\"",
+ strings.Join(skiplist, "|"),
+ ),
+ },
+ func(dep string) {
+ slog.Info(gotext.Get("Provided dependency found"), "dep", dep)
+ pkgInfo.Overridables.Provides = append(pkgInfo.Overridables.Provides, dep)
+ })
+}
+
+func (o *FedoraFindProvReq) FindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
+ return rpmFindDependenciesFedora(
+ ctx,
+ pkgInfo,
+ dirs,
+ "/usr/lib/rpm/rpmdeps",
+ []string{
+ "--define=_use_internal_dependency_generator 1",
+ "--requires",
+ fmt.Sprintf(
+ "--define=__requires_exclude_from %s",
+ strings.Join(skiplist, "|"),
+ ),
+ },
+ func(dep string) {
+ slog.Info(gotext.Get("Required dependency found"), "dep", dep)
+ pkgInfo.Overridables.Depends = append(pkgInfo.Overridables.Depends, dep)
+ })
+}
diff --git a/pkg/build/find_deps/find_deps.go b/pkg/build/find_deps/find_deps.go
new file mode 100644
index 0000000..4e9b52e
--- /dev/null
+++ b/pkg/build/find_deps/find_deps.go
@@ -0,0 +1,58 @@
+// ALR - Any Linux Repository
+// Copyright (C) 2025 Евгений Храмов
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+package finddeps
+
+import (
+ "context"
+
+ "github.com/goreleaser/nfpm/v2"
+
+ "gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
+)
+
+type ProvReqFinder interface {
+ FindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error
+ FindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error
+}
+
+type ProvReqService struct {
+ finder ProvReqFinder
+}
+
+func New(info *distro.OSRelease, pkgFormat string) *ProvReqService {
+ s := &ProvReqService{
+ finder: &EmptyFindProvReq{},
+ }
+ if pkgFormat == "rpm" {
+ switch info.ID {
+ case "altlinux":
+ s.finder = &ALTLinuxFindProvReq{}
+ case "fedora":
+ s.finder = &FedoraFindProvReq{}
+ }
+ }
+ return s
+}
+
+func (s *ProvReqService) FindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
+ return s.finder.FindProvides(ctx, pkgInfo, dirs, skiplist)
+}
+
+func (s *ProvReqService) FindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
+ return s.finder.FindRequires(ctx, pkgInfo, dirs, skiplist)
+}