refactor: keep only one struct for package

This commit is contained in:
2025-06-12 16:25:18 +03:00
parent e259184a89
commit 392a522723
34 changed files with 682 additions and 580 deletions

View File

@ -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">16.5%</text> <text x="86" y="15" fill="#010101" fill-opacity=".3">17.6%</text>
<text x="86" y="14">16.5%</text> <text x="86" y="14">17.6%</text>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 926 B

After

Width:  |  Height:  |  Size: 926 B

View File

@ -31,8 +31,8 @@ func TestE2EGroupAndSummaryField(t *testing.T) {
RPM_SYSTEMS, RPM_SYSTEMS,
func(t *testing.T, r e2e.Runnable) { func(t *testing.T, r e2e.Runnable) {
defaultPrepare(t, r) defaultPrepare(t, r)
execShouldNoError(t, r, "sh", "-c", "alr search --name test-group-and-summary --format \"{{.Group}}\" | grep ^System/Base$") execShouldNoError(t, r, "sh", "-c", "alr search --name test-group-and-summary --format \"{{.Group.Resolved}}\" | grep ^System/Base$")
execShouldNoError(t, r, "sh", "-c", "alr search --name test-group-and-summary --format \"{{.Summary}}\" | grep \"^Custom summary$\"") execShouldNoError(t, r, "sh", "-c", "alr search --name test-group-and-summary --format \"{{.Summary.Resolved}}\" | grep \"^Custom summary$\"")
}, },
) )
} }

View File

