This commit is contained in:
Maxim Slipenko 2025-02-11 12:24:57 +03:00
parent 8978cc2855
commit 17bbb2f4c5
11 changed files with 378 additions and 341 deletions

@ -117,7 +117,7 @@ func BuildCmd() *cli.Command {
os.Exit(1) os.Exit(1)
} }
builder := build.New( builder := build.NewBuilder(
ctx, ctx,
types.BuildOpts{ types.BuildOpts{
Package: packageName, Package: packageName,

@ -11,7 +11,7 @@
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"> <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="33.5" y="15" fill="#010101" fill-opacity=".3">coverage</text> <text x="33.5" y="15" fill="#010101" fill-opacity=".3">coverage</text>
<text x="33.5" y="14">coverage</text> <text x="33.5" y="14">coverage</text>
<text x="86" y="15" fill="#010101" fill-opacity=".3">19.7%</text> <text x="86" y="15" fill="#010101" fill-opacity=".3">20.8%</text>
<text x="86" y="14">19.7%</text> <text x="86" y="14">20.8%</text>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 926 B

After

Width:  |  Height:  |  Size: 926 B

@ -29,9 +29,10 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config" "gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db" database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/build" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/build"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos"
) )
@ -63,22 +64,52 @@ func InstallCmd() *cli.Command {
os.Exit(1) os.Exit(1)
} }
if config.GetInstance(ctx).AutoPull(ctx) { cfg := config.New()
err := repos.Pull(ctx, config.Config(ctx).Repos) db := database.New(cfg)
rs := repos.New(cfg, db)
err := db.Init(ctx)
if err != nil {
slog.Error(gotext.Get("Error db init"), "err", err)
os.Exit(1)
}
if cfg.AutoPull(ctx) {
err := rs.Pull(ctx, cfg.Repos(ctx))
if err != nil { if err != nil {
slog.Error(gotext.Get("Error pulling repositories"), "err", err) slog.Error(gotext.Get("Error pulling repositories"), "err", err)
os.Exit(1) os.Exit(1)
} }
} }
found, notFound, err := repos.FindPkgs(ctx, args.Slice()) found, notFound, err := rs.FindPkgs(ctx, args.Slice())
if err != nil { if err != nil {
slog.Error(gotext.Get("Error finding packages"), "err", err) slog.Error(gotext.Get("Error finding packages"), "err", err)
os.Exit(1) os.Exit(1)
} }
pkgs := cliutils.FlattenPkgs(ctx, found, "install", c.Bool("interactive")) pkgs := cliutils.FlattenPkgs(ctx, found, "install", c.Bool("interactive"))
build.InstallPkgs(ctx, pkgs, notFound, types.BuildOpts{
opts := types.BuildOpts{
Manager: mgr,
Clean: c.Bool("clean"),
Interactive: c.Bool("interactive"),
}
info, err := distro.ParseOSRelease(ctx)
if err != nil {
slog.Error(gotext.Get("Error parsing os release"), "err", err)
os.Exit(1)
}
builder := build.NewBuilder(
ctx,
opts,
rs,
info,
cfg,
)
builder.InstallPkgs(ctx, pkgs, notFound, types.BuildOpts{
Manager: mgr, Manager: mgr,
Clean: c.Bool("clean"), Clean: c.Bool("clean"),
Interactive: c.Bool("interactive"), Interactive: c.Bool("interactive"),
@ -86,6 +117,8 @@ func InstallCmd() *cli.Command {
return nil return nil
}, },
BashComplete: func(c *cli.Context) { BashComplete: func(c *cli.Context) {
cfg := config.New()
db := database.New(cfg)
result, err := db.GetPkgs(c.Context, "true") result, err := db.GetPkgs(c.Context, "true")
if err != nil { if err != nil {
slog.Error(gotext.Get("Error getting packages"), "err", err) slog.Error(gotext.Get("Error getting packages"), "err", err)
@ -94,7 +127,7 @@ func InstallCmd() *cli.Command {
defer result.Close() defer result.Close()
for result.Next() { for result.Next() {
var pkg db.Package var pkg database.Package
err = result.StructScan(&pkg) err = result.StructScan(&pkg)
if err != nil { if err != nil {
slog.Error(gotext.Get("Error iterating over packages"), "err", err) slog.Error(gotext.Get("Error iterating over packages"), "err", err)

@ -138,31 +138,31 @@ msgstr ""
msgid "Error encoding script variables" msgid "Error encoding script variables"
msgstr "" msgstr ""
#: install.go:42 #: install.go:43
msgid "Install a new package" msgid "Install a new package"
msgstr "" msgstr ""
#: install.go:56 #: install.go:57
msgid "Command install expected at least 1 argument, got %d" msgid "Command install expected at least 1 argument, got %d"
msgstr "" msgstr ""
#: install.go:91 #: install.go:124
msgid "Error getting packages" msgid "Error getting packages"
msgstr "" msgstr ""
#: install.go:100 #: install.go:133
msgid "Error iterating over packages" msgid "Error iterating over packages"
msgstr "" msgstr ""
#: install.go:113 #: install.go:146
msgid "Remove an installed package" msgid "Remove an installed package"
msgstr "" msgstr ""
#: install.go:118 #: install.go:151
msgid "Command remove expected at least 1 argument, got %d" msgid "Command remove expected at least 1 argument, got %d"
msgstr "" msgstr ""
#: install.go:130 #: install.go:163
msgid "Error removing packages" msgid "Error removing packages"
msgstr "" msgstr ""
@ -301,78 +301,78 @@ msgstr ""
msgid "Error while running app" msgid "Error while running app"
msgstr "" msgstr ""
#: pkg/build/build.go:116 #: pkg/build/build.go:135
msgid "Failed to prompt user to view build script" msgid "Failed to prompt user to view build script"
msgstr "" msgstr ""
#: pkg/build/build.go:120 #: pkg/build/build.go:139
msgid "Building package" msgid "Building package"
msgstr "" msgstr ""
#: pkg/build/build.go:164 #: pkg/build/build.go:183
msgid "Downloading sources" msgid "Downloading sources"
msgstr "" msgstr ""
#: pkg/build/build.go:176 #: pkg/build/build.go:195
msgid "Building package metadata" msgid "Building package metadata"
msgstr "" msgstr ""
#: pkg/build/build.go:198 #: pkg/build/build.go:217
msgid "Compressing package" msgid "Compressing package"
msgstr "" msgstr ""
#: pkg/build/build.go:322 #: pkg/build/build.go:341
msgid "" msgid ""
"Your system's CPU architecture doesn't match this package. Do you want to " "Your system's CPU architecture doesn't match this package. Do you want to "
"build anyway?" "build anyway?"
msgstr "" msgstr ""
#: pkg/build/build.go:336 #: pkg/build/build.go:355
msgid "This package is already installed" msgid "This package is already installed"
msgstr "" msgstr ""
#: pkg/build/build.go:360 #: pkg/build/build.go:379
msgid "Installing build dependencies" msgid "Installing build dependencies"
msgstr "" msgstr ""
#: pkg/build/build.go:371 #: pkg/build/build.go:390
msgid "Installing dependencies" msgid "Installing dependencies"
msgstr "" msgstr ""
#: pkg/build/build.go:419 #: pkg/build/build.go:431
msgid "The checksums array must be the same length as sources" msgid "The checksums array must be the same length as sources"
msgstr "" msgstr ""
#: pkg/build/build.go:470 #: pkg/build/build.go:482
msgid "Would you like to remove the build dependencies?" msgid "Would you like to remove the build dependencies?"
msgstr "" msgstr ""
#: pkg/build/build.go:507 #: pkg/build/build.go:519
msgid "Executing version()" msgid "Executing version()"
msgstr "" msgstr ""
#: pkg/build/build.go:527 #: pkg/build/build.go:539
msgid "Updating version" msgid "Updating version"
msgstr "" msgstr ""
#: pkg/build/build.go:532 #: pkg/build/build.go:544
msgid "Executing prepare()" msgid "Executing prepare()"
msgstr "" msgstr ""
#: pkg/build/build.go:542 #: pkg/build/build.go:554
msgid "Executing build()" msgid "Executing build()"
msgstr "" msgstr ""
#: pkg/build/build.go:558 pkg/build/build.go:586 #: pkg/build/build.go:570 pkg/build/build.go:598
msgid "Executing %s()" msgid "Executing %s()"
msgstr "" msgstr ""
#: pkg/build/build_legacy.go:196 #: pkg/build/build.go:657
msgid "AutoProv is not implemented for this package format, so it's skipped" msgid "Error installing native packages"
msgstr "" msgstr ""
#: pkg/build/build_legacy.go:207 #: pkg/build/build.go:683
msgid "AutoReq is not implemented for this package format, so it's skipped" msgid "Error installing package"
msgstr "" msgstr ""
#: pkg/build/findDeps.go:35 #: pkg/build/findDeps.go:35
@ -387,12 +387,12 @@ msgstr ""
msgid "Required dependency found" msgid "Required dependency found"
msgstr "" msgstr ""
#: pkg/build/install.go:44 #: pkg/build/utils.go:136
msgid "Error installing native packages" msgid "AutoProv is not implemented for this package format, so it's skipped"
msgstr "" msgstr ""
#: pkg/build/install.go:94 #: pkg/build/utils.go:147
msgid "Error installing package" msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr "" msgstr ""
#: pkg/repos/pull.go:79 #: pkg/repos/pull.go:79
@ -461,10 +461,10 @@ msgstr ""
msgid "Upgrade all installed packages" msgid "Upgrade all installed packages"
msgstr "" msgstr ""
#: upgrade.go:83 #: upgrade.go:90
msgid "Error checking for updates" msgid "Error checking for updates"
msgstr "" msgstr ""
#: upgrade.go:94 #: upgrade.go:112
msgid "There is nothing to do." msgid "There is nothing to do."
msgstr "" msgstr ""

@ -146,31 +146,31 @@ msgstr "Ошибка устранения переорпеделений"
msgid "Error encoding script variables" msgid "Error encoding script variables"
msgstr "Ошибка кодирования переменных скрита" msgstr "Ошибка кодирования переменных скрита"
#: install.go:42 #: install.go:43
msgid "Install a new package" msgid "Install a new package"
msgstr "Установить новый пакет" msgstr "Установить новый пакет"
#: install.go:56 #: install.go:57
msgid "Command install expected at least 1 argument, got %d" msgid "Command install expected at least 1 argument, got %d"
msgstr "Для команды install ожидался хотя бы 1 аргумент, получено %d" msgstr "Для команды install ожидался хотя бы 1 аргумент, получено %d"
#: install.go:91 #: install.go:124
msgid "Error getting packages" msgid "Error getting packages"
msgstr "Ошибка при получении пакетов" msgstr "Ошибка при получении пакетов"
#: install.go:100 #: install.go:133
msgid "Error iterating over packages" msgid "Error iterating over packages"
msgstr "Ошибка при переборе пакетов" msgstr "Ошибка при переборе пакетов"
#: install.go:113 #: install.go:146
msgid "Remove an installed package" msgid "Remove an installed package"
msgstr "Удалить установленный пакет" msgstr "Удалить установленный пакет"
#: install.go:118 #: install.go:151
msgid "Command remove expected at least 1 argument, got %d" msgid "Command remove expected at least 1 argument, got %d"
msgstr "Для команды remove ожидался хотя бы 1 аргумент, получено %d" msgstr "Для команды remove ожидался хотя бы 1 аргумент, получено %d"
#: install.go:130 #: install.go:163
msgid "Error removing packages" msgid "Error removing packages"
msgstr "Ошибка при удалении пакетов" msgstr "Ошибка при удалении пакетов"
@ -316,27 +316,27 @@ msgstr ""
msgid "Error while running app" msgid "Error while running app"
msgstr "Ошибка при запуске приложения" msgstr "Ошибка при запуске приложения"
#: pkg/build/build.go:116 #: pkg/build/build.go:135
msgid "Failed to prompt user to view build script" msgid "Failed to prompt user to view build script"
msgstr "Не удалось предложить пользователю просмотреть скрипт сборки" msgstr "Не удалось предложить пользователю просмотреть скрипт сборки"
#: pkg/build/build.go:120 #: pkg/build/build.go:139
msgid "Building package" msgid "Building package"
msgstr "Сборка пакета" msgstr "Сборка пакета"
#: pkg/build/build.go:164 #: pkg/build/build.go:183
msgid "Downloading sources" msgid "Downloading sources"
msgstr "Скачивание источников" msgstr "Скачивание источников"
#: pkg/build/build.go:176 #: pkg/build/build.go:195
msgid "Building package metadata" msgid "Building package metadata"
msgstr "Сборка метаданных пакета" msgstr "Сборка метаданных пакета"
#: pkg/build/build.go:198 #: pkg/build/build.go:217
msgid "Compressing package" msgid "Compressing package"
msgstr "Сжатие пакета" msgstr "Сжатие пакета"
#: pkg/build/build.go:322 #: pkg/build/build.go:341
msgid "" msgid ""
"Your system's CPU architecture doesn't match this package. Do you want to " "Your system's CPU architecture doesn't match this package. Do you want to "
"build anyway?" "build anyway?"
@ -344,56 +344,54 @@ msgstr ""
"Архитектура процессора вашей системы не соответствует этому пакету. Вы все " "Архитектура процессора вашей системы не соответствует этому пакету. Вы все "
"равно хотите выполнить сборку?" "равно хотите выполнить сборку?"
#: pkg/build/build.go:336 #: pkg/build/build.go:355
msgid "This package is already installed" msgid "This package is already installed"
msgstr "Этот пакет уже установлен" msgstr "Этот пакет уже установлен"
#: pkg/build/build.go:360 #: pkg/build/build.go:379
msgid "Installing build dependencies" msgid "Installing build dependencies"
msgstr "Установка зависимостей сборки" msgstr "Установка зависимостей сборки"
#: pkg/build/build.go:371 #: pkg/build/build.go:390
msgid "Installing dependencies" msgid "Installing dependencies"
msgstr "Установка зависимостей" msgstr "Установка зависимостей"
#: pkg/build/build.go:419 #: pkg/build/build.go:431
msgid "The checksums array must be the same length as sources" msgid "The checksums array must be the same length as sources"
msgstr "Массив контрольных сумм должен быть той же длины, что и источники" msgstr "Массив контрольных сумм должен быть той же длины, что и источники"
#: pkg/build/build.go:470 #: pkg/build/build.go:482
msgid "Would you like to remove the build dependencies?" msgid "Would you like to remove the build dependencies?"
msgstr "Хотели бы вы удалить зависимости сборки?" msgstr "Хотели бы вы удалить зависимости сборки?"
#: pkg/build/build.go:507 #: pkg/build/build.go:519
msgid "Executing version()" msgid "Executing version()"
msgstr "Исполнение версия()" msgstr "Исполнение версия()"
#: pkg/build/build.go:527 #: pkg/build/build.go:539
msgid "Updating version" msgid "Updating version"
msgstr "Обновление версии" msgstr "Обновление версии"
#: pkg/build/build.go:532 #: pkg/build/build.go:544
msgid "Executing prepare()" msgid "Executing prepare()"
msgstr "Исполнение prepare()" msgstr "Исполнение prepare()"
#: pkg/build/build.go:542 #: pkg/build/build.go:554
msgid "Executing build()" msgid "Executing build()"
msgstr "Исполнение build()" msgstr "Исполнение build()"
#: pkg/build/build.go:558 pkg/build/build.go:586 #: pkg/build/build.go:570 pkg/build/build.go:598
#, fuzzy #, fuzzy
msgid "Executing %s()" msgid "Executing %s()"
msgstr "Исполнение files()" msgstr "Исполнение files()"
#: pkg/build/build_legacy.go:196 #: pkg/build/build.go:657
msgid "AutoProv is not implemented for this package format, so it's skipped" msgid "Error installing native packages"
msgstr "" msgstr "Ошибка при установке нативных пакетов"
"AutoProv не реализовано для этого формата пакета, поэтому будет пропущено"
#: pkg/build/build_legacy.go:207 #: pkg/build/build.go:683
msgid "AutoReq is not implemented for this package format, so it's skipped" msgid "Error installing package"
msgstr "" msgstr "Ошибка при установке пакета"
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
#: pkg/build/findDeps.go:35 #: pkg/build/findDeps.go:35
msgid "Command not found on the system" msgid "Command not found on the system"
@ -407,13 +405,15 @@ msgstr "Найденная предоставленная зависимость
msgid "Required dependency found" msgid "Required dependency found"
msgstr "Найдена требуемая зависимость" msgstr "Найдена требуемая зависимость"
#: pkg/build/install.go:44 #: pkg/build/utils.go:136
msgid "Error installing native packages" msgid "AutoProv is not implemented for this package format, so it's skipped"
msgstr "Ошибка при установке нативных пакетов" msgstr ""
"AutoProv не реализовано для этого формата пакета, поэтому будет пропущено"
#: pkg/build/install.go:94 #: pkg/build/utils.go:147
msgid "Error installing package" msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr "Ошибка при установке пакета" msgstr ""
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
#: pkg/repos/pull.go:79 #: pkg/repos/pull.go:79
msgid "Pulling repository" msgid "Pulling repository"
@ -483,11 +483,11 @@ msgstr "Скачать все изменённые репозитории"
msgid "Upgrade all installed packages" msgid "Upgrade all installed packages"
msgstr "Обновить все установленные пакеты" msgstr "Обновить все установленные пакеты"
#: upgrade.go:83 #: upgrade.go:90
msgid "Error checking for updates" msgid "Error checking for updates"
msgstr "Ошибка при проверке обновлений" msgstr "Ошибка при проверке обновлений"
#: upgrade.go:94 #: upgrade.go:112
msgid "There is nothing to do." msgid "There is nothing to do."
msgstr "Здесь нечего делать." msgstr "Здесь нечего делать."

@ -41,6 +41,7 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config" "gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/dl" "gitea.plemya-x.ru/Plemya-x/ALR/internal/dl"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/dlcache" "gitea.plemya-x.ru/Plemya-x/ALR/internal/dlcache"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder"
@ -49,23 +50,31 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos"
) )
type PackageFinder interface {
FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.Package, []string, error)
}
type Config interface {
GetPaths(ctx context.Context) *config.Paths
PagerStyle(ctx context.Context) string
}
type Builder struct { type Builder struct {
ctx context.Context ctx context.Context
opts types.BuildOpts opts types.BuildOpts
info *distro.OSRelease info *distro.OSRelease
repos *repos.Repos repos PackageFinder
config *config.ALRConfig config Config
} }
func New( func NewBuilder(
ctx context.Context, ctx context.Context,
opts types.BuildOpts, opts types.BuildOpts,
repos *repos.Repos, repos PackageFinder,
info *distro.OSRelease, info *distro.OSRelease,
config *config.ALRConfig, config Config,
) *Builder { ) *Builder {
return &Builder{ return &Builder{
ctx: ctx, ctx: ctx,
@ -76,6 +85,16 @@ func New(
} }
} }
func (b *Builder) UpdateOptsFromPkg(pkg *db.Package) {
repodir := b.config.GetPaths(b.ctx).RepoDir
if pkg.BasePkgName != "" {
b.opts.Script = filepath.Join(repodir, pkg.Repository, pkg.BasePkgName, "alr.sh")
b.opts.Package = pkg.Name
} else {
b.opts.Script = filepath.Join(repodir, pkg.Repository, pkg.Name, "alr.sh")
}
}
func (b *Builder) BuildPackage(ctx context.Context) ([]string, []string, error) { func (b *Builder) BuildPackage(ctx context.Context) ([]string, []string, error) {
fl, err := readScript(b.opts.Script) fl, err := readScript(b.opts.Script)
if err != nil { if err != nil {
@ -151,7 +170,7 @@ func (b *Builder) BuildPackage(ctx context.Context) ([]string, []string, error)
return nil, nil, err return nil, nil, err
} }
err = installOptDeps(ctx, b.repos, vars, b.opts) // Устанавливаем опциональные зависимости err = b.installOptDeps(ctx, vars) // Устанавливаем опциональные зависимости
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -352,7 +371,7 @@ func (b *Builder) installBuildDeps(ctx context.Context, vars *types.BuildVars) (
return nil, err return nil, err
} }
found, notFound, err := repos.FindPkgs(ctx, deps) // Находим пакеты-зависимости found, notFound, err := b.repos.FindPkgs(ctx, deps) // Находим пакеты-зависимости
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -361,7 +380,7 @@ func (b *Builder) installBuildDeps(ctx context.Context, vars *types.BuildVars) (
flattened := cliutils.FlattenPkgs(ctx, found, "install", b.opts.Interactive) // Уплощаем список зависимостей flattened := cliutils.FlattenPkgs(ctx, found, "install", b.opts.Interactive) // Уплощаем список зависимостей
buildDeps = packageNames(flattened) buildDeps = packageNames(flattened)
InstallPkgs(ctx, flattened, notFound, b.opts) // Устанавливаем пакеты b.InstallPkgs(ctx, flattened, notFound, b.opts) // Устанавливаем пакеты
} }
return buildDeps, nil return buildDeps, nil
} }
@ -370,7 +389,7 @@ func (b *Builder) buildALRDeps(ctx context.Context, vars *types.BuildVars) (buil
if len(vars.Depends) > 0 { if len(vars.Depends) > 0 {
slog.Info(gotext.Get("Installing dependencies")) slog.Info(gotext.Get("Installing dependencies"))
found, notFound, err := repos.FindPkgs(ctx, vars.Depends) // Поиск зависимостей found, notFound, err := b.repos.FindPkgs(ctx, vars.Depends) // Поиск зависимостей
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
@ -380,16 +399,9 @@ func (b *Builder) buildALRDeps(ctx context.Context, vars *types.BuildVars) (buil
pkgs := cliutils.FlattenPkgs(ctx, found, "install", b.opts.Interactive) pkgs := cliutils.FlattenPkgs(ctx, found, "install", b.opts.Interactive)
for _, pkg := range pkgs { for _, pkg := range pkgs {
newOpts := b.opts
UpdateOpts(ctx, &newOpts, &pkg)
newB := New( newB := *b
ctx, newB.UpdateOptsFromPkg(&pkg)
newOpts,
b.repos,
b.info,
b.config,
)
// Собираем зависимости // Собираем зависимости
pkgPaths, pkgNames, err := newB.BuildPackage(ctx) pkgPaths, pkgNames, err := newB.BuildPackage(ctx)
@ -402,7 +414,7 @@ func (b *Builder) buildALRDeps(ctx context.Context, vars *types.BuildVars) (buil
// Добавляем пути всех собранных пакетов в builtPaths // Добавляем пути всех собранных пакетов в builtPaths
builtNames = append(builtNames, pkgNames...) builtNames = append(builtNames, pkgNames...)
// Добавляем имя текущего пакета в builtNames // Добавляем имя текущего пакета в builtNames
builtNames = append(builtNames, filepath.Base(filepath.Dir(newOpts.Script))) builtNames = append(builtNames, filepath.Base(filepath.Dir(newB.opts.Script)))
} }
} }
@ -605,3 +617,72 @@ func (b *Builder) executeFunctions(
return output, nil return output, nil
} }
func (b *Builder) installOptDeps(ctx context.Context, vars *types.BuildVars) error {
optDeps, err := removeAlreadyInstalled(b.opts, vars.OptDepends)
if err != nil {
return err
}
if len(optDeps) > 0 {
optDeps, err := cliutils.ChooseOptDepends(ctx, optDeps, "install", b.opts.Interactive) // Пользователя просят выбрать опциональные зависимости
if err != nil {
return err
}
if len(optDeps) == 0 {
return nil
}
found, notFound, err := b.repos.FindPkgs(ctx, optDeps) // Находим опциональные зависимости
if err != nil {
return err
}
flattened := cliutils.FlattenPkgs(ctx, found, "install", b.opts.Interactive)
b.InstallPkgs(ctx, flattened, notFound, b.opts) // Устанавливаем выбранные пакеты
}
return nil
}
func (b *Builder) InstallPkgs(
ctx context.Context,
alrPkgs []db.Package,
nativePkgs []string,
opts types.BuildOpts,
) {
if len(nativePkgs) > 0 {
err := opts.Manager.Install(nil, nativePkgs...)
// Если есть нативные пакеты, выполняем их установку
if err != nil {
slog.Error(gotext.Get("Error installing native packages"), "err", err)
os.Exit(1)
// Логируем и завершаем выполнение при ошибке
}
}
b.InstallALRPackages(ctx, alrPkgs, opts)
// Устанавливаем скрипты сборки через функцию InstallScripts
}
func (b *Builder) InstallALRPackages(ctx context.Context, pkgs []db.Package, opts types.BuildOpts) {
for _, pkg := range pkgs {
builder := *b
builder.UpdateOptsFromPkg(&pkg)
builtPkgs, _, err := builder.BuildPackage(ctx)
// Выполняем сборку пакета
if err != nil {
slog.Error(gotext.Get("Error building package"), "err", err)
os.Exit(1)
// Логируем и завершаем выполнение при ошибке сборки
}
err = opts.Manager.InstallLocal(nil, builtPkgs...)
// Устанавливаем локально собранные пакеты
if err != nil {
slog.Error(gotext.Get("Error installing package"), "err", err)
os.Exit(1)
// Логируем и завершаем выполнение при ошибке установки
}
}
}

@ -18,10 +18,18 @@ package build
import ( import (
"context" "context"
"fmt"
"os"
"strings"
"testing" "testing"
"github.com/stretchr/testify/assert"
"mvdan.cc/sh/v3/syntax"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db" "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
) )
@ -134,93 +142,143 @@ func (m *TestManager) IsInstalled(pkg string) (bool, error) {
return true, nil return true, nil
} }
// TODO: fix test type TestConfig struct{}
func TestInstallBuildDeps(t *testing.T) {
type testEnv struct {
pf PackageFinder
vars *types.BuildVars
opts types.BuildOpts
// Contains pkgs captured by FindPkgsFunc func (c *TestConfig) PagerStyle(ctx context.Context) string {
// capturedPkgs []string return "native"
}
func (c *TestConfig) GetPaths(ctx context.Context) *config.Paths {
return &config.Paths{
CacheDir: "/tmp",
}
}
func TestExecuteFirstPassIsSecure(t *testing.T) {
cfg := &TestConfig{}
pf := &TestPackageFinder{}
info := &distro.OSRelease{}
m := &TestManager{}
opts := types.BuildOpts{
Manager: m,
Interactive: false,
} }
ctx := context.Background()
b := NewBuilder(
ctx,
opts,
pf,
info,
cfg,
)
tmpFile, err := os.CreateTemp("", "testfile-")
assert.NoError(t, err)
tmpFilePath := tmpFile.Name()
defer os.Remove(tmpFilePath)
_, err = os.Stat(tmpFilePath)
assert.NoError(t, err)
testScript := fmt.Sprintf(`name='test'
version=1.0.0
release=1
rm -f %s`, tmpFilePath)
fl, err := syntax.NewParser().Parse(strings.NewReader(testScript), "alr.sh")
assert.NoError(t, err)
_, err = b.executeFirstPass(fl)
assert.NoError(t, err)
_, err = os.Stat(tmpFilePath)
assert.NoError(t, err)
}
func TestExecuteFirstPassIsCorrect(t *testing.T) {
type testCase struct { type testCase struct {
Name string Name string
Prepare func() *testEnv Script string
Expected func(t *testing.T, e *testEnv, res []string, err error) Opts types.BuildOpts
Expected func(t *testing.T, vars *types.BuildVars)
} }
for _, tc := range []testCase{ for _, tc := range []testCase{{
/* Name: "single package",
{ Script: `name='test'
Name: "install only needed deps", version='1.0.0'
Prepare: func() *testEnv { release=1
pf := TestPackageFinder{} epoch=2
vars := types.BuildVars{} desc="Test package"
m := TestManager{} homepage='https://example.com'
opts := types.BuildOpts{ maintainer='Ivan Ivanov'
Manager: &m, `,
Interactive: false, Opts: types.BuildOpts{
} Manager: &TestManager{},
Interactive: false,
},
Expected: func(t *testing.T, vars *types.BuildVars) {
assert.Equal(t, vars.Name, "test")
assert.Equal(t, vars.Version, "1.0.0")
assert.Equal(t, vars.Release, int(1))
assert.Equal(t, vars.Epoch, uint(2))
assert.Equal(t, vars.Description, "Test package")
},
}, {
Name: "multiple packages",
Script: `name=(
foo
bar
)
env := &testEnv{ version='0.0.1'
pf: &pf, release=1
vars: &vars, epoch=2
opts: opts, desc="Test package"
capturedPkgs: []string{},
}
pf.FindPkgsFunc = func(ctx context.Context, pkgs []string) (map[string][]db.Package, []string, error) { meta_foo() {
env.capturedPkgs = append(env.capturedPkgs, pkgs...) desc="Foo package"
result := make(map[string][]db.Package) }
result["bar"] = []db.Package{{
Name: "bar-pkg",
}}
result["buz"] = []db.Package{{
Name: "buz-pkg",
}}
return result, []string{}, nil meta_bar() {
}
vars.BuildDepends = []string{ }
"foo", `,
"bar", Opts: types.BuildOpts{
"buz", Package: "foo",
} Manager: &TestManager{},
m.IsInstalledFunc = func(pkg string) (bool, error) { Interactive: false,
if pkg == "foo" { },
return true, nil Expected: func(t *testing.T, vars *types.BuildVars) {
} else { assert.Equal(t, vars.Name, "foo")
return false, nil assert.Equal(t, vars.Description, "Foo package")
} },
} }} {
t.Run(tc.Name, func(t *testing.T) {
cfg := &TestConfig{}
pf := &TestPackageFinder{}
info := &distro.OSRelease{}
return env
},
Expected: func(t *testing.T, e *testEnv, res []string, err error) {
assert.NoError(t, err)
assert.Len(t, res, 2)
assert.ElementsMatch(t, res, []string{"bar-pkg", "buz-pkg"})
assert.ElementsMatch(t, e.capturedPkgs, []string{"bar", "buz"})
},
},
*/
} {
t.Run(tc.Name, func(tt *testing.T) {
ctx := context.Background() ctx := context.Background()
env := tc.Prepare()
result, err := installBuildDeps( b := NewBuilder(
ctx, ctx,
env.pf, tc.Opts,
env.vars, pf,
env.opts, info,
cfg,
) )
tc.Expected(tt, env, result, err) fl, err := syntax.NewParser().Parse(strings.NewReader(tc.Script), "alr.sh")
assert.NoError(t, err)
vars, err := b.executeFirstPass(fl)
assert.NoError(t, err)
tc.Expected(t, vars)
}) })
} }
} }

@ -1,99 +0,0 @@
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
//
// 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 <http://www.gnu.org/licenses/>.
package build
import (
"context"
"log/slog"
"os"
"path/filepath"
"github.com/leonelquinteros/gotext"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos"
)
// InstallPkgs устанавливает нативные пакеты с использованием менеджера пакетов,
// затем строит и устанавливает пакеты ALR
func InstallPkgs(ctx context.Context, alrPkgs []db.Package, nativePkgs []string, opts types.BuildOpts) {
if len(nativePkgs) > 0 {
err := opts.Manager.Install(nil, nativePkgs...)
// Если есть нативные пакеты, выполняем их установку
if err != nil {
slog.Error(gotext.Get("Error installing native packages"), "err", err)
os.Exit(1)
// Логируем и завершаем выполнение при ошибке
}
}
InstallALRPackages(ctx, alrPkgs, opts)
// Устанавливаем скрипты сборки через функцию InstallScripts
}
func UpdateOpts(ctx context.Context, opts *types.BuildOpts, pkg *db.Package) {
repodir := config.GetPaths(ctx).RepoDir
if pkg.BasePkgName != "" {
opts.Script = filepath.Join(repodir, pkg.Repository, pkg.BasePkgName, "alr.sh")
opts.Package = pkg.Name
} else {
opts.Script = filepath.Join(repodir, pkg.Repository, pkg.Name, "alr.sh")
}
}
// InstallALRPackages строит и устанавливает переданные alr скрипты сборки
func InstallALRPackages(ctx context.Context, pkgs []db.Package, opts types.BuildOpts) {
info, err := distro.ParseOSRelease(ctx)
if err != nil {
slog.Error(gotext.Get("Error parsing os release"), "err", err)
os.Exit(1)
}
for _, pkg := range pkgs {
UpdateOpts(ctx, &opts, &pkg)
builder := New(
ctx,
opts,
repos.GetInstance(ctx),
info,
config.GetInstance(ctx),
)
builtPkgs, _, err := builder.BuildPackage(ctx)
// Выполняем сборку пакета
if err != nil {
slog.Error(gotext.Get("Error building package"), "err", err)
os.Exit(1)
// Логируем и завершаем выполнение при ошибке сборки
}
err = opts.Manager.InstallLocal(nil, builtPkgs...)
// Устанавливаем локально собранные пакеты
if err != nil {
slog.Error(gotext.Get("Error installing package"), "err", err)
os.Exit(1)
// Логируем и завершаем выполнение при ошибке установки
}
}
}

@ -1,6 +1,3 @@
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
//
// ALR - Any Linux Repository // ALR - Any Linux Repository
// Copyright (C) 2025 Евгений Храмов // Copyright (C) 2025 Евгений Храмов
// //
@ -43,7 +40,6 @@ import (
"github.com/goreleaser/nfpm/v2" "github.com/goreleaser/nfpm/v2"
"github.com/goreleaser/nfpm/v2/files" "github.com/goreleaser/nfpm/v2/files"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db" "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides" "gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides"
@ -82,62 +78,6 @@ func prepareDirs(dirs types.Directories) error {
return os.MkdirAll(dirs.PkgDir, 0o755) // Создаем директорию для пакетов return os.MkdirAll(dirs.PkgDir, 0o755) // Создаем директорию для пакетов
} }
type PackageFinder interface {
FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.Package, []string, error)
}
// Функция installBuildDeps устанавливает все зависимости сборки, которые еще не установлены, и возвращает
// срез, содержащий имена всех установленных пакетов.
func installBuildDeps(ctx context.Context, repos PackageFinder, vars *types.BuildVars, opts types.BuildOpts) ([]string, error) {
var buildDeps []string
if len(vars.BuildDepends) > 0 {
deps, err := removeAlreadyInstalled(opts, vars.BuildDepends)
if err != nil {
return nil, err
}
found, notFound, err := repos.FindPkgs(ctx, deps) // Находим пакеты-зависимости
if err != nil {
return nil, err
}
slog.Info(gotext.Get("Installing build dependencies")) // Логгируем установку зависимостей
flattened := cliutils.FlattenPkgs(ctx, found, "install", opts.Interactive) // Уплощаем список зависимостей
buildDeps = packageNames(flattened)
InstallPkgs(ctx, flattened, notFound, opts) // Устанавливаем пакеты
}
return buildDeps, nil
}
// Функция installOptDeps спрашивает у пользователя, какие, если таковые имеются, опциональные зависимости он хочет установить.
// Если пользователь решает установить какие-либо опциональные зависимости, выполняется их установка.
func installOptDeps(ctx context.Context, repos PackageFinder, vars *types.BuildVars, opts types.BuildOpts) error {
optDeps, err := removeAlreadyInstalled(opts, vars.OptDepends)
if err != nil {
return err
}
if len(optDeps) > 0 {
optDeps, err := cliutils.ChooseOptDepends(ctx, optDeps, "install", opts.Interactive) // Пользователя просят выбрать опциональные зависимости
if err != nil {
return err
}
if len(optDeps) == 0 {
return nil
}
found, notFound, err := repos.FindPkgs(ctx, optDeps) // Находим опциональные зависимости
if err != nil {
return err
}
flattened := cliutils.FlattenPkgs(ctx, found, "install", opts.Interactive)
InstallPkgs(ctx, flattened, notFound, opts) // Устанавливаем выбранные пакеты
}
return nil
}
// Функция buildPkgMetadata создает метаданные для пакета, который будет собран. // Функция buildPkgMetadata создает метаданные для пакета, который будет собран.
func buildPkgMetadata( func buildPkgMetadata(
ctx context.Context, ctx context.Context,

@ -40,7 +40,7 @@ func Pull(ctx context.Context, repos []types.Repo) error {
// It also returns a slice that contains the names of all packages that were not found. // It also returns a slice that contains the names of all packages that were not found.
// //
// Deprecated: use struct method // Deprecated: use struct method
func FindPkgs(ctx context.Context, pkgs []string) (map[string][]database.Package, []string, error) { func FindPkgs_(ctx context.Context, pkgs []string) (map[string][]database.Package, []string, error) {
return GetInstance(ctx).FindPkgs(ctx, pkgs) return GetInstance(ctx).FindPkgs(ctx, pkgs)
} }

@ -32,7 +32,7 @@ import (
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config" "gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db" database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides" "gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/build" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/build"
@ -56,7 +56,14 @@ func UpgradeCmd() *cli.Command {
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
ctx := c.Context ctx := c.Context
cfg := config.GetInstance(ctx) cfg := config.New()
db := database.New(cfg)
rs := repos.New(cfg, db)
err := db.Init(ctx)
if err != nil {
slog.Error(gotext.Get("Error db init"), "err", err)
os.Exit(1)
}
info, err := distro.ParseOSRelease(ctx) info, err := distro.ParseOSRelease(ctx)
if err != nil { if err != nil {
@ -71,21 +78,32 @@ func UpgradeCmd() *cli.Command {
} }
if cfg.AutoPull(ctx) { if cfg.AutoPull(ctx) {
err = repos.Pull(ctx, config.Config(ctx).Repos) err = rs.Pull(ctx, cfg.Repos(ctx))
if err != nil { if err != nil {
slog.Error(gotext.Get("Error pulling repos"), "err", err) slog.Error(gotext.Get("Error pulling repos"), "err", err)
os.Exit(1) os.Exit(1)
} }
} }
updates, err := checkForUpdates(ctx, mgr, info) updates, err := checkForUpdates(ctx, mgr, cfg, rs, info)
if err != nil { if err != nil {
slog.Error(gotext.Get("Error checking for updates"), "err", err) slog.Error(gotext.Get("Error checking for updates"), "err", err)
os.Exit(1) os.Exit(1)
} }
if len(updates) > 0 { if len(updates) > 0 {
build.InstallPkgs(ctx, updates, nil, types.BuildOpts{ builder := build.NewBuilder(
ctx,
types.BuildOpts{
Manager: mgr,
Clean: c.Bool("clean"),
Interactive: c.Bool("interactive"),
},
rs,
info,
cfg,
)
builder.InstallPkgs(ctx, updates, nil, types.BuildOpts{
Manager: mgr, Manager: mgr,
Clean: c.Bool("clean"), Clean: c.Bool("clean"),
Interactive: c.Bool("interactive"), Interactive: c.Bool("interactive"),
@ -99,27 +117,33 @@ func UpgradeCmd() *cli.Command {
} }
} }
func checkForUpdates(ctx context.Context, mgr manager.Manager, info *distro.OSRelease) ([]db.Package, error) { func checkForUpdates(
ctx context.Context,
mgr manager.Manager,
cfg *config.ALRConfig,
rs *repos.Repos,
info *distro.OSRelease,
) ([]database.Package, error) {
installed, err := mgr.ListInstalled(nil) installed, err := mgr.ListInstalled(nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
pkgNames := maps.Keys(installed) pkgNames := maps.Keys(installed)
found, _, err := repos.FindPkgs(ctx, pkgNames) found, _, err := rs.FindPkgs(ctx, pkgNames)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var out []db.Package var out []database.Package
for pkgName, pkgs := range found { for pkgName, pkgs := range found {
if slices.Contains(config.Config(ctx).IgnorePkgUpdates, pkgName) { if slices.Contains(cfg.IgnorePkgUpdates(ctx), pkgName) {
continue continue
} }
if len(pkgs) > 1 { if len(pkgs) > 1 {
// Puts the element with the highest version first // Puts the element with the highest version first
slices.SortFunc(pkgs, func(a, b db.Package) int { slices.SortFunc(pkgs, func(a, b database.Package) int {
return vercmp.Compare(a.Version, b.Version) return vercmp.Compare(a.Version, b.Version)
}) })
} }