@ -32,6 +32,7 @@ import (
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder" appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
"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/utils" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
) )
@ -88,6 +89,7 @@ func InfoCmd() *cli.Command {
New(ctx). New(ctx).
WithConfig(). WithConfig().
WithDB(). WithDB().
WithDistroInfo().
WithRepos(). WithRepos().
Build() Build()
if err != nil { if err != nil {
@ -136,7 +138,8 @@ func InfoCmd() *cli.Command {
for _, pkg := range pkgs { for _, pkg := range pkgs {
if !all { if !all {
err = yaml.NewEncoder(os.Stdout).Encode(overrides.ResolvePackage(&pkg, names)) alrsh.ResolvePackage(&pkg, names)
err = yaml.NewEncoder(os.Stdout).Encode(pkg)
if err != nil { if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error encoding script variables"), err) return cliutils.FormatCliExit(gotext.Get("Error encoding script variables"), err)
} }

View File

@ -24,13 +24,13 @@ import (
"context" "context"
"encoding/gob" "encoding/gob"
"errors" "errors"
"fmt"
"log/slog" "log/slog"
"github.com/leonelquinteros/gotext" "github.com/leonelquinteros/gotext"
"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"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager" "gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
@ -158,7 +158,7 @@ func GetBuiltName(deps []*BuiltDep) []string {
} }
type PackageFinder interface { type PackageFinder interface {
FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.Package, []string, error) FindPkgs(ctx context.Context, pkgs []string) (map[string][]alrsh.Package, []string, error)
} }
type Config interface { type Config interface {
@ -173,12 +173,12 @@ type FunctionsOutput struct {
// EXECUTORS // EXECUTORS
type ScriptResolverExecutor interface { type ScriptResolverExecutor interface {
ResolveScript(ctx context.Context, pkg *db.Package) *ScriptInfo ResolveScript(ctx context.Context, pkg *alrsh.Package) *ScriptInfo
} }
type ScriptExecutor interface { type ScriptExecutor interface {
ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ScriptFile, error)
ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ScriptFile) (string, []*alrsh.Package, error)
PrepareDirs( PrepareDirs(
ctx context.Context, ctx context.Context,
input *BuildInput, input *BuildInput,
@ -187,8 +187,8 @@ type ScriptExecutor interface {
ExecuteSecondPass( ExecuteSecondPass(
ctx context.Context, ctx context.Context,
input *BuildInput, input *BuildInput,
sf *alrsh.ALRSh, sf *alrsh.ScriptFile,
varsOfPackages []*types.BuildVars, varsOfPackages []*alrsh.Package,
repoDeps []string, repoDeps []string,
builtDeps []*BuiltDep, builtDeps []*BuiltDep,
basePkg string, basePkg string,
@ -196,18 +196,18 @@ type ScriptExecutor interface {
} }
type CacheExecutor interface { type CacheExecutor interface {
CheckForBuiltPackage(ctx context.Context, input *BuildInput, vars *types.BuildVars) (string, bool, error) CheckForBuiltPackage(ctx context.Context, input *BuildInput, vars *alrsh.Package) (string, bool, error)
} }
type ScriptViewerExecutor interface { type ScriptViewerExecutor interface {
ViewScript(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh, basePkg string) error ViewScript(ctx context.Context, input *BuildInput, sf *alrsh.ScriptFile, basePkg string) error
} }
type CheckerExecutor interface { type CheckerExecutor interface {
PerformChecks( PerformChecks(
ctx context.Context, ctx context.Context,
input *BuildInput, input *BuildInput,
vars *types.BuildVars, vars *alrsh.Package,
) (bool, error) ) (bool, error)
} }
@ -285,7 +285,7 @@ func (b *BuildArgs) PkgFormat() string {
type BuildPackageFromDbArgs struct { type BuildPackageFromDbArgs struct {
BuildArgs BuildArgs
Package *db.Package Package *alrsh.Package
Packages []string Packages []string
} }
@ -334,19 +334,19 @@ func (b *Builder) BuildPackage(
slog.Debug("ReadScript") slog.Debug("ReadScript")
sf, err := b.scriptExecutor.ReadScript(ctx, scriptPath) sf, err := b.scriptExecutor.ReadScript(ctx, scriptPath)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed reading script: %w", err)
} }
slog.Debug("ExecuteFirstPass") slog.Debug("ExecuteFirstPass")
basePkg, varsOfPackages, err := b.scriptExecutor.ExecuteFirstPass(ctx, input, sf) basePkg, varsOfPackages, err := b.scriptExecutor.ExecuteFirstPass(ctx, input, sf)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed ExecuteFirstPass: %w", err)
} }
var builtDeps []*BuiltDep var builtDeps []*BuiltDep
if !input.opts.Clean { if !input.opts.Clean {
var remainingVars []*types.BuildVars var remainingVars []*alrsh.Package
for _, vars := range varsOfPackages { for _, vars := range varsOfPackages {
builtPkgPath, ok, err := b.cacheExecutor.CheckForBuiltPackage(ctx, input, vars) builtPkgPath, ok, err := b.cacheExecutor.CheckForBuiltPackage(ctx, input, vars)
if err != nil { if err != nil {
@ -367,6 +367,7 @@ func (b *Builder) BuildPackage(
} }
slog.Debug("ViewScript") slog.Debug("ViewScript")
slog.Debug("", "varsOfPackages", varsOfPackages)
err = b.scriptViewerExecutor.ViewScript(ctx, input, sf, basePkg) err = b.scriptViewerExecutor.ViewScript(ctx, input, sf, basePkg)
if err != nil { if err != nil {
return nil, err return nil, err
@ -390,11 +391,11 @@ func (b *Builder) BuildPackage(
sources := []string{} sources := []string{}
checksums := []string{} checksums := []string{}
for _, vars := range varsOfPackages { for _, vars := range varsOfPackages {
buildDepends = append(buildDepends, vars.BuildDepends...) buildDepends = append(buildDepends, vars.BuildDepends.Resolved()...)
optDepends = append(optDepends, vars.OptDepends...) optDepends = append(optDepends, vars.OptDepends.Resolved()...)
depends = append(depends, vars.Depends...) depends = append(depends, vars.Depends.Resolved()...)
sources = append(sources, vars.Sources...) sources = append(sources, vars.Sources.Resolved()...)
checksums = append(checksums, vars.Checksums...) checksums = append(checksums, vars.Checksums.Resolved()...)
} }
buildDepends = removeDuplicates(buildDepends) buildDepends = removeDuplicates(buildDepends)
optDepends = removeDuplicates(optDepends) optDepends = removeDuplicates(optDepends)
@ -481,7 +482,7 @@ func (b *Builder) BuildPackage(
type InstallPkgsArgs struct { type InstallPkgsArgs struct {
BuildArgs BuildArgs
AlrPkgs []db.Package AlrPkgs []alrsh.Package
NativePkgs []string NativePkgs []string
} }
@ -492,7 +493,7 @@ func (b *Builder) InstallALRPackages(
BuildOptsProvider BuildOptsProvider
PkgFormatProvider PkgFormatProvider
}, },
alrPkgs []db.Package, alrPkgs []alrsh.Package,
) error { ) error {
for _, pkg := range alrPkgs { for _, pkg := range alrPkgs {
res, err := b.BuildPackageFromDb( res, err := b.BuildPackageFromDb(
@ -539,7 +540,7 @@ func (b *Builder) BuildALRDeps(
found, notFound, err := b.repos.FindPkgs(ctx, depends) // Поиск зависимостей found, notFound, err := b.repos.FindPkgs(ctx, depends) // Поиск зависимостей
if err != nil { if err != nil {
return nil, nil, err return nil, nil, fmt.Errorf("failed FindPkgs: %w", err)
} }
repoDeps = notFound repoDeps = notFound
@ -551,7 +552,7 @@ func (b *Builder) BuildALRDeps(
input.BuildOpts().Interactive, input.BuildOpts().Interactive,
) )
type item struct { type item struct {
pkg *db.Package pkg *alrsh.Package
packages []string packages []string
} }
pkgsMap := make(map[string]*item) pkgsMap := make(map[string]*item)
@ -586,7 +587,7 @@ func (b *Builder) BuildALRDeps(
}, },
) )
if err != nil { if err != nil {
return nil, nil, err return nil, nil, fmt.Errorf("failed build package from db: %w", err)
} }
buildDeps = append(buildDeps, res...) buildDeps = append(buildDeps, res...)

View File

@ -23,7 +23,7 @@ import (
"github.com/goreleaser/nfpm/v2" "github.com/goreleaser/nfpm/v2"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
) )
type Cache struct { type Cache struct {
@ -33,7 +33,7 @@ type Cache struct {
func (c *Cache) CheckForBuiltPackage( func (c *Cache) CheckForBuiltPackage(
ctx context.Context, ctx context.Context,
input *BuildInput, input *BuildInput,
vars *types.BuildVars, vars *alrsh.Package,
) (string, bool, error) { ) (string, bool, error) {
filename, err := pkgFileName(input, vars) filename, err := pkgFileName(input, vars)
if err != nil { if err != nil {
@ -56,7 +56,7 @@ func pkgFileName(
PkgFormatProvider PkgFormatProvider
RepositoryProvider RepositoryProvider
}, },
vars *types.BuildVars, vars *alrsh.Package,
) (string, error) { ) (string, error) {
pkgInfo := getBasePkgInfo(vars, input) pkgInfo := getBasePkgInfo(vars, input)

View File

@ -25,7 +25,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/cpu" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager" "gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
) )
type Checker struct { type Checker struct {
@ -35,7 +35,7 @@ type Checker struct {
func (c *Checker) PerformChecks( func (c *Checker) PerformChecks(
ctx context.Context, ctx context.Context,
input *BuildInput, input *BuildInput,
vars *types.BuildVars, vars *alrsh.Package,
) (bool, error) { ) (bool, error) {
if !cpu.IsCompatibleWith(cpu.Arch(), vars.Architectures) { // Проверяем совместимость архитектуры if !cpu.IsCompatibleWith(cpu.Arch(), vars.Architectures) { // Проверяем совместимость архитектуры
cont, err := cliutils.YesNoPrompt( cont, err := cliutils.YesNoPrompt(

View File

@ -29,7 +29,6 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/logger" "gitea.plemya-x.ru/Plemya-x/ALR/internal/logger"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
) )
var HandshakeConfig = plugin.HandshakeConfig{ var HandshakeConfig = plugin.HandshakeConfig{
@ -51,13 +50,13 @@ type ScriptExecutorRPCServer struct {
// ReadScript // ReadScript
// //
func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) { func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ScriptFile, error) {
var resp *alrsh.ALRSh var resp *alrsh.ScriptFile
err := s.client.Call("Plugin.ReadScript", scriptPath, &resp) err := s.client.Call("Plugin.ReadScript", scriptPath, &resp)
return resp, err return resp, err
} }
func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *alrsh.ALRSh) error { func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *alrsh.ScriptFile) error {
file, err := s.Impl.ReadScript(context.Background(), scriptPath) file, err := s.Impl.ReadScript(context.Background(), scriptPath)
if err != nil { if err != nil {
return err return err
@ -73,15 +72,15 @@ func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *alrsh.ALRS
type ExecuteFirstPassArgs struct { type ExecuteFirstPassArgs struct {
Input *BuildInput Input *BuildInput
Sf *alrsh.ALRSh Sf *alrsh.ScriptFile
} }
type ExecuteFirstPassResp struct { type ExecuteFirstPassResp struct {
BasePkg string BasePkg string
VarsOfPackages []*types.BuildVars VarsOfPackages []*alrsh.Package
} }
func (s *ScriptExecutorRPC) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) { func (s *ScriptExecutorRPC) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ScriptFile) (string, []*alrsh.Package, error) {
var resp *ExecuteFirstPassResp var resp *ExecuteFirstPassResp
err := s.client.Call("Plugin.ExecuteFirstPass", &ExecuteFirstPassArgs{ err := s.client.Call("Plugin.ExecuteFirstPass", &ExecuteFirstPassArgs{
Input: input, Input: input,
@ -149,8 +148,8 @@ func (s *ScriptExecutorRPCServer) PrepareDirs(args *PrepareDirsArgs, reply *stru
type ExecuteSecondPassArgs struct { type ExecuteSecondPassArgs struct {
Input *BuildInput Input *BuildInput
Sf *alrsh.ALRSh Sf *alrsh.ScriptFile
VarsOfPackages []*types.BuildVars VarsOfPackages []*alrsh.Package
RepoDeps []string RepoDeps []string
BuiltDeps []*BuiltDep BuiltDeps []*BuiltDep
BasePkg string BasePkg string
@ -159,8 +158,8 @@ type ExecuteSecondPassArgs struct {
func (s *ScriptExecutorRPC) ExecuteSecondPass( func (s *ScriptExecutorRPC) ExecuteSecondPass(
ctx context.Context, ctx context.Context,
input *BuildInput, input *BuildInput,
sf *alrsh.ALRSh, sf *alrsh.ScriptFile,
varsOfPackages []*types.BuildVars, varsOfPackages []*alrsh.Package,
repoDeps []string, repoDeps []string,
builtDeps []*BuiltDep, builtDeps []*BuiltDep,
basePkg string, basePkg string,

View File

@ -53,11 +53,11 @@ func NewLocalScriptExecutor(cfg Config) *LocalScriptExecutor {
} }
} }
func (e *LocalScriptExecutor) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) { func (e *LocalScriptExecutor) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ScriptFile, error) {
return alrsh.ReadFromLocal(scriptPath) return alrsh.ReadFromLocal(scriptPath)
} }
func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) { func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ScriptFile) (string, []*alrsh.Package, error) {
return sf.ParseBuildVars(ctx, input.info, input.packages) return sf.ParseBuildVars(ctx, input.info, input.packages)
} }
@ -86,8 +86,8 @@ func (e *LocalScriptExecutor) PrepareDirs(
func (e *LocalScriptExecutor) ExecuteSecondPass( func (e *LocalScriptExecutor) ExecuteSecondPass(
ctx context.Context, ctx context.Context,
input *BuildInput, input *BuildInput,
sf *alrsh.ALRSh, sf *alrsh.ScriptFile,
varsOfPackages []*types.BuildVars, varsOfPackages []*alrsh.Package,
repoDeps []string, repoDeps []string,
builtDeps []*BuiltDep, builtDeps []*BuiltDep,
basePkg string, basePkg string,
@ -126,7 +126,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass(
for _, vars := range varsOfPackages { for _, vars := range varsOfPackages {
packageName := "" packageName := ""
if vars.Base != "" { if vars.BasePkgName != "" {
packageName = vars.Name packageName = vars.Name
} }
@ -194,24 +194,25 @@ func buildPkgMetadata(
PkgFormatProvider PkgFormatProvider
RepositoryProvider RepositoryProvider
}, },
vars *types.BuildVars, vars *alrsh.Package,
dirs types.Directories, dirs types.Directories,
deps []string, deps []string,
preferedContents *[]string, preferedContents *[]string,
) (*nfpm.Info, error) { ) (*nfpm.Info, error) {
pkgInfo := getBasePkgInfo(vars, input) pkgInfo := getBasePkgInfo(vars, input)
pkgInfo.Description = vars.Description slog.Warn("vars.Description", "vars.Description", vars.Description, "vars.Description.Resolved", vars.Description.Resolved())
pkgInfo.Description = vars.Description.Resolved()
pkgInfo.Platform = "linux" pkgInfo.Platform = "linux"
pkgInfo.Homepage = vars.Homepage pkgInfo.Homepage = vars.Homepage.Resolved()
pkgInfo.License = strings.Join(vars.Licenses, ", ") pkgInfo.License = strings.Join(vars.Licenses, ", ")
pkgInfo.Maintainer = vars.Maintainer pkgInfo.Maintainer = vars.Maintainer.Resolved()
pkgInfo.Overridables = nfpm.Overridables{ pkgInfo.Overridables = nfpm.Overridables{
Conflicts: append(vars.Conflicts, vars.Name), Conflicts: append(vars.Conflicts, vars.Name),
Replaces: vars.Replaces, Replaces: vars.Replaces,
Provides: append(vars.Provides, vars.Name), Provides: append(vars.Provides, vars.Name),
Depends: deps, Depends: deps,
} }
pkgInfo.Section = vars.Group pkgInfo.Section = vars.Group.Resolved()
pkgFormat := input.PkgFormat() pkgFormat := input.PkgFormat()
info := input.OSRelease() info := input.OSRelease()
@ -224,12 +225,12 @@ func buildPkgMetadata(
} }
if pkgFormat == "rpm" { if pkgFormat == "rpm" {
pkgInfo.RPM.Group = vars.Group pkgInfo.RPM.Group = vars.Group.Resolved()
if vars.Summary != "" { if vars.Summary.Resolved() != "" {
pkgInfo.RPM.Summary = vars.Summary pkgInfo.RPM.Summary = vars.Summary.Resolved()
} else { } else {
lines := strings.SplitN(vars.Description, "\n", 2) lines := strings.SplitN(vars.Description.Resolved(), "\n", 2)
pkgInfo.RPM.Summary = lines[0] pkgInfo.RPM.Summary = lines[0]
} }
} }
@ -250,17 +251,17 @@ func buildPkgMetadata(
} }
pkgInfo.Overridables.Contents = contents pkgInfo.Overridables.Contents = contents
if len(vars.AutoProv) == 1 && decoder.IsTruthy(vars.AutoProv[0]) { if len(vars.AutoProv.Resolved()) == 1 && decoder.IsTruthy(vars.AutoProv.Resolved()[0]) {
f := finddeps.New(info, pkgFormat) f := finddeps.New(info, pkgFormat)
err = f.FindProvides(ctx, pkgInfo, dirs, vars.AutoProvSkipList) err = f.FindProvides(ctx, pkgInfo, dirs, vars.AutoProvSkipList.Resolved())
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
if len(vars.AutoReq) == 1 && decoder.IsTruthy(vars.AutoReq[0]) { if len(vars.AutoReq.Resolved()) == 1 && decoder.IsTruthy(vars.AutoReq.Resolved()[0]) {
f := finddeps.New(info, pkgFormat) f := finddeps.New(info, pkgFormat)
err = f.FindRequires(ctx, pkgInfo, dirs, vars.AutoReqSkipList) err = f.FindRequires(ctx, pkgInfo, dirs, vars.AutoReqSkipList.Resolved())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -20,7 +20,7 @@ import (
"context" "context"
"path/filepath" "path/filepath"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
) )
type ScriptResolver struct { type ScriptResolver struct {
@ -34,7 +34,7 @@ type ScriptInfo struct {
func (s *ScriptResolver) ResolveScript( func (s *ScriptResolver) ResolveScript(
ctx context.Context, ctx context.Context,
pkg *db.Package, pkg *alrsh.Package,
) *ScriptInfo { ) *ScriptInfo {
var repository, script string var repository, script string

View File

@ -34,7 +34,7 @@ type ScriptViewer struct {
func (s *ScriptViewer) ViewScript( func (s *ScriptViewer) ViewScript(
ctx context.Context, ctx context.Context,
input *BuildInput, input *BuildInput,
a *alrsh.ALRSh, a *alrsh.ScriptFile,
basePkg string, basePkg string,
) error { ) error {
return cliutils.PromptViewScript( return cliutils.PromptViewScript(

View File

@ -40,6 +40,7 @@ import (
"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/manager" "gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
"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/pkg/alrsh"
"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/types" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
) )
@ -59,7 +60,7 @@ func prepareDirs(dirs types.Directories) error {
// Функция buildContents создает секцию содержимого пакета, которая содержит файлы, // Функция buildContents создает секцию содержимого пакета, которая содержит файлы,
// которые будут включены в конечный пакет. // которые будут включены в конечный пакет.
func buildContents(vars *types.BuildVars, dirs types.Directories, preferedContents *[]string) ([]*files.Content, error) { func buildContents(vars *alrsh.Package, dirs types.Directories, preferedContents *[]string) ([]*files.Content, error) {
contents := []*files.Content{} contents := []*files.Content{}
processPath := func(path, trimmed string, prefered bool) error { processPath := func(path, trimmed string, prefered bool) error {
@ -122,7 +123,7 @@ func buildContents(vars *types.BuildVars, dirs types.Directories, preferedConten
}, },
} }
if slices.Contains(vars.Backup, trimmed) { if slices.Contains(vars.Backup.Resolved(), trimmed) {
fileContent.Type = "config|noreplace" fileContent.Type = "config|noreplace"
} }
@ -155,7 +156,7 @@ func buildContents(vars *types.BuildVars, dirs types.Directories, preferedConten
var RegexpALRPackageName = regexp.MustCompile(`^(?P<package>[^+]+)\+alr-(?P<repo>.+)$`) var RegexpALRPackageName = regexp.MustCompile(`^(?P<package>[^+]+)\+alr-(?P<repo>.+)$`)
func getBasePkgInfo(vars *types.BuildVars, input interface { func getBasePkgInfo(vars *alrsh.Package, input interface {
RepositoryProvider RepositoryProvider
OsInfoProvider OsInfoProvider
}, },
@ -211,39 +212,39 @@ func createBuildEnvVars(info *distro.OSRelease, dirs types.Directories) []string
} }
// Функция setScripts добавляет скрипты-перехватчики к метаданным пакета. // Функция setScripts добавляет скрипты-перехватчики к метаданным пакета.
func setScripts(vars *types.BuildVars, info *nfpm.Info, scriptDir string) { func setScripts(vars *alrsh.Package, info *nfpm.Info, scriptDir string) {
if vars.Scripts.PreInstall != "" { if vars.Scripts.Resolved().PreInstall != "" {
info.Scripts.PreInstall = filepath.Join(scriptDir, vars.Scripts.PreInstall) info.Scripts.PreInstall = filepath.Join(scriptDir, vars.Scripts.Resolved().PreInstall)
} }
if vars.Scripts.PostInstall != "" { if vars.Scripts.Resolved().PostInstall != "" {
info.Scripts.PostInstall = filepath.Join(scriptDir, vars.Scripts.PostInstall) info.Scripts.PostInstall = filepath.Join(scriptDir, vars.Scripts.Resolved().PostInstall)
} }
if vars.Scripts.PreRemove != "" { if vars.Scripts.Resolved().PreRemove != "" {
info.Scripts.PreRemove = filepath.Join(scriptDir, vars.Scripts.PreRemove) info.Scripts.PreRemove = filepath.Join(scriptDir, vars.Scripts.Resolved().PreRemove)
} }
if vars.Scripts.PostRemove != "" { if vars.Scripts.Resolved().PostRemove != "" {
info.Scripts.PostRemove = filepath.Join(scriptDir, vars.Scripts.PostRemove) info.Scripts.PostRemove = filepath.Join(scriptDir, vars.Scripts.Resolved().PostRemove)
} }
if vars.Scripts.PreUpgrade != "" { if vars.Scripts.Resolved().PreUpgrade != "" {
info.ArchLinux.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.PreUpgrade) info.ArchLinux.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PreUpgrade)
info.APK.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.PreUpgrade) info.APK.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PreUpgrade)
} }
if vars.Scripts.PostUpgrade != "" { if vars.Scripts.Resolved().PostUpgrade != "" {
info.ArchLinux.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.PostUpgrade) info.ArchLinux.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PostUpgrade)
info.APK.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.PostUpgrade) info.APK.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PostUpgrade)
} }
if vars.Scripts.PreTrans != "" { if vars.Scripts.Resolved().PreTrans != "" {
info.RPM.Scripts.PreTrans = filepath.Join(scriptDir, vars.Scripts.PreTrans) info.RPM.Scripts.PreTrans = filepath.Join(scriptDir, vars.Scripts.Resolved().PreTrans)
} }
if vars.Scripts.PostTrans != "" { if vars.Scripts.Resolved().PostTrans != "" {
info.RPM.Scripts.PostTrans = filepath.Join(scriptDir, vars.Scripts.PostTrans) info.RPM.Scripts.PostTrans = filepath.Join(scriptDir, vars.Scripts.Resolved().PostTrans)
} }
} }

View File

@ -123,8 +123,15 @@ func (b *AppBuilder) withRepos(enablePull, forcePull bool) *AppBuilder {
cfg := b.deps.Cfg cfg := b.deps.Cfg
db := b.deps.DB db := b.deps.DB
if cfg == nil || db == nil { info := b.deps.Info
b.err = errors.New("config and db are required before initializing repos")
if info == nil {
b.WithDistroInfo()
info = b.deps.Info
}
if cfg == nil || db == nil || info == nil {
b.err = errors.New("config, db and info are required before initializing repos")
return b return b
} }

View File

@ -28,8 +28,8 @@ import (
"github.com/AlecAivazis/survey/v2" "github.com/AlecAivazis/survey/v2"
"github.com/leonelquinteros/gotext" "github.com/leonelquinteros/gotext"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/pager" "gitea.plemya-x.ru/Plemya-x/ALR/internal/pager"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
) )
// YesNoPrompt asks the user a yes or no question, using def as the default answer // YesNoPrompt asks the user a yes or no question, using def as the default answer
@ -102,8 +102,8 @@ func ShowScript(path, name, style string) error {
// FlattenPkgs attempts to flatten the a map of slices of packages into a single slice // FlattenPkgs attempts to flatten the a map of slices of packages into a single slice
// of packages by prompting the user if multiple packages match. // of packages by prompting the user if multiple packages match.
func FlattenPkgs(ctx context.Context, found map[string][]db.Package, verb string, interactive bool) []db.Package { func FlattenPkgs(ctx context.Context, found map[string][]alrsh.Package, verb string, interactive bool) []alrsh.Package {
var outPkgs []db.Package var outPkgs []alrsh.Package
for _, pkgs := range found { for _, pkgs := range found {
if len(pkgs) > 1 && interactive { if len(pkgs) > 1 && interactive {
choice, err := PkgPrompt(ctx, pkgs, verb, interactive) choice, err := PkgPrompt(ctx, pkgs, verb, interactive)
@ -120,7 +120,7 @@ func FlattenPkgs(ctx context.Context, found map[string][]db.Package, verb string
} }
// PkgPrompt asks the user to choose between multiple packages. // PkgPrompt asks the user to choose between multiple packages.
func PkgPrompt(ctx context.Context, options []db.Package, verb string, interactive bool) (db.Package, error) { func PkgPrompt(ctx context.Context, options []alrsh.Package, verb string, interactive bool) (alrsh.Package, error) {
if !interactive { if !interactive {
return options[0], nil return options[0], nil
} }
@ -138,7 +138,7 @@ func PkgPrompt(ctx context.Context, options []db.Package, verb string, interacti
var choice int var choice int
err := survey.AskOne(prompt, &choice) err := survey.AskOne(prompt, &choice)
if err != nil { if err != nil {
return db.Package{}, err return alrsh.Package{}, err
} }
return options[choice], nil return options[choice], nil

View File

@ -20,6 +20,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"runtime/debug"
"github.com/leonelquinteros/gotext" "github.com/leonelquinteros/gotext"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
@ -44,10 +45,12 @@ func HandleExitCoder(err error) {
slog.Error(err.Error()) slog.Error(err.Error())
} }
} }
debug.PrintStack()
cli.OsExiter(exitErr.ExitCode()) cli.OsExiter(exitErr.ExitCode())
return return
} }
debug.PrintStack()
slog.Error(err.Error()) slog.Error(err.Error())
cli.OsExiter(1) cli.OsExiter(1)
} }

View File

@ -28,32 +28,11 @@ import (
"xorm.io/xorm" "xorm.io/xorm"
"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/pkg/alrsh"
) )
const CurrentVersion = 5 const CurrentVersion = 5
type Package struct {
BasePkgName string `sh:"basepkg_name" xorm:"notnull 'basepkg_name'"`
Name string `sh:"name,required" xorm:"notnull unique(name_repo) 'name'"`
Version string `sh:"version,required" xorm:"notnull 'version'"`
Release int `sh:"release" xorm:"notnull 'release'"`
Epoch uint `sh:"epoch" xorm:"'epoch'"`
Summary map[string]string `xorm:"json 'summary'"`
Description map[string]string `xorm:"json 'description'"`
Group map[string]string `xorm:"json 'group_name'"`
Homepage map[string]string `xorm:"json 'homepage'"`
Maintainer map[string]string `xorm:"json 'maintainer'"`
Architectures []string `sh:"architectures" xorm:"json 'architectures'"`
Licenses []string `sh:"license" xorm:"json 'licenses'"`
Provides []string `sh:"provides" xorm:"json 'provides'"`
Conflicts []string `sh:"conflicts" xorm:"json 'conflicts'"`
Replaces []string `sh:"replaces" xorm:"json 'replaces'"`
Depends map[string][]string `xorm:"json 'depends'"`
BuildDepends map[string][]string `xorm:"json 'builddepends'"`
OptDepends map[string][]string `xorm:"json 'optdepends'"`
Repository string `xorm:"notnull unique(name_repo) 'repository'"`
}
type Version struct { type Version struct {
Version int `xorm:"'version'"` Version int `xorm:"'version'"`
} }
@ -76,6 +55,8 @@ func New(config Config) *Database {
func (d *Database) Connect() error { func (d *Database) Connect() error {
dsn := d.config.GetPaths().DBPath dsn := d.config.GetPaths().DBPath
engine, err := xorm.NewEngine("sqlite", dsn) engine, err := xorm.NewEngine("sqlite", dsn)
// engine.SetLogLevel(log.LOG_DEBUG)
// engine.ShowSQL(true)
if err != nil { if err != nil {
return err return err
} }
@ -87,7 +68,7 @@ func (d *Database) Init(ctx context.Context) error {
if err := d.Connect(); err != nil { if err := d.Connect(); err != nil {
return err return err
} }
if err := d.engine.Sync2(new(Package), new(Version)); err != nil { if err := d.engine.Sync2(new(alrsh.Package), new(Version)); err != nil {
return err return err
} }
ver, ok := d.GetVersion(ctx) ver, ok := d.GetVersion(ctx)
@ -119,10 +100,10 @@ func (d *Database) addVersion(ver int) error {
} }
func (d *Database) reset() error { func (d *Database) reset() error {
return d.engine.DropTables(new(Package), new(Version)) return d.engine.DropTables(new(alrsh.Package), new(Version))
} }
func (d *Database) InsertPackage(ctx context.Context, pkg Package) error { func (d *Database) InsertPackage(ctx context.Context, pkg alrsh.Package) error {
session := d.engine.Context(ctx) session := d.engine.Context(ctx)
affected, err := session.Where("name = ? AND repository = ?", pkg.Name, pkg.Repository).Update(&pkg) affected, err := session.Where("name = ? AND repository = ?", pkg.Name, pkg.Repository).Update(&pkg)
@ -140,14 +121,14 @@ func (d *Database) InsertPackage(ctx context.Context, pkg Package) error {
return nil return nil
} }
func (d *Database) GetPkgs(_ context.Context, where string, args ...any) ([]Package, error) { func (d *Database) GetPkgs(_ context.Context, where string, args ...any) ([]alrsh.Package, error) {
var pkgs []Package var pkgs []alrsh.Package
err := d.engine.Where(where, args...).Find(&pkgs) err := d.engine.Where(where, args...).Find(&pkgs)
return pkgs, err return pkgs, err
} }
func (d *Database) GetPkg(where string, args ...any) (*Package, error) { func (d *Database) GetPkg(where string, args ...any) (*alrsh.Package, error) {
var pkg Package var pkg alrsh.Package
has, err := d.engine.Where(where, args...).Get(&pkg) has, err := d.engine.Where(where, args...).Get(&pkg)
if err != nil || !has { if err != nil || !has {
return nil, err return nil, err
@ -156,12 +137,12 @@ func (d *Database) GetPkg(where string, args ...any) (*Package, error) {
} }
func (d *Database) DeletePkgs(_ context.Context, where string, args ...any) error { func (d *Database) DeletePkgs(_ context.Context, where string, args ...any) error {
_, err := d.engine.Where(where, args...).Delete(&Package{}) _, err := d.engine.Where(where, args...).Delete(&alrsh.Package{})
return err return err
} }
func (d *Database) IsEmpty() bool { func (d *Database) IsEmpty() bool {
count, err := d.engine.Count(new(Package)) count, err := d.engine.Count(new(alrsh.Package))
return err != nil || count == 0 return err != nil || count == 0
} }

View File

@ -25,8 +25,11 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/stretchr/testify/assert"
"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" "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
) )
type TestALRConfig struct{} type TestALRConfig struct{}
@ -43,35 +46,38 @@ func prepareDb() *db.Database {
return database return database
} }
var testPkg = db.Package{ var testPkg = alrsh.Package{
Name: "test", Name: "test",
Version: "0.0.1", Version: "0.0.1",
Release: 1, Release: 1,
Epoch: 2, Epoch: 2,
Description: map[string]string{ Description: alrsh.OverridableFromMap(map[string]string{
"en": "Test package", "en": "Test package",
"ru": "Проверочный пакет", "ru": "Проверочный пакет",
}, }),
Homepage: map[string]string{ Homepage: alrsh.OverridableFromMap(map[string]string{
"en": "https://gitea.plemya-x.ru/xpamych/ALR", "en": "https://gitea.plemya-x.ru/xpamych/ALR",
}, }),
Maintainer: map[string]string{ Maintainer: alrsh.OverridableFromMap(map[string]string{
"en": "Evgeniy Khramov <xpamych@yandex.ru>", "en": "Evgeniy Khramov <xpamych@yandex.ru>",
"ru": "Евгений Храмов <xpamych@yandex.ru>", "ru": "Евгений Храмов <xpamych@yandex.ru>",
}, }),
Architectures: []string{"arm64", "amd64"}, Architectures: []string{"arm64", "amd64"},
Licenses: []string{"GPL-3.0-or-later"}, Licenses: []string{"GPL-3.0-or-later"},
Provides: []string{"test"}, Provides: []string{"test"},
Conflicts: []string{"test"}, Conflicts: []string{"test"},
Replaces: []string{"test-old"}, Replaces: []string{"test-old"},
Depends: map[string][]string{ Depends: alrsh.OverridableFromMap(map[string][]string{
"": {"sudo"}, "": {"sudo"},
}, }),
BuildDepends: map[string][]string{ BuildDepends: alrsh.OverridableFromMap(map[string][]string{
"": {"golang"}, "": {"golang"},
"arch": {"go"}, "arch": {"go"},
}, }),
Repository: "default", Repository: "default",
Summary: alrsh.OverridableFromMap(map[string]string{}),
Group: alrsh.OverridableFromMap(map[string]string{}),
OptDepends: alrsh.OverridableFromMap(map[string][]string{}),
} }
func TestInit(t *testing.T) { func TestInit(t *testing.T) {
@ -106,9 +112,7 @@ func TestInsertPackage(t *testing.T) {
t.Fatalf("Expected 1 package, got %d", len(pkgs)) t.Fatalf("Expected 1 package, got %d", len(pkgs))
} }
if !reflect.DeepEqual(testPkg, pkgs[0]) { assert.Equal(t, testPkg, pkgs[0])
t.Errorf("Expected test package to be the same as database package")
}
} }
func TestGetPkgs(t *testing.T) { func TestGetPkgs(t *testing.T) {

View File

@ -21,7 +21,6 @@ package overrides
import ( import (
"fmt" "fmt"
"reflect"
"regexp" "regexp"
"strings" "strings"
@ -29,7 +28,6 @@ import (
"golang.org/x/text/language" "golang.org/x/text/language"
"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/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
) )
@ -150,65 +148,6 @@ func (o *Opts) WithLanguageTags(langs []string) *Opts {
return out return out
} }
// ResolvedPackage is a ALR package after its overrides
// have been resolved
type ResolvedPackage struct {
Name string `sh:"name"`
Version string `sh:"version"`
Release int `sh:"release"`
Epoch uint `sh:"epoch"`
Group string `db:"group_name"`
Summary string `db:"summary"`
Description string `db:"description"`
Homepage string `db:"homepage"`
Maintainer string `db:"maintainer"`
Architectures []string `sh:"architectures"`
Licenses []string `sh:"license"`
Provides []string `sh:"provides"`
Conflicts []string `sh:"conflicts"`
Replaces []string `sh:"replaces"`
Depends []string `sh:"deps"`
BuildDepends []string `sh:"build_deps"`
OptDepends []string `sh:"opt_deps"`
}
func ResolvePackage(pkg *db.Package, overrides []string) *ResolvedPackage {
out := &ResolvedPackage{}
outVal := reflect.ValueOf(out).Elem()
pkgVal := reflect.ValueOf(pkg).Elem()
for i := 0; i < outVal.NumField(); i++ {
fieldVal := outVal.Field(i)
fieldType := fieldVal.Type()
pkgFieldVal := pkgVal.FieldByName(outVal.Type().Field(i).Name)
pkgFieldType := pkgFieldVal.Type()
if strings.HasPrefix(pkgFieldType.String(), "db.JSON") {
pkgFieldVal = pkgFieldVal.FieldByName("Val")
pkgFieldType = pkgFieldVal.Type()
}
if pkgFieldType.AssignableTo(fieldType) {
fieldVal.Set(pkgFieldVal)
continue
}
if pkgFieldVal.Kind() == reflect.Map && pkgFieldType.Elem().AssignableTo(fieldType) {
for _, override := range overrides {
overrideVal := pkgFieldVal.MapIndex(reflect.ValueOf(override))
if !overrideVal.IsValid() {
continue
}
fieldVal.Set(overrideVal)
break
}
}
}
return out
}
func parseLangs(langs []string, tags []language.Tag) ([]string, error) { func parseLangs(langs []string, tags []language.Tag) ([]string, error) {
out := make([]string, len(tags)+len(langs)) out := make([]string, len(tags)+len(langs))
for i, tag := range tags { for i, tag := range tags {

View File

@ -22,11 +22,11 @@ package repos
import ( import (
"context" "context"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
) )
func (rs *Repos) FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.Package, []string, error) { func (rs *Repos) FindPkgs(ctx context.Context, pkgs []string) (map[string][]alrsh.Package, []string, error) {
found := map[string][]db.Package{} found := map[string][]alrsh.Package{}
notFound := []string(nil) notFound := []string(nil)
for _, pkgName := range pkgs { for _, pkgName := range pkgs {

View File

@ -24,8 +24,8 @@ import (
"strings" "strings"
"testing" "testing"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/repos" "gitea.plemya-x.ru/Plemya-x/ALR/internal/repos"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
) )
@ -89,31 +89,31 @@ func TestFindPkgsEmpty(t *testing.T) {
e.Db, e.Db,
) )
err := e.Db.InsertPackage(e.Ctx, db.Package{ err := e.Db.InsertPackage(e.Ctx, alrsh.Package{
Name: "test1", Name: "test1",
Repository: "default", Repository: "default",
Version: "0.0.1", Version: "0.0.1",
Release: 1, Release: 1,
Description: map[string]string{ Provides: []string{""},
Description: alrsh.OverridableFromMap(map[string]string{
"en": "Test package 1", "en": "Test package 1",
"ru": "Проверочный пакет 1", "ru": "Проверочный пакет 1",
}, }),
Provides: []string{""},
}) })
if err != nil { if err != nil {
t.Fatalf("Expected no error, got %s", err) t.Fatalf("Expected no error, got %s", err)
} }
err = e.Db.InsertPackage(e.Ctx, db.Package{ err = e.Db.InsertPackage(e.Ctx, alrsh.Package{
Name: "test2", Name: "test2",
Repository: "default", Repository: "default",
Version: "0.0.1", Version: "0.0.1",
Release: 1, Release: 1,
Description: map[string]string{ Provides: []string{"test"},
Description: alrsh.OverridableFromMap(map[string]string{
"en": "Test package 2", "en": "Test package 2",
"ru": "Проверочный пакет 2", "ru": "Проверочный пакет 2",
}, }),
Provides: []string{"test"},
}) })
if err != nil { if err != nil {
t.Fatalf("Expected no error, got %s", err) t.Fatalf("Expected no error, got %s", err)

View File

@ -27,6 +27,7 @@ import (
"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" "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
) )
@ -84,10 +85,10 @@ build_deps=('golang')
result, err := database.GetPkgs(ctx, "1 = 1") result, err := database.GetPkgs(ctx, "1 = 1")
assert.NoError(t, err) assert.NoError(t, err)
pkgCount := 0 pkgCount := 0
for _, dbPkg := range result { for _, pkg := range result {
assert.Equal(t, "foo", dbPkg.Name) assert.Equal(t, "foo", pkg.Name)
assert.Equal(t, map[string]string{"": "main desc"}, dbPkg.Description) assert.Equal(t, alrsh.OverridableFromMap(map[string]string{"": "main desc"}), pkg.Description)
assert.Equal(t, map[string][]string{"": {"sudo"}}, dbPkg.Depends) assert.Equal(t, alrsh.OverridableFromMap(map[string][]string{"": {"sudo"}}), pkg.Depends)
pkgCount++ pkgCount++
} }
assert.Equal(t, 1, pkgCount) assert.Equal(t, 1, pkgCount)
@ -119,18 +120,18 @@ meta_buz() {
assert.NoError(t, err) assert.NoError(t, err)
pkgCount := 0 pkgCount := 0
for _, dbPkg := range result { for _, pkg := range result {
if err != nil { if err != nil {
t.Errorf("Expected no error, got %s", err) t.Errorf("Expected no error, got %s", err)
} }
if dbPkg.Name == "bar" { if pkg.Name == "bar" {
assert.Equal(t, map[string]string{"": "foo desc"}, dbPkg.Description) assert.Equal(t, alrsh.OverridableFromMap(map[string]string{"": "foo desc"}), pkg.Description)
assert.Equal(t, map[string][]string{"": {"sudo"}}, dbPkg.Depends) assert.Equal(t, alrsh.OverridableFromMap(map[string][]string{"": {"sudo"}}), pkg.Depends)
} }
if dbPkg.Name == "buz" { if pkg.Name == "buz" {
assert.Equal(t, map[string]string{"": "main desc"}, dbPkg.Description) assert.Equal(t, alrsh.OverridableFromMap(map[string]string{"": "main desc"}), pkg.Description)
assert.Equal(t, map[string][]string{"": {"sudo", "doas"}}, dbPkg.Depends) assert.Equal(t, alrsh.OverridableFromMap(map[string][]string{"": {"sudo", "doas"}}), pkg.Depends)
} }
pkgCount++ pkgCount++
} }

View File

@ -18,12 +18,9 @@ package repos
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"io" "io"
"path/filepath" "path/filepath"
"reflect"
"strings"
"github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing"
@ -34,9 +31,7 @@ import (
"mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/syntax" "mvdan.cc/sh/v3/syntax"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/parser"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder"
"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/types" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
) )
@ -63,151 +58,21 @@ func parseScript(
syntaxParser *syntax.Parser, syntaxParser *syntax.Parser,
runner *interp.Runner, runner *interp.Runner,
r io.ReadCloser, r io.ReadCloser,
) ([]*db.Package, error) { ) ([]*alrsh.Package, error) {
fl, err := syntaxParser.Parse(r, "alr.sh") f, err := alrsh.ReadFromIOReader(r, "/tmp")
if err != nil { if err != nil {
return nil, err return nil, err
} }
_, dbPkgs, err := f.ParseBuildVars(ctx, &distro.OSRelease{}, []string{})
runner.Reset()
err = runner.Run(ctx, fl)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, pkg := range dbPkgs {
d := decoder.New(&distro.OSRelease{}, runner) pkg.Repository = repo.Name
d.Overrides = false
d.LikeDistros = false
pkgNames, err := parser.ParseNames(d)
if err != nil {
return nil, fmt.Errorf("failed parsing package names: %w", err)
} }
if len(pkgNames.Names) == 0 {
return nil, errors.New("package name is missing")
}
var dbPkgs []*db.Package
if len(pkgNames.Names) > 1 {
if pkgNames.BasePkgName == "" {
pkgNames.BasePkgName = pkgNames.Names[0]
}
for _, pkgName := range pkgNames.Names {
pkgInfo := PackageInfo{}
funcName := fmt.Sprintf("meta_%s", pkgName)
runner.Reset()
err = runner.Run(ctx, fl)
if err != nil {
return nil, err
}
meta, ok := d.GetFuncWithSubshell(funcName)
if !ok {
return nil, fmt.Errorf("func %s is missing", funcName)
}
r, err := meta(ctx)
if err != nil {
return nil, err
}
d := decoder.New(&distro.OSRelease{}, r)
d.Overrides = false
d.LikeDistros = false
err = d.DecodeVars(&pkgInfo)
if err != nil {
return nil, err
}
pkg := pkgInfo.ToPackage(repo.Name)
resolveOverrides(r, pkg)
pkg.Name = pkgName
pkg.BasePkgName = pkgNames.BasePkgName
dbPkgs = append(dbPkgs, pkg)
}
return dbPkgs, nil
}
pkg := EmptyPackage(repo.Name)
err = d.DecodeVars(pkg)
if err != nil {
return nil, err
}
resolveOverrides(runner, pkg)
dbPkgs = append(dbPkgs, pkg)
return dbPkgs, nil return dbPkgs, nil
} }
type PackageInfo struct {
Version string `sh:"version,required"`
Release int `sh:"release,required"`
Epoch uint `sh:"epoch"`
Architectures []string `sh:"architectures"`
Licenses []string `sh:"license"`
Provides []string `sh:"provides"`
Conflicts []string `sh:"conflicts"`
Replaces []string `sh:"replaces"`
}
func (inf *PackageInfo) ToPackage(repoName string) *db.Package {
pkg := EmptyPackage(repoName)
pkg.Version = inf.Version
pkg.Release = inf.Release
pkg.Epoch = inf.Epoch
pkg.Architectures = inf.Architectures
pkg.Licenses = inf.Licenses
pkg.Provides = inf.Provides
pkg.Conflicts = inf.Conflicts
pkg.Replaces = inf.Replaces
return pkg
}
func EmptyPackage(repoName string) *db.Package {
return &db.Package{
Group: map[string]string{},
Summary: map[string]string{},
Description: map[string]string{},
Homepage: map[string]string{},
Maintainer: map[string]string{},
Depends: map[string][]string{},
BuildDepends: map[string][]string{},
Repository: repoName,
}
}
var overridable = map[string]string{
"deps": "Depends",
"build_deps": "BuildDepends",
"desc": "Description",
"homepage": "Homepage",
"maintainer": "Maintainer",
"group": "Group",
"summary": "Summary",
}
func resolveOverrides(runner *interp.Runner, pkg *db.Package) {
pkgVal := reflect.ValueOf(pkg).Elem()
for name, val := range runner.Vars {
for prefix, field := range overridable {
if strings.HasPrefix(name, prefix) {
override := strings.TrimPrefix(name, prefix)
override = strings.TrimPrefix(override, "_")
varVal := pkgVal.FieldByName(field)
varType := varVal.Type()
switch varType.Elem().String() {
case "[]string":
varVal.SetMapIndex(reflect.ValueOf(override), reflect.ValueOf(val.List))
case "string":
varVal.SetMapIndex(reflect.ValueOf(override), reflect.ValueOf(val.Str))
}
break
}
}
}
}
func getHeadReference(r *git.Repository) (plumbing.ReferenceName, error) { func getHeadReference(r *git.Repository) (plumbing.ReferenceName, error) {
remote, err := r.Remote(git.DefaultRemoteName) remote, err := r.Remote(git.DefaultRemoteName)
if err != nil { if err != nil {

View File

@ -22,12 +22,11 @@ package search
import ( import (
"context" "context"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
) )
type PackagesProvider interface { type PackagesProvider interface {
GetPkgs(ctx context.Context, where string, args ...any) ([]db.Package, error) GetPkgs(ctx context.Context, where string, args ...any) ([]alrsh.Package, error)
} }
type Searcher struct { type Searcher struct {
@ -43,7 +42,7 @@ func New(pp PackagesProvider) *Searcher {
func (s *Searcher) Search( func (s *Searcher) Search(
ctx context.Context, ctx context.Context,
opts *SearchOptions, opts *SearchOptions,
) ([]database.Package, error) { ) ([]alrsh.Package, error) {
where, args := opts.WhereClause() where, args := opts.WhereClause()
packages, err := s.pp.GetPkgs(ctx, where, args...) packages, err := s.pp.GetPkgs(ctx, where, args...)
return packages, err return packages, err

View File

@ -22,6 +22,8 @@ package decoder
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"log/slog"
"reflect" "reflect"
"strings" "strings"
@ -52,7 +54,7 @@ type InvalidTypeError struct {
} }
func (ite InvalidTypeError) Error() string { func (ite InvalidTypeError) Error() string {
return "variable '" + ite.name + "' is of type " + ite.vartype + ", but " + ite.exptype + " is expected" return fmt.Sprintf("variable '%s' is of type %s, but %s is expected", ite.name, ite.vartype, ite.exptype)
} }
// Decoder provides methods for decoding variable values // Decoder provides methods for decoding variable values
@ -80,10 +82,58 @@ func (d *Decoder) DecodeVar(name string, val any) error {
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
WeaklyTypedInput: true, WeaklyTypedInput: true,
Result: val, DecodeHook: mapstructure.DecodeHookFuncValue(func(from, to reflect.Value) (interface{}, error) {
TagName: "sh", if strings.Contains(to.Type().String(), "alrsh.OverridableField") {
if to.Kind() != reflect.Ptr && to.CanAddr() {
to = to.Addr()
}
names, err := overrides.Resolve(d.info, overrides.DefaultOpts.WithName(name))
if err != nil {
return nil, err
}
isNotSet := true
setMethod := to.MethodByName("Set")
setResolvedMethod := to.MethodByName("SetResolved")
for _, varName := range names {
val := d.getVarNoOverrides(varName)
if val == nil {
continue
}
t := setMethod.Type().In(1)
newVal := from
if !newVal.Type().AssignableTo(t) {
newVal = reflect.New(t)
err = d.DecodeVar(name, newVal.Interface())
if err != nil {
return nil, err
}
newVal = newVal.Elem()
}
if isNotSet {
setResolvedMethod.Call([]reflect.Value{newVal})
}
override := strings.TrimPrefix(strings.TrimPrefix(varName, name), "_")
setMethod.Call([]reflect.Value{reflect.ValueOf(override), newVal})
}
return to, nil
}
return from.Interface(), nil
}),
Result: val,
TagName: "sh",
}) })
if err != nil { if err != nil {
slog.Warn("err", "err", err)
return err return err
} }
@ -243,23 +293,31 @@ func (d *Decoder) getVar(name string) *expand.Variable {
} }
for _, varName := range names { for _, varName := range names {
val, ok := d.Runner.Vars[varName] res := d.getVarNoOverrides(varName)
if ok { if res != nil {
// Resolve nameref variables return res
_, resolved := val.Resolve(expand.FuncEnviron(func(s string) string {
if val, ok := d.Runner.Vars[s]; ok {
return val.String()
}
return ""
}))
val = resolved
return &val
} }
} }
return nil return nil
} }
func (d *Decoder) getVarNoOverrides(name string) *expand.Variable {
val, ok := d.Runner.Vars[name]
if ok {
// Resolve nameref variables
_, resolved := val.Resolve(expand.FuncEnviron(func(s string) string {
if val, ok := d.Runner.Vars[s]; ok {
return val.String()
}
return ""
}))
val = resolved
return &val
}
return nil
}
func IsTruthy(value string) bool { func IsTruthy(value string) bool {
value = strings.ToLower(strings.TrimSpace(value)) value = strings.ToLower(strings.TrimSpace(value))
return value == "true" || value == "yes" || value == "1" return value == "true" || value == "yes" || value == "1"

View File

@ -114,35 +114,35 @@ msgstr ""
msgid "Error parsing os-release file" msgid "Error parsing os-release file"
msgstr "" msgstr ""
#: info.go:41 #: info.go:42
msgid "Print information about a package" msgid "Print information about a package"
msgstr "" msgstr ""
#: info.go:46 #: info.go:47
msgid "Show all information, not just for the current distro" msgid "Show all information, not just for the current distro"
msgstr "" msgstr ""
#: info.go:67 #: info.go:68
msgid "Error getting packages" msgid "Error getting packages"
msgstr "" msgstr ""
#: info.go:82 #: info.go:83
msgid "Command info expected at least 1 argument, got %d" msgid "Command info expected at least 1 argument, got %d"
msgstr "" msgstr ""
#: info.go:102 #: info.go:104
msgid "Error finding packages" msgid "Error finding packages"
msgstr "" msgstr ""
#: info.go:116 #: info.go:118
msgid "Can't detect system language" msgid "Can't detect system language"
msgstr "" msgstr ""
#: info.go:133 #: info.go:135
msgid "Error resolving overrides" msgid "Error resolving overrides"
msgstr "" msgstr ""
#: info.go:141 info.go:146 #: info.go:144 info.go:149
msgid "Error encoding script variables" msgid "Error encoding script variables"
msgstr "" msgstr ""
@ -174,19 +174,19 @@ msgstr ""
msgid "Error removing packages" msgid "Error removing packages"
msgstr "" msgstr ""
#: internal/build/build.go:375 #: internal/build/build.go:376
msgid "Building package" msgid "Building package"
msgstr "" msgstr ""
#: internal/build/build.go:404 #: internal/build/build.go:405
msgid "The checksums array must be the same length as sources" msgid "The checksums array must be the same length as sources"
msgstr "" msgstr ""
#: internal/build/build.go:446 #: internal/build/build.go:447
msgid "Downloading sources" msgid "Downloading sources"
msgstr "" msgstr ""
#: internal/build/build.go:538 #: internal/build/build.go:539
msgid "Installing dependencies" msgid "Installing dependencies"
msgstr "" msgstr ""
@ -224,15 +224,15 @@ msgstr ""
msgid "Building package metadata" msgid "Building package metadata"
msgstr "" msgstr ""
#: internal/build/script_executor.go:275 #: internal/build/script_executor.go:276
msgid "Executing prepare()" msgid "Executing prepare()"
msgstr "" msgstr ""
#: internal/build/script_executor.go:284 #: internal/build/script_executor.go:285
msgid "Executing build()" msgid "Executing build()"
msgstr "" msgstr ""
#: internal/build/script_executor.go:313 internal/build/script_executor.go:333 #: internal/build/script_executor.go:314 internal/build/script_executor.go:334
msgid "Executing %s()" msgid "Executing %s()"
msgstr "" msgstr ""
@ -244,15 +244,15 @@ msgstr ""
msgid "Error initialization database" msgid "Error initialization database"
msgstr "" msgstr ""
#: internal/cliutils/app_builder/builder.go:135 #: internal/cliutils/app_builder/builder.go:142
msgid "Error pulling repositories" msgid "Error pulling repositories"
msgstr "" msgstr ""
#: internal/cliutils/app_builder/builder.go:152 #: internal/cliutils/app_builder/builder.go:159
msgid "Error parsing os release" msgid "Error parsing os release"
msgstr "" msgstr ""
#: internal/cliutils/app_builder/builder.go:165 #: internal/cliutils/app_builder/builder.go:172
msgid "Unable to detect a supported package manager on the system" msgid "Unable to detect a supported package manager on the system"
msgstr "" msgstr ""
@ -336,17 +336,17 @@ msgstr ""
msgid "OPTIONS" msgid "OPTIONS"
msgstr "" msgstr ""
#: internal/cliutils/utils.go:69 #: internal/cliutils/utils.go:72
msgid "" msgid ""
"This command is deprecated and would be removed in the future, use \"%s\" " "This command is deprecated and would be removed in the future, use \"%s\" "
"instead!" "instead!"
msgstr "" msgstr ""
#: internal/db/db.go:95 #: internal/db/db.go:76
msgid "Database version mismatch; resetting" msgid "Database version mismatch; resetting"
msgstr "" msgstr ""
#: internal/db/db.go:101 #: internal/db/db.go:82
msgid "" msgid ""
"Database version does not exist. Run alr fix if something isn't working." "Database version does not exist. Run alr fix if something isn't working."
msgstr "" msgstr ""
@ -541,14 +541,14 @@ msgstr ""
msgid "Error while executing search" msgid "Error while executing search"
msgstr "" msgstr ""
#: upgrade.go:47 #: upgrade.go:48
msgid "Upgrade all installed packages" msgid "Upgrade all installed packages"
msgstr "" msgstr ""
#: upgrade.go:105 upgrade.go:122 #: upgrade.go:106 upgrade.go:123
msgid "Error checking for updates" msgid "Error checking for updates"
msgstr "" msgstr ""
#: upgrade.go:125 #: upgrade.go:126
msgid "There is nothing to do." msgid "There is nothing to do."
msgstr "" msgstr ""

View File

@ -121,35 +121,35 @@ msgstr "Такой вспомогательной команды нет"
msgid "Error parsing os-release file" msgid "Error parsing os-release file"
msgstr "Ошибка при разборе файла выпуска операционной системы" msgstr "Ошибка при разборе файла выпуска операционной системы"
#: info.go:41 #: info.go:42
msgid "Print information about a package" msgid "Print information about a package"
msgstr "Отобразить информацию о пакете" msgstr "Отобразить информацию о пакете"
#: info.go:46 #: info.go:47
msgid "Show all information, not just for the current distro" msgid "Show all information, not just for the current distro"
msgstr "Показывать всю информацию, не только для текущего дистрибутива" msgstr "Показывать всю информацию, не только для текущего дистрибутива"
#: info.go:67 #: info.go:68
msgid "Error getting packages" msgid "Error getting packages"
msgstr "Ошибка при получении пакетов" msgstr "Ошибка при получении пакетов"
#: info.go:82 #: info.go:83
msgid "Command info expected at least 1 argument, got %d" msgid "Command info expected at least 1 argument, got %d"
msgstr "Для команды info ожидался хотя бы 1 аргумент, получено %d" msgstr "Для команды info ожидался хотя бы 1 аргумент, получено %d"
#: info.go:102 #: info.go:104
msgid "Error finding packages" msgid "Error finding packages"
msgstr "Ошибка при поиске пакетов" msgstr "Ошибка при поиске пакетов"
#: info.go:116 #: info.go:118
msgid "Can't detect system language" msgid "Can't detect system language"
msgstr "Ошибка при определении языка системы" msgstr "Ошибка при определении языка системы"
#: info.go:133 #: info.go:135
msgid "Error resolving overrides" msgid "Error resolving overrides"
msgstr "Ошибка устранения переорпеделений" msgstr "Ошибка устранения переорпеделений"
#: info.go:141 info.go:146 #: info.go:144 info.go:149
msgid "Error encoding script variables" msgid "Error encoding script variables"
msgstr "Ошибка кодирования переменных скрита" msgstr "Ошибка кодирования переменных скрита"
@ -181,19 +181,19 @@ msgstr "Для команды remove ожидался хотя бы 1 аргум
msgid "Error removing packages" msgid "Error removing packages"
msgstr "Ошибка при удалении пакетов" msgstr "Ошибка при удалении пакетов"
#: internal/build/build.go:375 #: internal/build/build.go:376
msgid "Building package" msgid "Building package"
msgstr "Сборка пакета" msgstr "Сборка пакета"
#: internal/build/build.go:404 #: internal/build/build.go:405
msgid "The checksums array must be the same length as sources" msgid "The checksums array must be the same length as sources"
msgstr "Массив контрольных сумм должен быть той же длины, что и источники" msgstr "Массив контрольных сумм должен быть той же длины, что и источники"
#: internal/build/build.go:446 #: internal/build/build.go:447
msgid "Downloading sources" msgid "Downloading sources"
msgstr "Скачивание источников" msgstr "Скачивание источников"
#: internal/build/build.go:538 #: internal/build/build.go:539
msgid "Installing dependencies" msgid "Installing dependencies"
msgstr "Установка зависимостей" msgstr "Установка зависимостей"
@ -235,15 +235,15 @@ msgstr ""
msgid "Building package metadata" msgid "Building package metadata"
msgstr "Сборка метаданных пакета" msgstr "Сборка метаданных пакета"
#: internal/build/script_executor.go:275 #: internal/build/script_executor.go:276
msgid "Executing prepare()" msgid "Executing prepare()"
msgstr "Выполнение prepare()" msgstr "Выполнение prepare()"
#: internal/build/script_executor.go:284 #: internal/build/script_executor.go:285
msgid "Executing build()" msgid "Executing build()"
msgstr "Выполнение build()" msgstr "Выполнение build()"
#: internal/build/script_executor.go:313 internal/build/script_executor.go:333 #: internal/build/script_executor.go:314 internal/build/script_executor.go:334
msgid "Executing %s()" msgid "Executing %s()"
msgstr "Выполнение %s()" msgstr "Выполнение %s()"
@ -255,15 +255,15 @@ msgstr "Ошибка при загрузке"
msgid "Error initialization database" msgid "Error initialization database"
msgstr "Ошибка инициализации базы данных" msgstr "Ошибка инициализации базы данных"
#: internal/cliutils/app_builder/builder.go:135 #: internal/cliutils/app_builder/builder.go:142
msgid "Error pulling repositories" msgid "Error pulling repositories"
msgstr "Ошибка при извлечении репозиториев" msgstr "Ошибка при извлечении репозиториев"
#: internal/cliutils/app_builder/builder.go:152 #: internal/cliutils/app_builder/builder.go:159
msgid "Error parsing os release" msgid "Error parsing os release"
msgstr "Ошибка при разборе файла выпуска операционной системы" msgstr "Ошибка при разборе файла выпуска операционной системы"
#: internal/cliutils/app_builder/builder.go:165 #: internal/cliutils/app_builder/builder.go:172
msgid "Unable to detect a supported package manager on the system" msgid "Unable to detect a supported package manager on the system"
msgstr "Не удалось обнаружить поддерживаемый менеджер пакетов в системе" msgstr "Не удалось обнаружить поддерживаемый менеджер пакетов в системе"
@ -347,7 +347,7 @@ msgstr "КАТЕГОРИЯ"
msgid "OPTIONS" msgid "OPTIONS"
msgstr "ПАРАМЕТРЫ" msgstr "ПАРАМЕТРЫ"
#: internal/cliutils/utils.go:69 #: internal/cliutils/utils.go:72
msgid "" msgid ""
"This command is deprecated and would be removed in the future, use \"%s\" " "This command is deprecated and would be removed in the future, use \"%s\" "
"instead!" "instead!"
@ -355,11 +355,11 @@ msgstr ""
"Эта команда устарела и будет удалена в будущем, используйте вместо нее \"%s" "Эта команда устарела и будет удалена в будущем, используйте вместо нее \"%s"
"\"!" "\"!"
#: internal/db/db.go:95 #: internal/db/db.go:76
msgid "Database version mismatch; resetting" msgid "Database version mismatch; resetting"
msgstr "Несоответствие версий базы данных; сброс настроек" msgstr "Несоответствие версий базы данных; сброс настроек"
#: internal/db/db.go:101 #: internal/db/db.go:82
msgid "" msgid ""
"Database version does not exist. Run alr fix if something isn't working." "Database version does not exist. Run alr fix if something isn't working."
msgstr "" msgstr ""
@ -557,15 +557,15 @@ msgstr "Иcкать по provides"
msgid "Error while executing search" msgid "Error while executing search"
msgstr "Ошибка при выполнении поиска" msgstr "Ошибка при выполнении поиска"
#: upgrade.go:47 #: upgrade.go:48
msgid "Upgrade all installed packages" msgid "Upgrade all installed packages"
msgstr "Обновить все установленные пакеты" msgstr "Обновить все установленные пакеты"
#: upgrade.go:105 upgrade.go:122 #: upgrade.go:106 upgrade.go:123
msgid "Error checking for updates" msgid "Error checking for updates"
msgstr "Ошибка при проверке обновлений" msgstr "Ошибка при проверке обновлений"
#: upgrade.go:125 #: upgrade.go:126
msgid "There is nothing to do." msgid "There is nothing to do."
msgstr "Здесь нечего делать." msgstr "Здесь нечего делать."

View File

@ -32,9 +32,9 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/build" "gitea.plemya-x.ru/Plemya-x/ALR/internal/build"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder" appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager" "gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
) )
func ListCmd() *cli.Command { func ListCmd() *cli.Command {
@ -69,9 +69,9 @@ func ListCmd() *cli.Command {
WithConfig(). WithConfig().
WithDB(). WithDB().
WithManager(). WithManager().
WithDistroInfo().
// autoPull only // autoPull only
WithRepos(). WithRepos().
WithDistroInfo().
Build() Build()
if err != nil { if err != nil {
return err return err
@ -159,7 +159,7 @@ func ListCmd() *cli.Command {
} }
type packageInfo struct { type packageInfo struct {
Package *database.Package Package *alrsh.Package
Version string Version string
} }

View File

@ -38,7 +38,7 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
) )
type ALRSh struct { type ScriptFile struct {
file *syntax.File file *syntax.File
path string path string
} }
@ -72,97 +72,134 @@ func createBuildEnvVars(info *distro.OSRelease, dirs types.Directories) []string
return env return env
} }
func (s *ALRSh) ParseBuildVars(ctx context.Context, info *distro.OSRelease, packages []string) (string, []*types.BuildVars, error) { func (s *ScriptFile) ParseBuildVars(ctx context.Context, info *distro.OSRelease, packages []string) (string, []*Package, error) {
varsOfPackages := []*types.BuildVars{} runner, err := s.createRunner(info)
scriptDir := filepath.Dir(s.path)
env := createBuildEnvVars(info, types.Directories{ScriptDir: scriptDir})
runner, err := interp.New(
interp.Env(expand.ListEnviron(env...)), // Устанавливаем окружение
interp.StdIO(os.Stdin, os.Stderr, os.Stderr), // Устанавливаем стандартный ввод-вывод
interp.ExecHandler(helpers.Restricted.ExecHandler(handlers.NopExec)), // Ограничиваем выполнение
interp.ReadDirHandler2(handlers.RestrictedReadDir(scriptDir)), // Ограничиваем чтение директорий
interp.StatHandler(handlers.RestrictedStat(scriptDir)), // Ограничиваем доступ к статистике файлов
interp.OpenHandler(handlers.RestrictedOpen(scriptDir)), // Ограничиваем открытие файлов
interp.Dir(scriptDir),
)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
err = runner.Run(ctx, s.file) // Запускаем скрипт if err := runScript(ctx, runner, s.file); err != nil {
return "", nil, err
}
dec := newDecoder(info, runner)
pkgNames, err := ParseNames(dec)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
dec := decoder.New(info, runner) // Создаём новый декодер if len(pkgNames.Names) == 0 {
type Packages struct {
BasePkgName string `sh:"basepkg_name"`
Names []string `sh:"name"`
}
var pkgs Packages
err = dec.DecodeVars(&pkgs)
if err != nil {
return "", nil, err
}
if len(pkgs.Names) == 0 {
return "", nil, errors.New("package name is missing") return "", nil, errors.New("package name is missing")
} }
var vars types.BuildVars targetPackages := packages
if len(targetPackages) == 0 {
if len(pkgs.Names) == 1 { targetPackages = pkgNames.Names
err = dec.DecodeVars(&vars)
if err != nil {
return "", nil, err
}
varsOfPackages = append(varsOfPackages, &vars)
return vars.Name, varsOfPackages, nil
} }
var pkgNames []string varsOfPackages, err := s.createPackagesForBuildVars(ctx, dec, pkgNames, targetPackages)
if err != nil {
if len(packages) != 0 { return "", nil, err
pkgNames = packages
} else {
pkgNames = pkgs.Names
} }
for _, pkgName := range pkgNames { baseName := pkgNames.BasePkgName
var preVars types.BuildVarsPre if len(pkgNames.Names) == 1 {
funcName := fmt.Sprintf("meta_%s", pkgName) baseName = pkgNames.Names[0]
meta, ok := dec.GetFuncWithSubshell(funcName)
if !ok {
return "", nil, fmt.Errorf("func %s is missing", funcName)
}
r, err := meta(ctx)
if err != nil {
return "", nil, err
}
d := decoder.New(&distro.OSRelease{}, r)
err = d.DecodeVars(&preVars)
if err != nil {
return "", nil, err
}
vars := preVars.ToBuildVars()
vars.Name = pkgName
vars.Base = pkgs.BasePkgName
varsOfPackages = append(varsOfPackages, &vars)
} }
return pkgs.BasePkgName, varsOfPackages, nil return baseName, varsOfPackages, nil
} }
func (a *ALRSh) Path() string { func (s *ScriptFile) createRunner(info *distro.OSRelease) (*interp.Runner, error) {
scriptDir := filepath.Dir(s.path)
env := createBuildEnvVars(info, types.Directories{ScriptDir: scriptDir})
return interp.New(
interp.Env(expand.ListEnviron(env...)),
interp.StdIO(os.Stdin, os.Stderr, os.Stderr),
interp.ExecHandler(helpers.Restricted.ExecHandler(handlers.NopExec)),
interp.ReadDirHandler2(handlers.RestrictedReadDir(scriptDir)),
interp.StatHandler(handlers.RestrictedStat(scriptDir)),
interp.OpenHandler(handlers.RestrictedOpen(scriptDir)),
interp.Dir(scriptDir),
)
}
func (s *ScriptFile) createPackagesForBuildVars(
ctx context.Context,
dec *decoder.Decoder,
pkgNames *PackageNames,
targetPackages []string,
) ([]*Package, error) {
var varsOfPackages []*Package
if len(pkgNames.Names) == 1 {
var pkg Package
pkg.Name = pkgNames.Names[0]
if err := dec.DecodeVars(&pkg); err != nil {
return nil, err
}
varsOfPackages = append(varsOfPackages, &pkg)
return varsOfPackages, nil
}
for _, pkgName := range targetPackages {
pkg, err := s.createPackageFromMeta(ctx, dec, pkgName, pkgNames.BasePkgName)
if err != nil {
return nil, err
}
varsOfPackages = append(varsOfPackages, pkg)
}
return varsOfPackages, nil
}
func (s *ScriptFile) createPackageFromMeta(
ctx context.Context,
dec *decoder.Decoder,
pkgName, basePkgName string,
) (*Package, error) {
funcName := fmt.Sprintf("meta_%s", pkgName)
meta, ok := dec.GetFuncWithSubshell(funcName)
if !ok {
return nil, fmt.Errorf("func %s is missing", funcName)
}
metaRunner, err := meta(ctx)
if err != nil {
return nil, err
}
metaDecoder := decoder.New(&distro.OSRelease{}, metaRunner)
var vars Package
if err := metaDecoder.DecodeVars(&vars); err != nil {
return nil, err
}
vars.Name = pkgName
vars.BasePkgName = basePkgName
return &vars, nil
}
func runScript(ctx context.Context, runner *interp.Runner, fl *syntax.File) error {
runner.Reset()
return runner.Run(ctx, fl)
}
func newDecoder(info *distro.OSRelease, runner *interp.Runner) *decoder.Decoder {
d := decoder.New(info, runner)
// d.Overrides = false
// d.LikeDistros = false
return d
}
func (a *ScriptFile) Path() string {
return a.path return a.path
} }
func (a *ALRSh) File() *syntax.File { func (a *ScriptFile) File() *syntax.File {
return a.file return a.file
} }

View File

@ -24,7 +24,7 @@ import (
"mvdan.cc/sh/v3/syntax/typedjson" "mvdan.cc/sh/v3/syntax/typedjson"
) )
func (s *ALRSh) GobEncode() ([]byte, error) { func (s *ScriptFile) GobEncode() ([]byte, error) {
var buf bytes.Buffer var buf bytes.Buffer
enc := gob.NewEncoder(&buf) enc := gob.NewEncoder(&buf)
if err := enc.Encode(s.path); err != nil { if err := enc.Encode(s.path); err != nil {
@ -41,7 +41,7 @@ func (s *ALRSh) GobEncode() ([]byte, error) {
return buf.Bytes(), nil return buf.Bytes(), nil
} }
func (s *ALRSh) GobDecode(data []byte) error { func (s *ScriptFile) GobDecode(data []byte) error {
buf := bytes.NewBuffer(data) buf := bytes.NewBuffer(data)
dec := gob.NewDecoder(buf) dec := gob.NewDecoder(buf)
if err := dec.Decode(&s.path); err != nil { if err := dec.Decode(&s.path); err != nil {

146
pkg/alrsh/overridable.go Normal file
View File

@ -0,0 +1,146 @@
// ALR - Any Linux Repository
// Copyright (C) 2025 The ALR Authors
//
// 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 alrsh
import (
"bytes"
"encoding/gob"
"encoding/json"
)
type OverridableField[T any] struct {
data map[string]T
// It can't be a pointer
//
// See https://gitea.com/xorm/xorm/issues/2431
resolved T
}
func (f *OverridableField[T]) Set(key string, value T) {
if f.data == nil {
f.data = make(map[string]T)
}
f.data[key] = value
}
func (f *OverridableField[T]) Get(key string) T {
if f.data == nil {
f.data = make(map[string]T)
}
return f.data[key]
}
func (f *OverridableField[T]) Has(key string) (T, bool) {
if f.data == nil {
f.data = make(map[string]T)
}
val, ok := f.data[key]
return val, ok
}
func (f *OverridableField[T]) SetResolved(value T) {
f.resolved = value
}
func (f *OverridableField[T]) Resolved() T {
return f.resolved
}
func (f *OverridableField[T]) All() map[string]T {
return f.data
}
func (o *OverridableField[T]) Resolve(overrides []string) {
for _, override := range overrides {
if v, ok := o.Has(override); ok {
o.SetResolved(v)
}
}
}
func (f *OverridableField[T]) ToDB() ([]byte, error) {
var data map[string]T
if f.data == nil {
data = make(map[string]T)
} else {
data = f.data
}
return json.Marshal(data)
}
func (f *OverridableField[T]) FromDB(data []byte) error {
if len(data) == 0 {
*f = OverridableField[T]{data: make(map[string]T)}
return nil
}
var temp map[string]T
if err := json.Unmarshal(data, &temp); err != nil {
return err
}
if temp == nil {
temp = make(map[string]T)
}
*f = OverridableField[T]{data: temp}
return nil
}
type overridableFieldGobPayload[T any] struct {
Data map[string]T
Resolved T
}
func (f *OverridableField[T]) GobEncode() ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
payload := overridableFieldGobPayload[T]{
Data: f.data,
Resolved: f.resolved,
}
if err := enc.Encode(payload); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func (f *OverridableField[T]) GobDecode(data []byte) error {
dec := gob.NewDecoder(bytes.NewBuffer(data))
var payload overridableFieldGobPayload[T]
if err := dec.Decode(&payload); err != nil {
return err
}
f.data = payload.Data
f.resolved = payload.Resolved
return nil
}
func OverridableFromMap[T any](data map[string]T) OverridableField[T] {
if data == nil {
data = make(map[string]T)
}
return OverridableField[T]{
data: data,
}
}

105
pkg/alrsh/package.go Normal file
View File

@ -0,0 +1,105 @@
// ALR - Any Linux Repository
// Copyright (C) 2025 The ALR Authors
//
// 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 alrsh
import (
"fmt"
"reflect"
"strings"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder"
)
type PackageNames struct {
BasePkgName string `sh:"basepkg_name"`
Names []string `sh:"name"`
}
func ParseNames(dec *decoder.Decoder) (*PackageNames, error) {
var pkgs PackageNames
err := dec.DecodeVars(&pkgs)
if err != nil {
return nil, fmt.Errorf("fail parse names: %w", err)
}
return &pkgs, nil
}
type Package struct {
Repository string `xorm:"pk 'repository'"`
Name string `xorm:"pk 'name'"`
BasePkgName string `xorm:"notnull 'basepkg_name'"`
Version string `sh:"version" xorm:"notnull 'version'"`
Release int `sh:"release" xorm:"notnull 'release'"`
Epoch uint `sh:"epoch" xorm:"'epoch'"`
Architectures []string `sh:"architectures" xorm:"json 'architectures'"`
Licenses []string `sh:"license" xorm:"json 'licenses'"`
Provides []string `sh:"provides" xorm:"json 'provides'"`
Conflicts []string `sh:"conflicts" xorm:"json 'conflicts'"`
Replaces []string `sh:"replaces" xorm:"json 'replaces'"`
Summary OverridableField[string] `sh:"summary" xorm:"'summary'"`
Description OverridableField[string] `sh:"desc" xorm:"'description'"`
Group OverridableField[string] `sh:"group" xorm:"'group_name'"`
Homepage OverridableField[string] `sh:"homepage" xorm:"'homepage'"`
Maintainer OverridableField[string] `sh:"maintainer" xorm:"'maintainer'"`
Depends OverridableField[[]string] `sh:"deps" xorm:"'depends'"`
BuildDepends OverridableField[[]string] `sh:"build_deps" xorm:"'builddepends'"`
OptDepends OverridableField[[]string] `sh:"opt_deps" xorm:"'optdepends'"`
Sources OverridableField[[]string] `sh:"sources" xorm:"-"`
Checksums OverridableField[[]string] `sh:"checksums" xorm:"-"`
Backup OverridableField[[]string] `sh:"backup" xorm:"-"`
Scripts OverridableField[Scripts] `sh:"scripts" xorm:"-"`
AutoReq OverridableField[[]string] `sh:"auto_req" xorm:"-"`
AutoProv OverridableField[[]string] `sh:"auto_prov" xorm:"-"`
AutoReqSkipList OverridableField[[]string] `sh:"auto_req_skiplist" xorm:"-"`
AutoProvSkipList OverridableField[[]string] `sh:"auto_prov_skiplist" xorm:"-"`
}
type Scripts struct {
PreInstall string `sh:"preinstall"`
PostInstall string `sh:"postinstall"`
PreRemove string `sh:"preremove"`
PostRemove string `sh:"postremove"`
PreUpgrade string `sh:"preupgrade"`
PostUpgrade string `sh:"postupgrade"`
PreTrans string `sh:"pretrans"`
PostTrans string `sh:"posttrans"`
}
func ResolvePackage(p *Package, overrides []string) {
val := reflect.ValueOf(p).Elem()
typ := val.Type()
for i := range val.NumField() {
field := val.Field(i)
fieldType := typ.Field(i)
if !field.CanInterface() {
continue
}
if field.Kind() == reflect.Struct && strings.HasPrefix(fieldType.Type.String(), "alrsh.OverridableField") {
of := field.Addr().Interface()
if res, ok := of.(interface {
Resolve([]string)
}); ok {
res.Resolve(overrides)
}
}
}
}

View File

@ -18,6 +18,7 @@ package alrsh
import ( import (
"fmt" "fmt"
"io"
"io/fs" "io/fs"
"os" "os"
@ -30,23 +31,27 @@ func (fs *localFs) Open(name string) (fs.File, error) {
return os.Open(name) return os.Open(name)
} }
func ReadFromFS(fsys fs.FS, script string) (*ALRSh, error) { func ReadFromIOReader(r io.Reader, script string) (*ScriptFile, error) {
file, err := syntax.NewParser().Parse(r, "alr.sh")
if err != nil {
return nil, err
}
return &ScriptFile{
file: file,
path: script,
}, nil
}
func ReadFromFS(fsys fs.FS, script string) (*ScriptFile, error) {
fl, err := fsys.Open(script) fl, err := fsys.Open(script)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to open alr.sh: %w", err) return nil, fmt.Errorf("failed to open alr.sh: %w", err)
} }
defer fl.Close() defer fl.Close()
file, err := syntax.NewParser().Parse(fl, "alr.sh") return ReadFromIOReader(fl, script)
if err != nil {
return nil, err
}
return &ALRSh{
file: file,
path: script,
}, nil
} }
func ReadFromLocal(script string) (*ALRSh, error) { func ReadFromLocal(script string) (*ScriptFile, error) {
return ReadFromFS(&localFs{}, script) return ReadFromFS(&localFs{}, script)
} }

View File

@ -24,49 +24,6 @@ type BuildOpts struct {
Interactive bool Interactive bool
} }
type BuildVarsPre struct {
Version string `sh:"version,required"`
Release int `sh:"release,required"`
Epoch uint `sh:"epoch"`
Summary string `sh:"summary"`
Description string `sh:"desc"`
Group string `sh:"group"`
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: "",
Base: "",
BuildVarsPre: *bv,
}
}
// BuildVars represents the script variables required
// to build a package
type BuildVars struct {
Name string `sh:"name,required"`
Base string
BuildVarsPre
}
type Scripts struct { type Scripts struct {
PreInstall string `sh:"preinstall"` PreInstall string `sh:"preinstall"`
PostInstall string `sh:"postinstall"` PostInstall string `sh:"postinstall"`

View File

@ -27,10 +27,10 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder" appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
"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/search" "gitea.plemya-x.ru/Plemya-x/ALR/internal/search"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
) )
@ -139,27 +139,16 @@ func SearchCmd() *cli.Command {
} }
} }
for _, dbPkg := range packages { for _, pkg := range packages {
var pkg any alrsh.ResolvePackage(&pkg, names)
if !all {
pkg = overrides.ResolvePackage(&dbPkg, names)
} else {
pkg = &dbPkg
}
if tmpl != nil { if tmpl != nil {
err = tmpl.Execute(os.Stdout, pkg) err = tmpl.Execute(os.Stdout, &pkg)
if err != nil { if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error executing template"), err) return cliutils.FormatCliExit(gotext.Get("Error executing template"), err)
} }
fmt.Println() fmt.Println()
} else { } else {
switch v := pkg.(type) { fmt.Println(pkg.Name)
case *overrides.ResolvedPackage:
fmt.Println(v.Name)
case *db.Package:
fmt.Println(v.Name)
}
} }
} }

View File

@ -37,6 +37,7 @@ import (
"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/search" "gitea.plemya-x.ru/Plemya-x/ALR/internal/search"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
"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/types" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
) )
@ -130,8 +131,8 @@ func UpgradeCmd() *cli.Command {
} }
} }
func mapUptatesInfoToPackages(updates []UpdateInfo) []database.Package { func mapUptatesInfoToPackages(updates []UpdateInfo) []alrsh.Package {
var pkgs []database.Package var pkgs []alrsh.Package
for _, info := range updates { for _, info := range updates {
pkgs = append(pkgs, *info.Package) pkgs = append(pkgs, *info.Package)
} }
@ -139,7 +140,7 @@ func mapUptatesInfoToPackages(updates []UpdateInfo) []database.Package {
} }
type UpdateInfo struct { type UpdateInfo struct {
Package *database.Package Package *alrsh.Package
FromVersion string FromVersion string
ToVersion string ToVersion string