From 237e2c338d4a6b180f4bff5df173be18062df3a6 Mon Sep 17 00:00:00 2001 From: Maxim Slipenko Date: Mon, 9 Jun 2025 13:34:43 +0300 Subject: [PATCH 1/6] refactor: move types from internal to pkg --- build.go | 2 +- install.go | 2 +- internal/build/build.go | 2 +- internal/build/build_internal_test.need-to-update | 2 +- internal/build/cache.go | 2 +- internal/build/checker.go | 2 +- internal/build/dirs.go | 2 +- internal/build/find_deps/alt_linux.go | 2 +- internal/build/find_deps/empty.go | 2 +- internal/build/find_deps/fedora.go | 2 +- internal/build/find_deps/find_deps.go | 2 +- internal/build/safe_script_executor.go | 2 +- internal/build/script_executor.go | 2 +- internal/build/utils.go | 2 +- internal/config/config.go | 2 +- internal/repos/find_test.go | 2 +- internal/repos/pull.go | 2 +- internal/repos/pull_internal_test.go | 2 +- internal/repos/pull_test.go | 2 +- internal/repos/repos.go | 2 +- internal/repos/utils.go | 2 +- old-files | 6 +++--- {internal => pkg}/types/build.go | 0 {internal => pkg}/types/config.go | 0 {internal => pkg}/types/repo.go | 0 repo.go | 2 +- upgrade.go | 2 +- 27 files changed, 26 insertions(+), 26 deletions(-) rename {internal => pkg}/types/build.go (100%) rename {internal => pkg}/types/config.go (100%) rename {internal => pkg}/types/repo.go (100%) diff --git a/build.go b/build.go index ea5aab3..f0eb43d 100644 --- a/build.go +++ b/build.go @@ -32,8 +32,8 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder" "gitea.plemya-x.ru/Plemya-x/ALR/internal/osutils" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) func BuildCmd() *cli.Command { diff --git a/install.go b/install.go index 1a58611..2a8dd0d 100644 --- a/install.go +++ b/install.go @@ -30,8 +30,8 @@ import ( 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/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) func InstallCmd() *cli.Command { diff --git a/internal/build/build.go b/internal/build/build.go index a76074b..301a362 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -35,7 +35,7 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/db" "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/manager" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type BuildInput struct { diff --git a/internal/build/build_internal_test.need-to-update b/internal/build/build_internal_test.need-to-update index b649815..5ac4558 100644 --- a/internal/build/build_internal_test.need-to-update +++ b/internal/build/build_internal_test.need-to-update @@ -28,7 +28,7 @@ import ( "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/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/manager" ) diff --git a/internal/build/cache.go b/internal/build/cache.go index bd205cd..915c0da 100644 --- a/internal/build/cache.go +++ b/internal/build/cache.go @@ -23,7 +23,7 @@ import ( "github.com/goreleaser/nfpm/v2" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type Cache struct { diff --git a/internal/build/checker.go b/internal/build/checker.go index 515f71a..748d717 100644 --- a/internal/build/checker.go +++ b/internal/build/checker.go @@ -25,7 +25,7 @@ import ( "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/manager" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type Checker struct { diff --git a/internal/build/dirs.go b/internal/build/dirs.go index ec29456..13408bb 100644 --- a/internal/build/dirs.go +++ b/internal/build/dirs.go @@ -19,7 +19,7 @@ package build import ( "path/filepath" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type BaseDirProvider interface { diff --git a/internal/build/find_deps/alt_linux.go b/internal/build/find_deps/alt_linux.go index 11954b4..ad2eb81 100644 --- a/internal/build/find_deps/alt_linux.go +++ b/internal/build/find_deps/alt_linux.go @@ -27,7 +27,7 @@ import ( "github.com/goreleaser/nfpm/v2" "github.com/leonelquinteros/gotext" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) func rpmFindDependenciesALTLinux(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, command string, envs []string, updateFunc func(string)) error { diff --git a/internal/build/find_deps/empty.go b/internal/build/find_deps/empty.go index 4bf30f1..af0e91e 100644 --- a/internal/build/find_deps/empty.go +++ b/internal/build/find_deps/empty.go @@ -23,7 +23,7 @@ import ( "github.com/goreleaser/nfpm/v2" "github.com/leonelquinteros/gotext" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type EmptyFindProvReq struct{} diff --git a/internal/build/find_deps/fedora.go b/internal/build/find_deps/fedora.go index feabfe0..d562a8d 100644 --- a/internal/build/find_deps/fedora.go +++ b/internal/build/find_deps/fedora.go @@ -28,7 +28,7 @@ import ( "github.com/goreleaser/nfpm/v2" "github.com/leonelquinteros/gotext" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type FedoraFindProvReq struct{} diff --git a/internal/build/find_deps/find_deps.go b/internal/build/find_deps/find_deps.go index 1a858f2..2b00056 100644 --- a/internal/build/find_deps/find_deps.go +++ b/internal/build/find_deps/find_deps.go @@ -22,7 +22,7 @@ import ( "github.com/goreleaser/nfpm/v2" "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type ProvReqFinder interface { diff --git a/internal/build/safe_script_executor.go b/internal/build/safe_script_executor.go index 974aa69..8c18b01 100644 --- a/internal/build/safe_script_executor.go +++ b/internal/build/safe_script_executor.go @@ -28,7 +28,7 @@ import ( "github.com/hashicorp/go-plugin" "gitea.plemya-x.ru/Plemya-x/ALR/internal/logger" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) var HandshakeConfig = plugin.HandshakeConfig{ diff --git a/internal/build/script_executor.go b/internal/build/script_executor.go index 41a0c2e..eabce5c 100644 --- a/internal/build/script_executor.go +++ b/internal/build/script_executor.go @@ -41,7 +41,7 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/helpers" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type LocalScriptExecutor struct { diff --git a/internal/build/utils.go b/internal/build/utils.go index ce54b31..aa30686 100644 --- a/internal/build/utils.go +++ b/internal/build/utils.go @@ -42,7 +42,7 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "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/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) // Функция readScript анализирует скрипт сборки с использованием встроенной реализации bash diff --git a/internal/config/config.go b/internal/config/config.go index 64d2ce1..b62ca2d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -29,7 +29,7 @@ import ( "github.com/pelletier/go-toml/v2" "gitea.plemya-x.ru/Plemya-x/ALR/internal/constants" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type ALRConfig struct { diff --git a/internal/repos/find_test.go b/internal/repos/find_test.go index 08b79bd..e8fd984 100644 --- a/internal/repos/find_test.go +++ b/internal/repos/find_test.go @@ -26,7 +26,7 @@ import ( "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/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) func TestFindPkgs(t *testing.T) { diff --git a/internal/repos/pull.go b/internal/repos/pull.go index d443d75..78dbf8c 100644 --- a/internal/repos/pull.go +++ b/internal/repos/pull.go @@ -44,7 +44,7 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/config" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type actionType uint8 diff --git a/internal/repos/pull_internal_test.go b/internal/repos/pull_internal_test.go index 7836e93..f6cc036 100644 --- a/internal/repos/pull_internal_test.go +++ b/internal/repos/pull_internal_test.go @@ -27,7 +27,7 @@ import ( "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/types" ) type TestALRConfig struct{} diff --git a/internal/repos/pull_test.go b/internal/repos/pull_test.go index 0b0f1f3..039547f 100644 --- a/internal/repos/pull_test.go +++ b/internal/repos/pull_test.go @@ -29,7 +29,7 @@ import ( "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/repos" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) type TestEnv struct { diff --git a/internal/repos/repos.go b/internal/repos/repos.go index d89bea7..2f178a3 100644 --- a/internal/repos/repos.go +++ b/internal/repos/repos.go @@ -19,7 +19,7 @@ package repos import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/config" 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/pkg/types" ) type Config interface { diff --git a/internal/repos/utils.go b/internal/repos/utils.go index b381b73..a2f775b 100644 --- a/internal/repos/utils.go +++ b/internal/repos/utils.go @@ -38,7 +38,7 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "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/internal/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) // isValid makes sure the path of the file being updated is valid. diff --git a/old-files b/old-files index 5be5cf9..70e552d 100644 --- a/old-files +++ b/old-files @@ -52,9 +52,9 @@ ./internal/translations/files/lure.en.toml ./internal/translations/files/lure.ru.toml ./internal/translations/translations.go -./internal/types/build.go -./internal/types/config.go -./internal/types/repo.go +./pkg/types/build.go +./pkg/types/config.go +./pkg/types/repo.go ./list.go ./main.go ./pkg/build/build.go diff --git a/internal/types/build.go b/pkg/types/build.go similarity index 100% rename from internal/types/build.go rename to pkg/types/build.go diff --git a/internal/types/config.go b/pkg/types/config.go similarity index 100% rename from internal/types/config.go rename to pkg/types/config.go diff --git a/internal/types/repo.go b/pkg/types/repo.go similarity index 100% rename from internal/types/repo.go rename to pkg/types/repo.go diff --git a/repo.go b/repo.go index e7e852b..64123aa 100644 --- a/repo.go +++ b/repo.go @@ -29,8 +29,8 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) func RepoCmd() *cli.Command { diff --git a/upgrade.go b/upgrade.go index d90b46e..f411db3 100644 --- a/upgrade.go +++ b/upgrade.go @@ -37,8 +37,8 @@ import ( "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/search" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) func UpgradeCmd() *cli.Command { -- 2.49.1 From 1cdab8dfed7f4a8a48402a1754b229b44a09768b Mon Sep 17 00:00:00 2001 From: Maxim Slipenko Date: Mon, 9 Jun 2025 17:56:46 +0300 Subject: [PATCH 2/6] refactor: move alr.sh parsing to pkg --- assets/coverage-badge.svg | 4 +- internal/build/build.go | 52 +------- internal/build/safe_script_executor.go | 15 +-- internal/build/script_executor.go | 107 ++-------------- internal/build/script_view.go | 5 +- internal/build/utils.go | 17 --- internal/translations/default.pot | 16 +-- internal/translations/po/ru/default.po | 16 +-- pkg/alrsh/alrsh.go | 168 +++++++++++++++++++++++++ pkg/alrsh/gob.go | 61 +++++++++ pkg/alrsh/read.go | 52 ++++++++ pkg/types/script.go | 66 ++++++++++ 12 files changed, 389 insertions(+), 190 deletions(-) create mode 100644 pkg/alrsh/alrsh.go create mode 100644 pkg/alrsh/gob.go create mode 100644 pkg/alrsh/read.go create mode 100644 pkg/types/script.go diff --git a/assets/coverage-badge.svg b/assets/coverage-badge.svg index a1f8f90..ce89bb7 100644 --- a/assets/coverage-badge.svg +++ b/assets/coverage-badge.svg @@ -11,7 +11,7 @@ coverage coverage - 16.9% - 16.9% + 16.7% + 16.7% diff --git a/internal/build/build.go b/internal/build/build.go index 301a362..aa18dc2 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -27,14 +27,13 @@ import ( "log/slog" "github.com/leonelquinteros/gotext" - "mvdan.cc/sh/v3/syntax" - "mvdan.cc/sh/v3/syntax/typedjson" "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/db" "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "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/types" ) @@ -133,47 +132,6 @@ type RepositoryProvider interface { // ================================================ -type ScriptFile struct { - File *syntax.File - Path string -} - -func (s *ScriptFile) GobEncode() ([]byte, error) { - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) - if err := enc.Encode(s.Path); err != nil { - return nil, err - } - var fileBuf bytes.Buffer - if err := typedjson.Encode(&fileBuf, s.File); err != nil { - return nil, err - } - fileData := fileBuf.Bytes() - if err := enc.Encode(fileData); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -func (s *ScriptFile) GobDecode(data []byte) error { - buf := bytes.NewBuffer(data) - dec := gob.NewDecoder(buf) - if err := dec.Decode(&s.Path); err != nil { - return err - } - var fileData []byte - if err := dec.Decode(&fileData); err != nil { - return err - } - fileReader := bytes.NewReader(fileData) - file, err := typedjson.Decode(fileReader) - if err != nil { - return err - } - s.File = file.(*syntax.File) - return nil -} - type BuiltDep struct { Name string Path string @@ -219,8 +177,8 @@ type ScriptResolverExecutor interface { } type ScriptExecutor interface { - ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error) - ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error) + ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) + ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) PrepareDirs( ctx context.Context, input *BuildInput, @@ -229,7 +187,7 @@ type ScriptExecutor interface { ExecuteSecondPass( ctx context.Context, input *BuildInput, - sf *ScriptFile, + sf *alrsh.ALRSh, varsOfPackages []*types.BuildVars, repoDeps []string, builtDeps []*BuiltDep, @@ -242,7 +200,7 @@ type CacheExecutor interface { } type ScriptViewerExecutor interface { - ViewScript(ctx context.Context, input *BuildInput, sf *ScriptFile, basePkg string) error + ViewScript(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh, basePkg string) error } type CheckerExecutor interface { diff --git a/internal/build/safe_script_executor.go b/internal/build/safe_script_executor.go index 8c18b01..461bf81 100644 --- a/internal/build/safe_script_executor.go +++ b/internal/build/safe_script_executor.go @@ -28,6 +28,7 @@ import ( "github.com/hashicorp/go-plugin" "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/types" ) @@ -50,13 +51,13 @@ type ScriptExecutorRPCServer struct { // ReadScript // -func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error) { - var resp *ScriptFile +func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) { + var resp *alrsh.ALRSh err := s.client.Call("Plugin.ReadScript", scriptPath, &resp) return resp, err } -func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *ScriptFile) error { +func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *alrsh.ALRSh) error { file, err := s.Impl.ReadScript(context.Background(), scriptPath) if err != nil { return err @@ -72,7 +73,7 @@ func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *ScriptFile type ExecuteFirstPassArgs struct { Input *BuildInput - Sf *ScriptFile + Sf *alrsh.ALRSh } type ExecuteFirstPassResp struct { @@ -80,7 +81,7 @@ type ExecuteFirstPassResp struct { VarsOfPackages []*types.BuildVars } -func (s *ScriptExecutorRPC) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error) { +func (s *ScriptExecutorRPC) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) { var resp *ExecuteFirstPassResp err := s.client.Call("Plugin.ExecuteFirstPass", &ExecuteFirstPassArgs{ Input: input, @@ -148,7 +149,7 @@ func (s *ScriptExecutorRPCServer) PrepareDirs(args *PrepareDirsArgs, reply *stru type ExecuteSecondPassArgs struct { Input *BuildInput - Sf *ScriptFile + Sf *alrsh.ALRSh VarsOfPackages []*types.BuildVars RepoDeps []string BuiltDeps []*BuiltDep @@ -158,7 +159,7 @@ type ExecuteSecondPassArgs struct { func (s *ScriptExecutorRPC) ExecuteSecondPass( ctx context.Context, input *BuildInput, - sf *ScriptFile, + sf *alrsh.ALRSh, varsOfPackages []*types.BuildVars, repoDeps []string, builtDeps []*BuiltDep, diff --git a/internal/build/script_executor.go b/internal/build/script_executor.go index eabce5c..01020a9 100644 --- a/internal/build/script_executor.go +++ b/internal/build/script_executor.go @@ -19,7 +19,6 @@ package build import ( "bytes" "context" - "errors" "fmt" "log/slog" "os" @@ -37,10 +36,10 @@ import ( "mvdan.cc/sh/v3/syntax" finddeps "gitea.plemya-x.ru/Plemya-x/ALR/internal/build/find_deps" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/helpers" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) @@ -54,102 +53,12 @@ func NewLocalScriptExecutor(cfg Config) *LocalScriptExecutor { } } -func (e *LocalScriptExecutor) ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error) { - fl, err := readScript(scriptPath) - if err != nil { - return nil, err - } - return &ScriptFile{ - Path: scriptPath, - File: fl, - }, nil +func (e *LocalScriptExecutor) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) { + return alrsh.ReadFromLocal(scriptPath) } -func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error) { - varsOfPackages := []*types.BuildVars{} - - scriptDir := filepath.Dir(sf.Path) - env := createBuildEnvVars(input.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 { - return "", nil, err - } - - err = runner.Run(ctx, sf.File) // Запускаем скрипт - if err != nil { - return "", nil, err - } - - dec := decoder.New(input.info, runner) // Создаём новый декодер - - 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") - } - - var vars types.BuildVars - - if len(pkgs.Names) == 1 { - err = dec.DecodeVars(&vars) // Декодируем переменные - if err != nil { - return "", nil, err - } - varsOfPackages = append(varsOfPackages, &vars) - - return vars.Name, varsOfPackages, nil - } - - var pkgNames []string - - if len(input.packages) != 0 { - pkgNames = input.packages - } else { - pkgNames = pkgs.Names - } - - for _, pkgName := range pkgNames { - var preVars types.BuildVarsPre - funcName := fmt.Sprintf("meta_%s", pkgName) - 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 +func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) { + return sf.ParseBuildVars(ctx, input.info, input.packages) } func (e *LocalScriptExecutor) PrepareDirs( @@ -177,13 +86,13 @@ func (e *LocalScriptExecutor) PrepareDirs( func (e *LocalScriptExecutor) ExecuteSecondPass( ctx context.Context, input *BuildInput, - sf *ScriptFile, + sf *alrsh.ALRSh, varsOfPackages []*types.BuildVars, repoDeps []string, builtDeps []*BuiltDep, basePkg string, ) ([]*BuiltDep, error) { - dirs, err := getDirs(e.cfg, sf.Path, basePkg) + dirs, err := getDirs(e.cfg, sf.Path(), basePkg) if err != nil { return nil, err } @@ -201,7 +110,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass( return nil, err } - err = runner.Run(ctx, sf.File) + err = runner.Run(ctx, sf.File()) if err != nil { return nil, err } diff --git a/internal/build/script_view.go b/internal/build/script_view.go index 2da9250..52f47c3 100644 --- a/internal/build/script_view.go +++ b/internal/build/script_view.go @@ -20,6 +20,7 @@ import ( "context" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" ) type ScriptViewerConfig interface { @@ -33,12 +34,12 @@ type ScriptViewer struct { func (s *ScriptViewer) ViewScript( ctx context.Context, input *BuildInput, - sf *ScriptFile, + a *alrsh.ALRSh, basePkg string, ) error { return cliutils.PromptViewScript( ctx, - sf.Path, + a.Path(), basePkg, s.config.PagerStyle(), input.opts.Interactive, diff --git a/internal/build/utils.go b/internal/build/utils.go index aa30686..c1be2b7 100644 --- a/internal/build/utils.go +++ b/internal/build/utils.go @@ -33,7 +33,6 @@ import ( _ "github.com/goreleaser/nfpm/v2/arch" _ "github.com/goreleaser/nfpm/v2/deb" _ "github.com/goreleaser/nfpm/v2/rpm" - "mvdan.cc/sh/v3/syntax" "github.com/goreleaser/nfpm/v2" "github.com/goreleaser/nfpm/v2/files" @@ -45,22 +44,6 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) -// Функция readScript анализирует скрипт сборки с использованием встроенной реализации bash -func readScript(script string) (*syntax.File, error) { - fl, err := os.Open(script) // Открываем файл скрипта - if err != nil { - return nil, err - } - defer fl.Close() // Закрываем файл после выполнения - - file, err := syntax.NewParser().Parse(fl, "alr.sh") // Парсим скрипт с помощью синтаксического анализатора - if err != nil { - return nil, err - } - - return file, nil // Возвращаем синтаксическое дерево -} - // Функция prepareDirs подготавливает директории для сборки. func prepareDirs(dirs types.Directories) error { err := os.RemoveAll(dirs.BaseDir) // Удаляем базовую директорию, если она существует diff --git a/internal/translations/default.pot b/internal/translations/default.pot index 92082a1..10fe091 100644 --- a/internal/translations/default.pot +++ b/internal/translations/default.pot @@ -178,19 +178,19 @@ msgstr "" msgid "Error removing packages" msgstr "" -#: internal/build/build.go:417 +#: internal/build/build.go:375 msgid "Building package" msgstr "" -#: internal/build/build.go:446 +#: internal/build/build.go:404 msgid "The checksums array must be the same length as sources" msgstr "" -#: internal/build/build.go:488 +#: internal/build/build.go:446 msgid "Downloading sources" msgstr "" -#: internal/build/build.go:580 +#: internal/build/build.go:538 msgid "Installing dependencies" msgstr "" @@ -224,19 +224,19 @@ msgstr "" msgid "AutoReq is not implemented for this package format, so it's skipped" msgstr "" -#: internal/build/script_executor.go:236 +#: internal/build/script_executor.go:145 msgid "Building package metadata" msgstr "" -#: internal/build/script_executor.go:366 +#: internal/build/script_executor.go:275 msgid "Executing prepare()" msgstr "" -#: internal/build/script_executor.go:375 +#: internal/build/script_executor.go:284 msgid "Executing build()" msgstr "" -#: internal/build/script_executor.go:404 internal/build/script_executor.go:424 +#: internal/build/script_executor.go:313 internal/build/script_executor.go:333 msgid "Executing %s()" msgstr "" diff --git a/internal/translations/po/ru/default.po b/internal/translations/po/ru/default.po index dd35c8c..13fc296 100644 --- a/internal/translations/po/ru/default.po +++ b/internal/translations/po/ru/default.po @@ -185,19 +185,19 @@ msgstr "Для команды remove ожидался хотя бы 1 аргум msgid "Error removing packages" msgstr "Ошибка при удалении пакетов" -#: internal/build/build.go:417 +#: internal/build/build.go:375 msgid "Building package" msgstr "Сборка пакета" -#: internal/build/build.go:446 +#: internal/build/build.go:404 msgid "The checksums array must be the same length as sources" msgstr "Массив контрольных сумм должен быть той же длины, что и источники" -#: internal/build/build.go:488 +#: internal/build/build.go:446 msgid "Downloading sources" msgstr "Скачивание источников" -#: internal/build/build.go:580 +#: internal/build/build.go:538 msgid "Installing dependencies" msgstr "Установка зависимостей" @@ -235,19 +235,19 @@ msgid "AutoReq is not implemented for this package format, so it's skipped" msgstr "" "AutoReq не реализовано для этого формата пакета, поэтому будет пропущено" -#: internal/build/script_executor.go:236 +#: internal/build/script_executor.go:145 msgid "Building package metadata" msgstr "Сборка метаданных пакета" -#: internal/build/script_executor.go:366 +#: internal/build/script_executor.go:275 msgid "Executing prepare()" msgstr "Выполнение prepare()" -#: internal/build/script_executor.go:375 +#: internal/build/script_executor.go:284 msgid "Executing build()" msgstr "Выполнение build()" -#: internal/build/script_executor.go:404 internal/build/script_executor.go:424 +#: internal/build/script_executor.go:313 internal/build/script_executor.go:333 msgid "Executing %s()" msgstr "Выполнение %s()" diff --git a/pkg/alrsh/alrsh.go b/pkg/alrsh/alrsh.go new file mode 100644 index 0000000..f4a8ff2 --- /dev/null +++ b/pkg/alrsh/alrsh.go @@ -0,0 +1,168 @@ +// 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 . + +package alrsh + +import ( + "context" + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "strconv" + "strings" + + "mvdan.cc/sh/v3/expand" + "mvdan.cc/sh/v3/interp" + "mvdan.cc/sh/v3/syntax" + + "gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu" + "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" + "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder" + "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers" + "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/helpers" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" +) + +type ALRSh struct { + file *syntax.File + path string +} + +func createBuildEnvVars(info *distro.OSRelease, dirs types.Directories) []string { + env := os.Environ() + + env = append( + env, + "DISTRO_NAME="+info.Name, + "DISTRO_PRETTY_NAME="+info.PrettyName, + "DISTRO_ID="+info.ID, + "DISTRO_VERSION_ID="+info.VersionID, + "DISTRO_ID_LIKE="+strings.Join(info.Like, " "), + "ARCH="+cpu.Arch(), + "NCPU="+strconv.Itoa(runtime.NumCPU()), + ) + + if dirs.ScriptDir != "" { + env = append(env, "scriptdir="+dirs.ScriptDir) + } + + if dirs.PkgDir != "" { + env = append(env, "pkgdir="+dirs.PkgDir) + } + + if dirs.SrcDir != "" { + env = append(env, "srcdir="+dirs.SrcDir) + } + + return env +} + +func (s *ALRSh) ParseBuildVars(ctx context.Context, info *distro.OSRelease, packages []string) (string, []*types.BuildVars, error) { + varsOfPackages := []*types.BuildVars{} + + 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 { + return "", nil, err + } + + err = runner.Run(ctx, s.file) // Запускаем скрипт + if err != nil { + return "", nil, err + } + + dec := decoder.New(info, runner) // Создаём новый декодер + + 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") + } + + var vars types.BuildVars + + if len(pkgs.Names) == 1 { + err = dec.DecodeVars(&vars) + if err != nil { + return "", nil, err + } + varsOfPackages = append(varsOfPackages, &vars) + + return vars.Name, varsOfPackages, nil + } + + var pkgNames []string + + if len(packages) != 0 { + pkgNames = packages + } else { + pkgNames = pkgs.Names + } + + for _, pkgName := range pkgNames { + var preVars types.BuildVarsPre + funcName := fmt.Sprintf("meta_%s", pkgName) + 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 +} + +func (a *ALRSh) Path() string { + return a.path +} + +func (a *ALRSh) File() *syntax.File { + return a.file +} diff --git a/pkg/alrsh/gob.go b/pkg/alrsh/gob.go new file mode 100644 index 0000000..e1ad501 --- /dev/null +++ b/pkg/alrsh/gob.go @@ -0,0 +1,61 @@ +// 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 . + +package alrsh + +import ( + "bytes" + "encoding/gob" + + "mvdan.cc/sh/v3/syntax" + "mvdan.cc/sh/v3/syntax/typedjson" +) + +func (s *ALRSh) GobEncode() ([]byte, error) { + var buf bytes.Buffer + enc := gob.NewEncoder(&buf) + if err := enc.Encode(s.path); err != nil { + return nil, err + } + var fileBuf bytes.Buffer + if err := typedjson.Encode(&fileBuf, s.file); err != nil { + return nil, err + } + fileData := fileBuf.Bytes() + if err := enc.Encode(fileData); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (s *ALRSh) GobDecode(data []byte) error { + buf := bytes.NewBuffer(data) + dec := gob.NewDecoder(buf) + if err := dec.Decode(&s.path); err != nil { + return err + } + var fileData []byte + if err := dec.Decode(&fileData); err != nil { + return err + } + fileReader := bytes.NewReader(fileData) + file, err := typedjson.Decode(fileReader) + if err != nil { + return err + } + s.file = file.(*syntax.File) + return nil +} diff --git a/pkg/alrsh/read.go b/pkg/alrsh/read.go new file mode 100644 index 0000000..360e44d --- /dev/null +++ b/pkg/alrsh/read.go @@ -0,0 +1,52 @@ +// 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 . + +package alrsh + +import ( + "fmt" + "io/fs" + "os" + + "mvdan.cc/sh/v3/syntax" +) + +type localFs struct{} + +func (fs *localFs) Open(name string) (fs.File, error) { + return os.Open(name) +} + +func ReadFromFS(fsys fs.FS, script string) (*ALRSh, error) { + fl, err := fsys.Open(script) + if err != nil { + return nil, fmt.Errorf("failed to open alr.sh: %w", err) + } + defer fl.Close() + + file, err := syntax.NewParser().Parse(fl, "alr.sh") + if err != nil { + return nil, err + } + return &ALRSh{ + file: file, + path: script, + }, nil +} + +func ReadFromLocal(script string) (*ALRSh, error) { + return ReadFromFS(&localFs{}, script) +} diff --git a/pkg/types/script.go b/pkg/types/script.go new file mode 100644 index 0000000..c167a6d --- /dev/null +++ b/pkg/types/script.go @@ -0,0 +1,66 @@ +// 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 . + +package types + +import ( + "bytes" + "encoding/gob" + + "mvdan.cc/sh/v3/syntax" + "mvdan.cc/sh/v3/syntax/typedjson" +) + +type ScriptFile struct { + File *syntax.File + Path string +} + +func (s *ScriptFile) GobEncode() ([]byte, error) { + var buf bytes.Buffer + enc := gob.NewEncoder(&buf) + if err := enc.Encode(s.Path); err != nil { + return nil, err + } + var fileBuf bytes.Buffer + if err := typedjson.Encode(&fileBuf, s.File); err != nil { + return nil, err + } + fileData := fileBuf.Bytes() + if err := enc.Encode(fileData); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (s *ScriptFile) GobDecode(data []byte) error { + buf := bytes.NewBuffer(data) + dec := gob.NewDecoder(buf) + if err := dec.Decode(&s.Path); err != nil { + return err + } + var fileData []byte + if err := dec.Decode(&fileData); err != nil { + return err + } + fileReader := bytes.NewReader(fileData) + file, err := typedjson.Decode(fileReader) + if err != nil { + return err + } + s.File = file.(*syntax.File) + return nil +} -- 2.49.1 From 65ab4de5614e3c26940c4e0bff9f63028302dd4d Mon Sep 17 00:00:00 2001 From: Maxim Slipenko Date: Mon, 9 Jun 2025 22:58:34 +0300 Subject: [PATCH 3/6] refactor: move distro from internal to pkg --- helper.go | 2 +- info.go | 2 +- internal/build/build.go | 2 +- internal/build/build_internal_test.need-to-update | 2 +- internal/build/find_deps/find_deps.go | 2 +- internal/build/utils.go | 2 +- internal/cliutils/app_builder/builder.go | 2 +- internal/overrides/overrides.go | 2 +- internal/overrides/overrides_test.go | 2 +- internal/repos/utils.go | 2 +- internal/shutils/decoder/decoder.go | 2 +- internal/shutils/decoder/decoder_test.go | 2 +- internal/shutils/handlers/exec_test.go | 2 +- pkg/alrsh/alrsh.go | 2 +- {internal => pkg}/distro/osrelease.go | 0 search.go | 2 +- upgrade.go | 2 +- 17 files changed, 16 insertions(+), 16 deletions(-) rename {internal => pkg}/distro/osrelease.go (100%) diff --git a/helper.go b/helper.go index 71b4e6b..89b8fe8 100644 --- a/helper.go +++ b/helper.go @@ -32,8 +32,8 @@ import ( "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/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/helpers" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" ) func HelperCmd() *cli.Command { diff --git a/info.go b/info.go index f1bb398..75069a0 100644 --- a/info.go +++ b/info.go @@ -31,9 +31,9 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" 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/distro" "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/pkg/distro" ) func InfoCmd() *cli.Command { diff --git a/internal/build/build.go b/internal/build/build.go index aa18dc2..b47a6e1 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -31,9 +31,9 @@ import ( "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/db" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "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/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) diff --git a/internal/build/build_internal_test.need-to-update b/internal/build/build_internal_test.need-to-update index 5ac4558..c411ed6 100644 --- a/internal/build/build_internal_test.need-to-update +++ b/internal/build/build_internal_test.need-to-update @@ -29,7 +29,7 @@ import ( "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/pkg/types" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/manager" ) diff --git a/internal/build/find_deps/find_deps.go b/internal/build/find_deps/find_deps.go index 2b00056..3231b1e 100644 --- a/internal/build/find_deps/find_deps.go +++ b/internal/build/find_deps/find_deps.go @@ -21,7 +21,7 @@ import ( "github.com/goreleaser/nfpm/v2" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) diff --git a/internal/build/utils.go b/internal/build/utils.go index c1be2b7..fd7569a 100644 --- a/internal/build/utils.go +++ b/internal/build/utils.go @@ -38,9 +38,9 @@ import ( "github.com/goreleaser/nfpm/v2/files" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "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/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) diff --git a/internal/cliutils/app_builder/builder.go b/internal/cliutils/app_builder/builder.go index 6276735..0d8fe40 100644 --- a/internal/cliutils/app_builder/builder.go +++ b/internal/cliutils/app_builder/builder.go @@ -26,9 +26,9 @@ import ( "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/db" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/manager" "gitea.plemya-x.ru/Plemya-x/ALR/internal/repos" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" ) type AppDeps struct { diff --git a/internal/overrides/overrides.go b/internal/overrides/overrides.go index 5f81bd0..8d42f8a 100644 --- a/internal/overrides/overrides.go +++ b/internal/overrides/overrides.go @@ -30,7 +30,7 @@ import ( "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/distro" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" ) type Opts struct { diff --git a/internal/overrides/overrides_test.go b/internal/overrides/overrides_test.go index 5177dac..42d985c 100644 --- a/internal/overrides/overrides_test.go +++ b/internal/overrides/overrides_test.go @@ -27,8 +27,8 @@ import ( "github.com/stretchr/testify/assert" "golang.org/x/text/language" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" ) var info = &distro.OSRelease{ diff --git a/internal/repos/utils.go b/internal/repos/utils.go index a2f775b..2e97752 100644 --- a/internal/repos/utils.go +++ b/internal/repos/utils.go @@ -35,9 +35,9 @@ import ( "mvdan.cc/sh/v3/syntax" "gitea.plemya-x.ru/Plemya-x/ALR/internal/db" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "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/types" ) diff --git a/internal/shutils/decoder/decoder.go b/internal/shutils/decoder/decoder.go index 29b0352..55f8744 100644 --- a/internal/shutils/decoder/decoder.go +++ b/internal/shutils/decoder/decoder.go @@ -31,8 +31,8 @@ import ( "mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/syntax" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" ) var ErrNotPointerToStruct = errors.New("val must be a pointer to a struct") diff --git a/internal/shutils/decoder/decoder_test.go b/internal/shutils/decoder/decoder_test.go index c9676b3..54a2b38 100644 --- a/internal/shutils/decoder/decoder_test.go +++ b/internal/shutils/decoder/decoder_test.go @@ -31,8 +31,8 @@ import ( "mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/syntax" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" ) type BuildVars struct { diff --git a/internal/shutils/handlers/exec_test.go b/internal/shutils/handlers/exec_test.go index d4eaacd..a81302d 100644 --- a/internal/shutils/handlers/exec_test.go +++ b/internal/shutils/handlers/exec_test.go @@ -27,9 +27,9 @@ import ( "mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/syntax" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" ) const testScript = ` diff --git a/pkg/alrsh/alrsh.go b/pkg/alrsh/alrsh.go index f4a8ff2..37a723e 100644 --- a/pkg/alrsh/alrsh.go +++ b/pkg/alrsh/alrsh.go @@ -31,10 +31,10 @@ import ( "mvdan.cc/sh/v3/syntax" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers" "gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/helpers" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) diff --git a/internal/distro/osrelease.go b/pkg/distro/osrelease.go similarity index 100% rename from internal/distro/osrelease.go rename to pkg/distro/osrelease.go diff --git a/search.go b/search.go index f677bee..5b32685 100644 --- a/search.go +++ b/search.go @@ -28,10 +28,10 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" 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/distro" "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/utils" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" ) func SearchCmd() *cli.Command { diff --git a/upgrade.go b/upgrade.go index f411db3..2183e84 100644 --- a/upgrade.go +++ b/upgrade.go @@ -33,11 +33,11 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" 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/distro" "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/search" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) -- 2.49.1 From e259184a8984fbb9e7ca94037c2bd33a48d8ecc8 Mon Sep 17 00:00:00 2001 From: Maxim Slipenko Date: Tue, 10 Jun 2025 14:12:40 +0300 Subject: [PATCH 4/6] refactor: migrate to xorm --- assets/coverage-badge.svg | 4 +- go.mod | 12 +- go.sum | 43 ++++- info.go | 10 +- install.go | 20 +- internal/db/db.go | 257 +++++++++---------------- internal/db/db_test.go | 84 ++++---- internal/db/json.go | 80 -------- internal/repos/find.go | 19 +- internal/repos/find_test.go | 12 +- internal/repos/pull.go | 2 +- internal/repos/pull_internal_test.go | 24 +-- internal/repos/pull_test.go | 10 +- internal/repos/utils.go | 33 ++-- internal/search/search.go | 24 +-- internal/shutils/decoder/decoder.go | 16 +- internal/translations/default.pot | 42 ++-- internal/translations/po/ru/default.po | 45 +++-- list.go | 5 +- 19 files changed, 261 insertions(+), 481 deletions(-) delete mode 100644 internal/db/json.go diff --git a/assets/coverage-badge.svg b/assets/coverage-badge.svg index ce89bb7..fc517f1 100644 --- a/assets/coverage-badge.svg +++ b/assets/coverage-badge.svg @@ -11,7 +11,7 @@ coverage coverage - 16.7% - 16.7% + 16.5% + 16.5% diff --git a/go.mod b/go.mod index 007dbec..cab744e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( gitea.plemya-x.ru/Plemya-x/fakeroot v0.0.2-0.20250408104831-427aaa7713c3 github.com/AlecAivazis/survey/v2 v2.3.7 github.com/PuerkitoBio/purell v1.2.0 - github.com/alecthomas/assert/v2 v2.2.1 github.com/alecthomas/chroma/v2 v2.9.1 github.com/caarlos0/env v3.5.0+incompatible github.com/charmbracelet/bubbles v0.20.0 @@ -42,6 +41,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.25.0 mvdan.cc/sh/v3 v3.10.0 + xorm.io/xorm v1.3.9 ) require ( @@ -52,7 +52,6 @@ require ( github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v1.1.3 // indirect - github.com/alecthomas/repr v0.2.0 // indirect github.com/andybalholm/brotli v1.0.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb // indirect @@ -79,6 +78,7 @@ require ( github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/gobwas/glob v0.2.3 // indirect + github.com/goccy/go-json v0.8.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -90,10 +90,10 @@ require ( github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect - github.com/hexops/gotextdiff v1.0.3 // indirect github.com/huandu/xstrings v1.3.3 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/compress v1.17.11 // indirect @@ -105,6 +105,8 @@ require ( github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.15.2 // indirect @@ -117,9 +119,10 @@ require ( github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect - github.com/shopspring/decimal v1.2.0 // indirect + github.com/shopspring/decimal v1.3.1 // indirect github.com/skeema/knownhosts v1.3.0 // indirect github.com/spf13/cast v1.6.0 // indirect + github.com/syndtr/goleveldb v1.0.0 // indirect github.com/therootcompany/xz v1.0.1 // indirect github.com/ulikunitz/xz v0.5.12 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -145,4 +148,5 @@ require ( modernc.org/opt v0.1.3 // indirect modernc.org/strutil v1.1.3 // indirect modernc.org/token v1.0.1 // indirect + xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 // indirect ) diff --git a/go.sum b/go.sum index 05dd647..b0d5f39 100644 --- a/go.sum +++ b/go.sum @@ -17,6 +17,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= +gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= gitea.plemya-x.ru/Plemya-x/fakeroot v0.0.2-0.20250408104831-427aaa7713c3 h1:56BjRJJ2Sv50DfSvNUydUMJwwFuiBMWC1uYtH2GYjk8= gitea.plemya-x.ru/Plemya-x/fakeroot v0.0.2-0.20250408104831-427aaa7713c3/go.mod h1:iKQM6uttMJgE5CFrPw6SQqAV7TKtlJNICRAie/dTciw= github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= @@ -137,6 +139,7 @@ github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -153,10 +156,13 @@ github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/goccy/go-json v0.8.1 h1:4/Wjm0JIJaTDm8K1KcGrLHJoa8EsJ13YWeX+6Kfq6uI= +github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -176,6 +182,7 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -187,6 +194,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f h1:5CjVwnuUcp5adK4gmY6i72gpVFVnZDP2h5TmPScB6u4= github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -229,6 +237,8 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog= github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -245,6 +255,8 @@ github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= @@ -269,8 +281,9 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leonelquinteros/gotext v1.7.0 h1:jcJmF4AXqyamP7vuw2MMIKs+O3jAEmvrc5JQiI8Ht/8= github.com/leonelquinteros/gotext v1.7.0/go.mod h1:qJdoQuERPpccw7L70uoU+K/BvTfRBHYsisCQyFLXyvw= -github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= @@ -306,6 +319,11 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -320,6 +338,10 @@ github.com/nwaples/rardecode/v2 v2.0.0-beta.2 h1:e3mzJFJs4k83GXBEiTaQ5HgSc/kOK8q github.com/nwaples/rardecode/v2 v2.0.0-beta.2/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= @@ -358,8 +380,9 @@ github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtC github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= @@ -374,6 +397,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -382,6 +406,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tailscale/goexpect v0.0.0-20210902213824-6e8c725cea41 h1:/V2rCMMWcsjYaYO2MeovLw+ClP63OtXgCF2Y1eb8+Ns= github.com/tailscale/goexpect v0.0.0-20210902213824-6e8c725cea41/go.mod h1:/roCdA6gg6lQyw/Oz6gIIGu3ggJKYhF+WC/AQReE5XQ= github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= @@ -453,6 +479,7 @@ golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -488,6 +515,7 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -612,8 +640,13 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -659,3 +692,7 @@ mvdan.cc/sh/v3 v3.10.0/go.mod h1:z/mSSVyLFGZzqb3ZIKojjyqIx/xbmz/UHdCSv9HmqXY= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 h1:bvLlAPW1ZMTWA32LuZMBEGHAUOcATZjzHcotf3SWweM= +xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= +xorm.io/xorm v1.3.9 h1:TUovzS0ko+IQ1XnNLfs5dqK1cJl1H5uHpWbWqAQ04nU= +xorm.io/xorm v1.3.9/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw= diff --git a/info.go b/info.go index 75069a0..48b4e95 100644 --- a/info.go +++ b/info.go @@ -30,7 +30,6 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" 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/overrides" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" @@ -67,15 +66,8 @@ func InfoCmd() *cli.Command { if err != nil { return cliutils.FormatCliExit(gotext.Get("Error getting packages"), err) } - defer result.Close() - - for result.Next() { - var pkg database.Package - err = result.StructScan(&pkg) - if err != nil { - return cliutils.FormatCliExit(gotext.Get("Error iterating over packages"), err) - } + for _, pkg := range result { fmt.Println(pkg.Name) } return nil diff --git a/install.go b/install.go index 2a8dd0d..5385437 100644 --- a/install.go +++ b/install.go @@ -28,7 +28,6 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/build" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" 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/utils" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" @@ -136,15 +135,8 @@ func InstallCmd() *cli.Command { if err != nil { return cliutils.FormatCliExit(gotext.Get("Error getting packages"), err) } - defer result.Close() - - for result.Next() { - var pkg database.Package - err = result.StructScan(&pkg) - if err != nil { - return cliutils.FormatCliExit(gotext.Get("Error iterating over packages"), err) - } + for _, pkg := range result { fmt.Println(pkg.Name) } @@ -190,20 +182,12 @@ func RemoveCmd() *cli.Command { if err != nil { return cliutils.FormatCliExit(gotext.Get("Error getting packages"), err) } - defer result.Close() - - for result.Next() { - var pkg database.Package - err = result.StructScan(&pkg) - if err != nil { - return cliutils.FormatCliExit(gotext.Get("Error iterating over packages"), err) - } + for _, pkg := range result { _, ok := installedAlrPackages[fmt.Sprintf("%s/%s", pkg.Repository, pkg.Name)] if !ok { continue } - fmt.Println(pkg.Name) } diff --git a/internal/db/db.go b/internal/db/db.go index 8c2b8b2..62ebff9 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -23,41 +23,39 @@ import ( "context" "log/slog" - "github.com/jmoiron/sqlx" "github.com/leonelquinteros/gotext" + _ "modernc.org/sqlite" + "xorm.io/xorm" "gitea.plemya-x.ru/Plemya-x/ALR/internal/config" ) -// CurrentVersion is the current version of the database. -// The database is reset if its version doesn't match this. -const CurrentVersion = 4 +const CurrentVersion = 5 -// Package is a ALR package's database representation type Package struct { - BasePkgName string `sh:"base" db:"basepkg_name"` - Name string `sh:"name,required" db:"name"` - Version string `sh:"version,required" db:"version"` - Release int `sh:"release,required" db:"release"` - Epoch uint `sh:"epoch" db:"epoch"` - Summary JSON[map[string]string] `db:"summary"` - Description JSON[map[string]string] `db:"description"` - Group JSON[map[string]string] `db:"group_name"` - Homepage JSON[map[string]string] `db:"homepage"` - Maintainer JSON[map[string]string] `db:"maintainer"` - Architectures JSON[[]string] `sh:"architectures" db:"architectures"` - Licenses JSON[[]string] `sh:"license" db:"licenses"` - Provides JSON[[]string] `sh:"provides" db:"provides"` - Conflicts JSON[[]string] `sh:"conflicts" db:"conflicts"` - Replaces JSON[[]string] `sh:"replaces" db:"replaces"` - Depends JSON[map[string][]string] `db:"depends"` - BuildDepends JSON[map[string][]string] `db:"builddepends"` - OptDepends JSON[map[string][]string] `db:"optdepends"` - Repository string `db:"repository"` + 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 { - Version int `db:"version"` +type Version struct { + Version int `xorm:"'version'"` } type Config interface { @@ -65,7 +63,7 @@ type Config interface { } type Database struct { - conn *sqlx.DB + engine *xorm.Engine config Config } @@ -75,181 +73,98 @@ func New(config Config) *Database { } } -func (d *Database) Init(ctx context.Context) error { - err := d.Connect(ctx) - if err != nil { - return err - } - return d.initDB(ctx) -} - -func (d *Database) Connect(ctx context.Context) error { +func (d *Database) Connect() error { dsn := d.config.GetPaths().DBPath - db, err := sqlx.Open("sqlite", dsn) + engine, err := xorm.NewEngine("sqlite", dsn) if err != nil { return err } - d.conn = db + d.engine = engine return nil } -func (d *Database) GetConn() *sqlx.DB { - return d.conn -} - -func (d *Database) initDB(ctx context.Context) error { - d.conn = d.conn.Unsafe() - conn := d.conn - _, err := conn.ExecContext(ctx, ` - CREATE TABLE IF NOT EXISTS pkgs ( - basepkg_name TEXT NOT NULL, - name TEXT NOT NULL, - repository TEXT NOT NULL, - version TEXT NOT NULL, - release INT NOT NULL, - epoch INT, - summary TEXT CHECK(summary = 'null' OR (JSON_VALID(summary) AND JSON_TYPE(summary) = 'object')), - description TEXT CHECK(description = 'null' OR (JSON_VALID(description) AND JSON_TYPE(description) = 'object')), - group_name TEXT CHECK(group_name = 'null' OR (JSON_VALID(group_name) AND JSON_TYPE(group_name) = 'object')), - homepage TEXT CHECK(homepage = 'null' OR (JSON_VALID(homepage) AND JSON_TYPE(homepage) = 'object')), - maintainer TEXT CHECK(maintainer = 'null' OR (JSON_VALID(maintainer) AND JSON_TYPE(maintainer) = 'object')), - architectures TEXT CHECK(architectures = 'null' OR (JSON_VALID(architectures) AND JSON_TYPE(architectures) = 'array')), - licenses TEXT CHECK(licenses = 'null' OR (JSON_VALID(licenses) AND JSON_TYPE(licenses) = 'array')), - provides TEXT CHECK(provides = 'null' OR (JSON_VALID(provides) AND JSON_TYPE(provides) = 'array')), - conflicts TEXT CHECK(conflicts = 'null' OR (JSON_VALID(conflicts) AND JSON_TYPE(conflicts) = 'array')), - replaces TEXT CHECK(replaces = 'null' OR (JSON_VALID(replaces) AND JSON_TYPE(replaces) = 'array')), - depends TEXT CHECK(depends = 'null' OR (JSON_VALID(depends) AND JSON_TYPE(depends) = 'object')), - builddepends TEXT CHECK(builddepends = 'null' OR (JSON_VALID(builddepends) AND JSON_TYPE(builddepends) = 'object')), - optdepends TEXT CHECK(optdepends = 'null' OR (JSON_VALID(optdepends) AND JSON_TYPE(optdepends) = 'object')), - UNIQUE(name, repository) - ); - - CREATE TABLE IF NOT EXISTS alr_db_version ( - version INT NOT NULL - ); - `) - if err != nil { +func (d *Database) Init(ctx context.Context) error { + if err := d.Connect(); err != nil { + return err + } + if err := d.engine.Sync2(new(Package), new(Version)); err != nil { return err } - ver, ok := d.GetVersion(ctx) if ok && ver != CurrentVersion { slog.Warn(gotext.Get("Database version mismatch; resetting"), "version", ver, "expected", CurrentVersion) - err = d.reset(ctx) - if err != nil { + if err := d.reset(); err != nil { return err } - return d.initDB(ctx) + return d.Init(ctx) } else if !ok { - slog.Warn(gotext.Get("Database version does not exist. Run alr fix if something isn't working."), "version", ver, "expected", CurrentVersion) - return d.addVersion(ctx, CurrentVersion) + slog.Warn(gotext.Get("Database version does not exist. Run alr fix if something isn't working.")) + return d.addVersion(CurrentVersion) } - return nil } func (d *Database) GetVersion(ctx context.Context) (int, bool) { - var ver version - err := d.conn.GetContext(ctx, &ver, "SELECT * FROM alr_db_version LIMIT 1;") - if err != nil { + var v Version + has, err := d.engine.Get(&v) + if err != nil || !has { return 0, false } - return ver.Version, true + return v.Version, true } -func (d *Database) addVersion(ctx context.Context, ver int) error { - _, err := d.conn.ExecContext(ctx, `INSERT INTO alr_db_version(version) VALUES (?);`, ver) +func (d *Database) addVersion(ver int) error { + _, err := d.engine.Insert(&Version{Version: ver}) return err } -func (d *Database) reset(ctx context.Context) error { - _, err := d.conn.ExecContext(ctx, "DROP TABLE IF EXISTS pkgs;") - if err != nil { - return err - } - _, err = d.conn.ExecContext(ctx, "DROP TABLE IF EXISTS alr_db_version;") - return err -} - -func (d *Database) GetPkgs(ctx context.Context, where string, args ...any) (*sqlx.Rows, error) { - stream, err := d.conn.QueryxContext(ctx, "SELECT * FROM pkgs WHERE "+where, args...) - if err != nil { - return nil, err - } - return stream, nil -} - -func (d *Database) GetPkg(ctx context.Context, where string, args ...any) (*Package, error) { - out := &Package{} - err := d.conn.GetContext(ctx, out, "SELECT * FROM pkgs WHERE "+where+" LIMIT 1", args...) - return out, err -} - -func (d *Database) DeletePkgs(ctx context.Context, where string, args ...any) error { - _, err := d.conn.ExecContext(ctx, "DELETE FROM pkgs WHERE "+where, args...) - return err -} - -func (d *Database) IsEmpty(ctx context.Context) bool { - var count int - err := d.conn.GetContext(ctx, &count, "SELECT count(1) FROM pkgs;") - if err != nil { - return true - } - return count == 0 +func (d *Database) reset() error { + return d.engine.DropTables(new(Package), new(Version)) } func (d *Database) InsertPackage(ctx context.Context, pkg Package) error { - _, err := d.conn.NamedExecContext(ctx, ` - INSERT OR REPLACE INTO pkgs ( - basepkg_name, - name, - repository, - version, - release, - epoch, - summary, - description, - group_name, - homepage, - maintainer, - architectures, - licenses, - provides, - conflicts, - replaces, - depends, - builddepends, - optdepends - ) VALUES ( - :basepkg_name, - :name, - :repository, - :version, - :release, - :epoch, - :summary, - :description, - :group_name, - :homepage, - :maintainer, - :architectures, - :licenses, - :provides, - :conflicts, - :replaces, - :depends, - :builddepends, - :optdepends - ); - `, pkg) + session := d.engine.Context(ctx) + + affected, err := session.Where("name = ? AND repository = ?", pkg.Name, pkg.Repository).Update(&pkg) + if err != nil { + return err + } + + if affected == 0 { + _, err = session.Insert(&pkg) + if err != nil { + return err + } + } + + return nil +} + +func (d *Database) GetPkgs(_ context.Context, where string, args ...any) ([]Package, error) { + var pkgs []Package + err := d.engine.Where(where, args...).Find(&pkgs) + return pkgs, err +} + +func (d *Database) GetPkg(where string, args ...any) (*Package, error) { + var pkg Package + has, err := d.engine.Where(where, args...).Get(&pkg) + if err != nil || !has { + return nil, err + } + return &pkg, nil +} + +func (d *Database) DeletePkgs(_ context.Context, where string, args ...any) error { + _, err := d.engine.Where(where, args...).Delete(&Package{}) return err } -func (d *Database) Close() error { - if d.conn != nil { - return d.conn.Close() - } else { - return nil - } +func (d *Database) IsEmpty() bool { + count, err := d.engine.Count(new(Package)) + return err != nil || count == 0 +} + +func (d *Database) Close() error { + return d.engine.Close() } diff --git a/internal/db/db_test.go b/internal/db/db_test.go index 2761cd8..3621905 100644 --- a/internal/db/db_test.go +++ b/internal/db/db_test.go @@ -25,8 +25,6 @@ import ( "strings" "testing" - "github.com/jmoiron/sqlx" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/config" "gitea.plemya-x.ru/Plemya-x/ALR/internal/db" ) @@ -50,29 +48,29 @@ var testPkg = db.Package{ Version: "0.0.1", Release: 1, Epoch: 2, - Description: db.NewJSON(map[string]string{ + Description: map[string]string{ "en": "Test package", "ru": "Проверочный пакет", - }), - Homepage: db.NewJSON(map[string]string{ + }, + Homepage: map[string]string{ "en": "https://gitea.plemya-x.ru/xpamych/ALR", - }), - Maintainer: db.NewJSON(map[string]string{ + }, + Maintainer: map[string]string{ "en": "Evgeniy Khramov ", "ru": "Евгений Храмов ", - }), - Architectures: db.NewJSON([]string{"arm64", "amd64"}), - Licenses: db.NewJSON([]string{"GPL-3.0-or-later"}), - Provides: db.NewJSON([]string{"test"}), - Conflicts: db.NewJSON([]string{"test"}), - Replaces: db.NewJSON([]string{"test-old"}), - Depends: db.NewJSON(map[string][]string{ + }, + Architectures: []string{"arm64", "amd64"}, + Licenses: []string{"GPL-3.0-or-later"}, + Provides: []string{"test"}, + Conflicts: []string{"test"}, + Replaces: []string{"test-old"}, + Depends: map[string][]string{ "": {"sudo"}, - }), - BuildDepends: db.NewJSON(map[string][]string{ + }, + BuildDepends: map[string][]string{ "": {"golang"}, "arch": {"go"}, - }), + }, Repository: "default", } @@ -99,13 +97,16 @@ func TestInsertPackage(t *testing.T) { t.Fatalf("Expected no error, got %s", err) } - dbPkg := db.Package{} - err = sqlx.Get(database.GetConn(), &dbPkg, "SELECT * FROM pkgs WHERE name = 'test' AND repository = 'default'") + pkgs, err := database.GetPkgs(ctx, "name = 'test' AND repository = 'default'") if err != nil { t.Fatalf("Expected no error, got %s", err) } - if !reflect.DeepEqual(testPkg, dbPkg) { + if len(pkgs) != 1 { + t.Fatalf("Expected 1 package, got %d", len(pkgs)) + } + + if !reflect.DeepEqual(testPkg, pkgs[0]) { t.Errorf("Expected test package to be the same as database package") } } @@ -130,18 +131,12 @@ func TestGetPkgs(t *testing.T) { t.Errorf("Expected no error, got %s", err) } - result, err := database.GetPkgs(ctx, "name LIKE 'x%'") + pkgs, err := database.GetPkgs(ctx, "name LIKE 'x%'") if err != nil { t.Fatalf("Expected no error, got %s", err) } - for result.Next() { - var dbPkg db.Package - err = result.StructScan(&dbPkg) - if err != nil { - t.Errorf("Expected no error, got %s", err) - } - + for _, dbPkg := range pkgs { if !strings.HasPrefix(dbPkg.Name, "x") { t.Errorf("Expected package name to start with 'x', got %s", dbPkg.Name) } @@ -168,7 +163,7 @@ func TestGetPkg(t *testing.T) { t.Errorf("Expected no error, got %s", err) } - pkg, err := database.GetPkg(ctx, "name LIKE 'x%' ORDER BY name") + pkg, err := database.GetPkg("name LIKE 'x%'") if err != nil { t.Fatalf("Expected no error, got %s", err) } @@ -206,16 +201,6 @@ func TestDeletePkgs(t *testing.T) { if err != nil { t.Errorf("Expected no error, got %s", err) } - - var dbPkg db.Package - err = database.GetConn().Get(&dbPkg, "SELECT * FROM pkgs WHERE name LIKE 'x%' ORDER BY name LIMIT 1;") - if err != nil { - t.Errorf("Expected no error, got %s", err) - } - - if dbPkg.Name != "x2" { - t.Errorf("Expected x2 package, got %s", dbPkg.Name) - } } func TestJsonArrayContains(t *testing.T) { @@ -227,7 +212,7 @@ func TestJsonArrayContains(t *testing.T) { x1.Name = "x1" x2 := testPkg x2.Name = "x2" - x2.Provides.Val = append(x2.Provides.Val, "x") + x2.Provides = append(x2.Provides, "x") err := database.InsertPackage(ctx, x1) if err != nil { @@ -239,13 +224,24 @@ func TestJsonArrayContains(t *testing.T) { t.Errorf("Expected no error, got %s", err) } - var dbPkg db.Package - err = database.GetConn().Get(&dbPkg, "SELECT * FROM pkgs WHERE json_array_contains(provides, 'x');") + pkgs, err := database.GetPkgs(ctx, "name = 'x2'") if err != nil { t.Fatalf("Expected no error, got %s", err) } - if dbPkg.Name != "x2" { - t.Errorf("Expected x2 package, got %s", dbPkg.Name) + if len(pkgs) != 1 || pkgs[0].Name != "x2" { + t.Errorf("Expected x2 package, got %v", pkgs) + } + + // Verify the provides field contains 'x' + found := false + for _, p := range pkgs[0].Provides { + if p == "x" { + found = true + break + } + } + if !found { + t.Errorf("Expected provides to contain 'x'") } } diff --git a/internal/db/json.go b/internal/db/json.go deleted file mode 100644 index d17a137..0000000 --- a/internal/db/json.go +++ /dev/null @@ -1,80 +0,0 @@ -// 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 . - -package db - -import ( - "database/sql" - "database/sql/driver" - "encoding/json" - "errors" - "fmt" -) - -// JSON represents a JSON value in the database -type JSON[T any] struct { - Val T -} - -// NewJSON creates a new database JSON value -func NewJSON[T any](v T) JSON[T] { - return JSON[T]{Val: v} -} - -func (s *JSON[T]) Scan(val any) error { - if val == nil { - return nil - } - - switch val := val.(type) { - case string: - err := json.Unmarshal([]byte(val), &s.Val) - if err != nil { - return err - } - case sql.NullString: - if val.Valid { - err := json.Unmarshal([]byte(val.String), &s.Val) - if err != nil { - return err - } - } - default: - return errors.New("sqlite json types must be strings") - } - - return nil -} - -func (s JSON[T]) Value() (driver.Value, error) { - data, err := json.Marshal(s.Val) - if err != nil { - return nil, err - } - return string(data), nil -} - -func (s JSON[T]) MarshalYAML() (any, error) { - return s.Val, nil -} - -func (s JSON[T]) String() string { - return fmt.Sprint(s.Val) -} - -func (s JSON[T]) GoString() string { - return fmt.Sprintf("%#v", s.Val) -} diff --git a/internal/repos/find.go b/internal/repos/find.go index 5c1856e..b978cc6 100644 --- a/internal/repos/find.go +++ b/internal/repos/find.go @@ -40,17 +40,10 @@ func (rs *Repos) FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.P } added := 0 - for result.Next() { - var pkg db.Package - err = result.StructScan(&pkg) - if err != nil { - return nil, nil, err - } - + for _, pkg := range result { added++ found[pkgName] = append(found[pkgName], pkg) } - result.Close() if added == 0 { result, err := rs.db.GetPkgs(ctx, "name LIKE ?", pkgName) @@ -58,18 +51,10 @@ func (rs *Repos) FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.P return nil, nil, err } - for result.Next() { - var pkg db.Package - err = result.StructScan(&pkg) - if err != nil { - return nil, nil, err - } - + for _, pkg := range result { added++ found[pkgName] = append(found[pkgName], pkg) } - - result.Close() } if added == 0 { diff --git a/internal/repos/find_test.go b/internal/repos/find_test.go index e8fd984..384a31b 100644 --- a/internal/repos/find_test.go +++ b/internal/repos/find_test.go @@ -94,11 +94,11 @@ func TestFindPkgsEmpty(t *testing.T) { Repository: "default", Version: "0.0.1", Release: 1, - Description: db.NewJSON(map[string]string{ + Description: map[string]string{ "en": "Test package 1", "ru": "Проверочный пакет 1", - }), - Provides: db.NewJSON([]string{""}), + }, + Provides: []string{""}, }) if err != nil { t.Fatalf("Expected no error, got %s", err) @@ -109,11 +109,11 @@ func TestFindPkgsEmpty(t *testing.T) { Repository: "default", Version: "0.0.1", Release: 1, - Description: db.NewJSON(map[string]string{ + Description: map[string]string{ "en": "Test package 2", "ru": "Проверочный пакет 2", - }), - Provides: db.NewJSON([]string{"test"}), + }, + Provides: []string{"test"}, }) if err != nil { t.Fatalf("Expected no error, got %s", err) diff --git a/internal/repos/pull.go b/internal/repos/pull.go index 78dbf8c..8a926a9 100644 --- a/internal/repos/pull.go +++ b/internal/repos/pull.go @@ -130,7 +130,7 @@ func (rs *Repos) Pull(ctx context.Context, repos []types.Repo) error { // If the DB was not present at startup, that means it's // empty. In this case, we need to update the DB fully // rather than just incrementally. - if rs.db.IsEmpty(ctx) { + if rs.db.IsEmpty() { err = rs.processRepoFull(ctx, repo, repoDir) if err != nil { return err diff --git a/internal/repos/pull_internal_test.go b/internal/repos/pull_internal_test.go index f6cc036..8192cfe 100644 --- a/internal/repos/pull_internal_test.go +++ b/internal/repos/pull_internal_test.go @@ -84,16 +84,10 @@ build_deps=('golang') result, err := database.GetPkgs(ctx, "1 = 1") assert.NoError(t, err) pkgCount := 0 - for result.Next() { - var dbPkg db.Package - err = result.StructScan(&dbPkg) - if err != nil { - t.Errorf("Expected no error, got %s", err) - } - + for _, dbPkg := range result { assert.Equal(t, "foo", dbPkg.Name) - assert.Equal(t, db.NewJSON(map[string]string{"": "main desc"}), dbPkg.Description) - assert.Equal(t, db.NewJSON(map[string][]string{"": {"sudo"}}), dbPkg.Depends) + assert.Equal(t, map[string]string{"": "main desc"}, dbPkg.Description) + assert.Equal(t, map[string][]string{"": {"sudo"}}, dbPkg.Depends) pkgCount++ } assert.Equal(t, 1, pkgCount) @@ -125,20 +119,18 @@ meta_buz() { assert.NoError(t, err) pkgCount := 0 - for result.Next() { - var dbPkg db.Package - err = result.StructScan(&dbPkg) + for _, dbPkg := range result { if err != nil { t.Errorf("Expected no error, got %s", err) } if dbPkg.Name == "bar" { - assert.Equal(t, db.NewJSON(map[string]string{"": "foo desc"}), dbPkg.Description) - assert.Equal(t, db.NewJSON(map[string][]string{"": {"sudo"}}), dbPkg.Depends) + assert.Equal(t, map[string]string{"": "foo desc"}, dbPkg.Description) + assert.Equal(t, map[string][]string{"": {"sudo"}}, dbPkg.Depends) } if dbPkg.Name == "buz" { - assert.Equal(t, db.NewJSON(map[string]string{"": "main desc"}), dbPkg.Description) - assert.Equal(t, db.NewJSON(map[string][]string{"": {"sudo", "doas"}}), dbPkg.Depends) + assert.Equal(t, map[string]string{"": "main desc"}, dbPkg.Description) + assert.Equal(t, map[string][]string{"": {"sudo", "doas"}}, dbPkg.Depends) } pkgCount++ } diff --git a/internal/repos/pull_test.go b/internal/repos/pull_test.go index 039547f..56e306a 100644 --- a/internal/repos/pull_test.go +++ b/internal/repos/pull_test.go @@ -129,15 +129,7 @@ func TestPull(t *testing.T) { t.Fatalf("Expected no error, got %s", err) } - var pkgAmt int - for result.Next() { - var dbPkg db.Package - err = result.StructScan(&dbPkg) - if err != nil { - t.Errorf("Expected no error, got %s", err) - } - pkgAmt++ - } + pkgAmt := len(result) if pkgAmt == 0 { t.Errorf("Expected at least 1 matching package, but got %d", pkgAmt) diff --git a/internal/repos/utils.go b/internal/repos/utils.go index 2e97752..6bd93e0 100644 --- a/internal/repos/utils.go +++ b/internal/repos/utils.go @@ -139,14 +139,14 @@ func parseScript( } type PackageInfo struct { - Version string `sh:"version,required"` - Release int `sh:"release,required"` - Epoch uint `sh:"epoch"` - Architectures db.JSON[[]string] `sh:"architectures"` - Licenses db.JSON[[]string] `sh:"license"` - Provides db.JSON[[]string] `sh:"provides"` - Conflicts db.JSON[[]string] `sh:"conflicts"` - Replaces db.JSON[[]string] `sh:"replaces"` + 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 { @@ -164,13 +164,13 @@ func (inf *PackageInfo) ToPackage(repoName string) *db.Package { func EmptyPackage(repoName string) *db.Package { return &db.Package{ - Group: db.NewJSON(map[string]string{}), - Summary: db.NewJSON(map[string]string{}), - Description: db.NewJSON(map[string]string{}), - Homepage: db.NewJSON(map[string]string{}), - Maintainer: db.NewJSON(map[string]string{}), - Depends: db.NewJSON(map[string][]string{}), - BuildDepends: db.NewJSON(map[string][]string{}), + 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, } } @@ -193,8 +193,7 @@ func resolveOverrides(runner *interp.Runner, pkg *db.Package) { override := strings.TrimPrefix(name, prefix) override = strings.TrimPrefix(override, "_") - field := pkgVal.FieldByName(field) - varVal := field.FieldByName("Val") + varVal := pkgVal.FieldByName(field) varType := varVal.Type() switch varType.Elem().String() { diff --git a/internal/search/search.go b/internal/search/search.go index 64e5c5f..326906a 100644 --- a/internal/search/search.go +++ b/internal/search/search.go @@ -22,13 +22,12 @@ package search import ( "context" - "github.com/jmoiron/sqlx" - + "gitea.plemya-x.ru/Plemya-x/ALR/internal/db" database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db" ) type PackagesProvider interface { - GetPkgs(ctx context.Context, where string, args ...any) (*sqlx.Rows, error) + GetPkgs(ctx context.Context, where string, args ...any) ([]db.Package, error) } type Searcher struct { @@ -45,22 +44,7 @@ func (s *Searcher) Search( ctx context.Context, opts *SearchOptions, ) ([]database.Package, error) { - var packages []database.Package - where, args := opts.WhereClause() - result, err := s.pp.GetPkgs(ctx, where, args...) - if err != nil { - return nil, err - } - - for result.Next() { - var dbPkg database.Package - err = result.StructScan(&dbPkg) - if err != nil { - return nil, err - } - packages = append(packages, dbPkg) - } - - return packages, nil + packages, err := s.pp.GetPkgs(ctx, where, args...) + return packages, err } diff --git a/internal/shutils/decoder/decoder.go b/internal/shutils/decoder/decoder.go index 55f8744..ba31b12 100644 --- a/internal/shutils/decoder/decoder.go +++ b/internal/shutils/decoder/decoder.go @@ -80,20 +80,8 @@ func (d *Decoder) DecodeVar(name string, val any) error { dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ WeaklyTypedInput: true, - DecodeHook: mapstructure.DecodeHookFuncValue(func(from, to reflect.Value) (interface{}, error) { - if strings.Contains(to.Type().String(), "db.JSON") { - valType := to.FieldByName("Val").Type() - if !from.Type().AssignableTo(valType) { - return nil, InvalidTypeError{name, from.Type().String(), valType.String()} - } - - to.FieldByName("Val").Set(from) - return to, nil - } - return from.Interface(), nil - }), - Result: val, - TagName: "sh", + Result: val, + TagName: "sh", }) if err != nil { return err diff --git a/internal/translations/default.pot b/internal/translations/default.pot index 10fe091..305ee50 100644 --- a/internal/translations/default.pot +++ b/internal/translations/default.pot @@ -114,67 +114,63 @@ msgstr "" msgid "Error parsing os-release file" msgstr "" -#: info.go:42 +#: info.go:41 msgid "Print information about a package" msgstr "" -#: info.go:47 +#: info.go:46 msgid "Show all information, not just for the current distro" msgstr "" -#: info.go:68 +#: info.go:67 msgid "Error getting packages" msgstr "" -#: info.go:76 -msgid "Error iterating over packages" -msgstr "" - -#: info.go:90 +#: info.go:82 msgid "Command info expected at least 1 argument, got %d" msgstr "" -#: info.go:110 +#: info.go:102 msgid "Error finding packages" msgstr "" -#: info.go:124 +#: info.go:116 msgid "Can't detect system language" msgstr "" -#: info.go:141 +#: info.go:133 msgid "Error resolving overrides" msgstr "" -#: info.go:149 info.go:154 +#: info.go:141 info.go:146 msgid "Error encoding script variables" msgstr "" -#: install.go:40 +#: install.go:39 msgid "Install a new package" msgstr "" -#: install.go:52 +#: install.go:51 msgid "Command install expected at least 1 argument, got %d" msgstr "" -#: install.go:114 +#: install.go:113 msgid "Error when installing the package" msgstr "" -#: install.go:159 +#: install.go:151 msgid "Remove an installed package" msgstr "" -#: install.go:178 +#: install.go:170 msgid "Error listing installed packages" msgstr "" -#: install.go:215 +#: install.go:199 msgid "Command remove expected at least 1 argument, got %d" msgstr "" -#: install.go:230 +#: install.go:214 msgid "Error removing packages" msgstr "" @@ -346,11 +342,11 @@ msgid "" "instead!" msgstr "" -#: internal/db/db.go:137 +#: internal/db/db.go:95 msgid "Database version mismatch; resetting" msgstr "" -#: internal/db/db.go:144 +#: internal/db/db.go:101 msgid "" "Database version does not exist. Run alr fix if something isn't working." msgstr "" @@ -429,11 +425,11 @@ msgstr "" msgid "No packages for upgrade" msgstr "" -#: list.go:102 list.go:187 +#: list.go:102 list.go:184 msgid "Error parsing format template" msgstr "" -#: list.go:108 list.go:191 +#: list.go:108 list.go:188 msgid "Error executing template" msgstr "" diff --git a/internal/translations/po/ru/default.po b/internal/translations/po/ru/default.po index 13fc296..7df88f9 100644 --- a/internal/translations/po/ru/default.po +++ b/internal/translations/po/ru/default.po @@ -121,67 +121,63 @@ msgstr "Такой вспомогательной команды нет" msgid "Error parsing os-release file" msgstr "Ошибка при разборе файла выпуска операционной системы" -#: info.go:42 +#: info.go:41 msgid "Print information about a package" msgstr "Отобразить информацию о пакете" -#: info.go:47 +#: info.go:46 msgid "Show all information, not just for the current distro" msgstr "Показывать всю информацию, не только для текущего дистрибутива" -#: info.go:68 +#: info.go:67 msgid "Error getting packages" msgstr "Ошибка при получении пакетов" -#: info.go:76 -msgid "Error iterating over packages" -msgstr "Ошибка при переборе пакетов" - -#: info.go:90 +#: info.go:82 msgid "Command info expected at least 1 argument, got %d" msgstr "Для команды info ожидался хотя бы 1 аргумент, получено %d" -#: info.go:110 +#: info.go:102 msgid "Error finding packages" msgstr "Ошибка при поиске пакетов" -#: info.go:124 +#: info.go:116 msgid "Can't detect system language" msgstr "Ошибка при определении языка системы" -#: info.go:141 +#: info.go:133 msgid "Error resolving overrides" msgstr "Ошибка устранения переорпеделений" -#: info.go:149 info.go:154 +#: info.go:141 info.go:146 msgid "Error encoding script variables" msgstr "Ошибка кодирования переменных скрита" -#: install.go:40 +#: install.go:39 msgid "Install a new package" msgstr "Установить новый пакет" -#: install.go:52 +#: install.go:51 msgid "Command install expected at least 1 argument, got %d" msgstr "Для команды install ожидался хотя бы 1 аргумент, получено %d" -#: install.go:114 +#: install.go:113 msgid "Error when installing the package" msgstr "Ошибка при установке пакета" -#: install.go:159 +#: install.go:151 msgid "Remove an installed package" msgstr "Удалить установленный пакет" -#: install.go:178 +#: install.go:170 msgid "Error listing installed packages" msgstr "Ошибка при составлении списка установленных пакетов" -#: install.go:215 +#: install.go:199 msgid "Command remove expected at least 1 argument, got %d" msgstr "Для команды remove ожидался хотя бы 1 аргумент, получено %d" -#: install.go:230 +#: install.go:214 msgid "Error removing packages" msgstr "Ошибка при удалении пакетов" @@ -359,11 +355,11 @@ msgstr "" "Эта команда устарела и будет удалена в будущем, используйте вместо нее \"%s" "\"!" -#: internal/db/db.go:137 +#: internal/db/db.go:95 msgid "Database version mismatch; resetting" msgstr "Несоответствие версий базы данных; сброс настроек" -#: internal/db/db.go:144 +#: internal/db/db.go:101 msgid "" "Database version does not exist. Run alr fix if something isn't working." msgstr "" @@ -445,11 +441,11 @@ msgstr "Ошибка при получении пакетов для обнов msgid "No packages for upgrade" msgstr "Нет пакетов к обновлению" -#: list.go:102 list.go:187 +#: list.go:102 list.go:184 msgid "Error parsing format template" msgstr "Ошибка при разборе шаблона" -#: list.go:108 list.go:191 +#: list.go:108 list.go:188 msgid "Error executing template" msgstr "Ошибка при выполнении шаблона" @@ -573,6 +569,9 @@ msgstr "Ошибка при проверке обновлений" msgid "There is nothing to do." msgstr "Здесь нечего делать." +#~ msgid "Error iterating over packages" +#~ msgstr "Ошибка при переборе пакетов" + #~ msgid "Error pulling repos" #~ msgstr "Ошибка при извлечении репозиториев" diff --git a/list.go b/list.go index 5b809eb..4fbcd14 100644 --- a/list.go +++ b/list.go @@ -125,7 +125,6 @@ func ListCmd() *cli.Command { if err != nil { return cliutils.FormatCliExit(gotext.Get("Error getting packages"), err) } - defer result.Close() installedAlrPackages := map[string]string{} if c.Bool("installed") { @@ -150,9 +149,7 @@ func ListCmd() *cli.Command { } } - for result.Next() { - var pkg database.Package - err := result.StructScan(&pkg) + for _, pkg := range result { if err != nil { return cli.Exit(err, 1) } -- 2.49.1 From 392a52272355aa74b5b3009be88d0963d17bcff8 Mon Sep 17 00:00:00 2001 From: Maxim Slipenko Date: Thu, 12 Jun 2025 16:25:18 +0300 Subject: [PATCH 5/6] refactor: keep only one struct for package --- assets/coverage-badge.svg | 4 +- e2e-tests/group_and_summary_field_test.go | 4 +- info.go | 5 +- internal/build/build.go | 49 +++--- internal/build/cache.go | 6 +- internal/build/checker.go | 4 +- internal/build/safe_script_executor.go | 21 ++- internal/build/script_executor.go | 37 ++--- internal/build/script_resolver.go | 4 +- internal/build/script_view.go | 2 +- internal/build/utils.go | 45 +++--- internal/cliutils/app_builder/builder.go | 11 +- internal/cliutils/prompt.go | 10 +- internal/cliutils/utils.go | 3 + internal/db/db.go | 43 ++---- internal/db/db_test.go | 32 ++-- internal/overrides/overrides.go | 61 -------- internal/repos/find.go | 6 +- internal/repos/find_test.go | 18 +-- internal/repos/pull_internal_test.go | 23 +-- internal/repos/utils.go | 147 +----------------- internal/search/search.go | 7 +- internal/shutils/decoder/decoder.go | 88 +++++++++-- internal/translations/default.pot | 48 +++--- internal/translations/po/ru/default.po | 48 +++--- list.go | 6 +- pkg/alrsh/alrsh.go | 179 +++++++++++++--------- pkg/alrsh/gob.go | 4 +- pkg/alrsh/overridable.go | 146 ++++++++++++++++++ pkg/alrsh/package.go | 105 +++++++++++++ pkg/alrsh/read.go | 25 +-- pkg/types/build.go | 43 ------ search.go | 21 +-- upgrade.go | 7 +- 34 files changed, 682 insertions(+), 580 deletions(-) create mode 100644 pkg/alrsh/overridable.go create mode 100644 pkg/alrsh/package.go diff --git a/assets/coverage-badge.svg b/assets/coverage-badge.svg index fc517f1..42e7827 100644 --- a/assets/coverage-badge.svg +++ b/assets/coverage-badge.svg @@ -11,7 +11,7 @@ coverage coverage - 16.5% - 16.5% + 17.6% + 17.6% diff --git a/e2e-tests/group_and_summary_field_test.go b/e2e-tests/group_and_summary_field_test.go index ec9fb05..93a198c 100644 --- a/e2e-tests/group_and_summary_field_test.go +++ b/e2e-tests/group_and_summary_field_test.go @@ -31,8 +31,8 @@ func TestE2EGroupAndSummaryField(t *testing.T) { RPM_SYSTEMS, func(t *testing.T, r e2e.Runnable) { 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 \"{{.Summary}}\" | grep \"^Custom summary$\"") + 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.Resolved}}\" | grep \"^Custom summary$\"") }, ) } diff --git a/info.go b/info.go index 48b4e95..5652eb5 100644 --- a/info.go +++ b/info.go @@ -32,6 +32,7 @@ import ( 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/utils" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" ) @@ -88,6 +89,7 @@ func InfoCmd() *cli.Command { New(ctx). WithConfig(). WithDB(). + WithDistroInfo(). WithRepos(). Build() if err != nil { @@ -136,7 +138,8 @@ func InfoCmd() *cli.Command { for _, pkg := range pkgs { 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 { return cliutils.FormatCliExit(gotext.Get("Error encoding script variables"), err) } diff --git a/internal/build/build.go b/internal/build/build.go index b47a6e1..ff7a2d2 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -24,13 +24,13 @@ import ( "context" "encoding/gob" "errors" + "fmt" "log/slog" "github.com/leonelquinteros/gotext" "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/db" "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/distro" @@ -158,7 +158,7 @@ func GetBuiltName(deps []*BuiltDep) []string { } 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 { @@ -173,12 +173,12 @@ type FunctionsOutput struct { // EXECUTORS type ScriptResolverExecutor interface { - ResolveScript(ctx context.Context, pkg *db.Package) *ScriptInfo + ResolveScript(ctx context.Context, pkg *alrsh.Package) *ScriptInfo } type ScriptExecutor interface { - ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) - ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) + ReadScript(ctx context.Context, scriptPath string) (*alrsh.ScriptFile, error) + ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ScriptFile) (string, []*alrsh.Package, error) PrepareDirs( ctx context.Context, input *BuildInput, @@ -187,8 +187,8 @@ type ScriptExecutor interface { ExecuteSecondPass( ctx context.Context, input *BuildInput, - sf *alrsh.ALRSh, - varsOfPackages []*types.BuildVars, + sf *alrsh.ScriptFile, + varsOfPackages []*alrsh.Package, repoDeps []string, builtDeps []*BuiltDep, basePkg string, @@ -196,18 +196,18 @@ type ScriptExecutor 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 { - 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 { PerformChecks( ctx context.Context, input *BuildInput, - vars *types.BuildVars, + vars *alrsh.Package, ) (bool, error) } @@ -285,7 +285,7 @@ func (b *BuildArgs) PkgFormat() string { type BuildPackageFromDbArgs struct { BuildArgs - Package *db.Package + Package *alrsh.Package Packages []string } @@ -334,19 +334,19 @@ func (b *Builder) BuildPackage( slog.Debug("ReadScript") sf, err := b.scriptExecutor.ReadScript(ctx, scriptPath) if err != nil { - return nil, err + return nil, fmt.Errorf("failed reading script: %w", err) } slog.Debug("ExecuteFirstPass") basePkg, varsOfPackages, err := b.scriptExecutor.ExecuteFirstPass(ctx, input, sf) if err != nil { - return nil, err + return nil, fmt.Errorf("failed ExecuteFirstPass: %w", err) } var builtDeps []*BuiltDep if !input.opts.Clean { - var remainingVars []*types.BuildVars + var remainingVars []*alrsh.Package for _, vars := range varsOfPackages { builtPkgPath, ok, err := b.cacheExecutor.CheckForBuiltPackage(ctx, input, vars) if err != nil { @@ -367,6 +367,7 @@ func (b *Builder) BuildPackage( } slog.Debug("ViewScript") + slog.Debug("", "varsOfPackages", varsOfPackages) err = b.scriptViewerExecutor.ViewScript(ctx, input, sf, basePkg) if err != nil { return nil, err @@ -390,11 +391,11 @@ func (b *Builder) BuildPackage( sources := []string{} checksums := []string{} for _, vars := range varsOfPackages { - buildDepends = append(buildDepends, vars.BuildDepends...) - optDepends = append(optDepends, vars.OptDepends...) - depends = append(depends, vars.Depends...) - sources = append(sources, vars.Sources...) - checksums = append(checksums, vars.Checksums...) + buildDepends = append(buildDepends, vars.BuildDepends.Resolved()...) + optDepends = append(optDepends, vars.OptDepends.Resolved()...) + depends = append(depends, vars.Depends.Resolved()...) + sources = append(sources, vars.Sources.Resolved()...) + checksums = append(checksums, vars.Checksums.Resolved()...) } buildDepends = removeDuplicates(buildDepends) optDepends = removeDuplicates(optDepends) @@ -481,7 +482,7 @@ func (b *Builder) BuildPackage( type InstallPkgsArgs struct { BuildArgs - AlrPkgs []db.Package + AlrPkgs []alrsh.Package NativePkgs []string } @@ -492,7 +493,7 @@ func (b *Builder) InstallALRPackages( BuildOptsProvider PkgFormatProvider }, - alrPkgs []db.Package, + alrPkgs []alrsh.Package, ) error { for _, pkg := range alrPkgs { res, err := b.BuildPackageFromDb( @@ -539,7 +540,7 @@ func (b *Builder) BuildALRDeps( found, notFound, err := b.repos.FindPkgs(ctx, depends) // Поиск зависимостей if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("failed FindPkgs: %w", err) } repoDeps = notFound @@ -551,7 +552,7 @@ func (b *Builder) BuildALRDeps( input.BuildOpts().Interactive, ) type item struct { - pkg *db.Package + pkg *alrsh.Package packages []string } pkgsMap := make(map[string]*item) @@ -586,7 +587,7 @@ func (b *Builder) BuildALRDeps( }, ) if err != nil { - return nil, nil, err + return nil, nil, fmt.Errorf("failed build package from db: %w", err) } buildDeps = append(buildDeps, res...) diff --git a/internal/build/cache.go b/internal/build/cache.go index 915c0da..2453090 100644 --- a/internal/build/cache.go +++ b/internal/build/cache.go @@ -23,7 +23,7 @@ import ( "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 { @@ -33,7 +33,7 @@ type Cache struct { func (c *Cache) CheckForBuiltPackage( ctx context.Context, input *BuildInput, - vars *types.BuildVars, + vars *alrsh.Package, ) (string, bool, error) { filename, err := pkgFileName(input, vars) if err != nil { @@ -56,7 +56,7 @@ func pkgFileName( PkgFormatProvider RepositoryProvider }, - vars *types.BuildVars, + vars *alrsh.Package, ) (string, error) { pkgInfo := getBasePkgInfo(vars, input) diff --git a/internal/build/checker.go b/internal/build/checker.go index 748d717..94cdc3f 100644 --- a/internal/build/checker.go +++ b/internal/build/checker.go @@ -25,7 +25,7 @@ import ( "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/manager" - "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" ) type Checker struct { @@ -35,7 +35,7 @@ type Checker struct { func (c *Checker) PerformChecks( ctx context.Context, input *BuildInput, - vars *types.BuildVars, + vars *alrsh.Package, ) (bool, error) { if !cpu.IsCompatibleWith(cpu.Arch(), vars.Architectures) { // Проверяем совместимость архитектуры cont, err := cliutils.YesNoPrompt( diff --git a/internal/build/safe_script_executor.go b/internal/build/safe_script_executor.go index 461bf81..3342e7b 100644 --- a/internal/build/safe_script_executor.go +++ b/internal/build/safe_script_executor.go @@ -29,7 +29,6 @@ import ( "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/types" ) var HandshakeConfig = plugin.HandshakeConfig{ @@ -51,13 +50,13 @@ type ScriptExecutorRPCServer struct { // ReadScript // -func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) { - var resp *alrsh.ALRSh +func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ScriptFile, error) { + var resp *alrsh.ScriptFile err := s.client.Call("Plugin.ReadScript", scriptPath, &resp) 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) if err != nil { return err @@ -73,15 +72,15 @@ func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *alrsh.ALRS type ExecuteFirstPassArgs struct { Input *BuildInput - Sf *alrsh.ALRSh + Sf *alrsh.ScriptFile } type ExecuteFirstPassResp struct { 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 err := s.client.Call("Plugin.ExecuteFirstPass", &ExecuteFirstPassArgs{ Input: input, @@ -149,8 +148,8 @@ func (s *ScriptExecutorRPCServer) PrepareDirs(args *PrepareDirsArgs, reply *stru type ExecuteSecondPassArgs struct { Input *BuildInput - Sf *alrsh.ALRSh - VarsOfPackages []*types.BuildVars + Sf *alrsh.ScriptFile + VarsOfPackages []*alrsh.Package RepoDeps []string BuiltDeps []*BuiltDep BasePkg string @@ -159,8 +158,8 @@ type ExecuteSecondPassArgs struct { func (s *ScriptExecutorRPC) ExecuteSecondPass( ctx context.Context, input *BuildInput, - sf *alrsh.ALRSh, - varsOfPackages []*types.BuildVars, + sf *alrsh.ScriptFile, + varsOfPackages []*alrsh.Package, repoDeps []string, builtDeps []*BuiltDep, basePkg string, diff --git a/internal/build/script_executor.go b/internal/build/script_executor.go index 01020a9..c67edfd 100644 --- a/internal/build/script_executor.go +++ b/internal/build/script_executor.go @@ -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) } -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) } @@ -86,8 +86,8 @@ func (e *LocalScriptExecutor) PrepareDirs( func (e *LocalScriptExecutor) ExecuteSecondPass( ctx context.Context, input *BuildInput, - sf *alrsh.ALRSh, - varsOfPackages []*types.BuildVars, + sf *alrsh.ScriptFile, + varsOfPackages []*alrsh.Package, repoDeps []string, builtDeps []*BuiltDep, basePkg string, @@ -126,7 +126,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass( for _, vars := range varsOfPackages { packageName := "" - if vars.Base != "" { + if vars.BasePkgName != "" { packageName = vars.Name } @@ -194,24 +194,25 @@ func buildPkgMetadata( PkgFormatProvider RepositoryProvider }, - vars *types.BuildVars, + vars *alrsh.Package, dirs types.Directories, deps []string, preferedContents *[]string, ) (*nfpm.Info, error) { 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.Homepage = vars.Homepage + pkgInfo.Homepage = vars.Homepage.Resolved() pkgInfo.License = strings.Join(vars.Licenses, ", ") - pkgInfo.Maintainer = vars.Maintainer + pkgInfo.Maintainer = vars.Maintainer.Resolved() pkgInfo.Overridables = nfpm.Overridables{ Conflicts: append(vars.Conflicts, vars.Name), Replaces: vars.Replaces, Provides: append(vars.Provides, vars.Name), Depends: deps, } - pkgInfo.Section = vars.Group + pkgInfo.Section = vars.Group.Resolved() pkgFormat := input.PkgFormat() info := input.OSRelease() @@ -224,12 +225,12 @@ func buildPkgMetadata( } if pkgFormat == "rpm" { - pkgInfo.RPM.Group = vars.Group + pkgInfo.RPM.Group = vars.Group.Resolved() - if vars.Summary != "" { - pkgInfo.RPM.Summary = vars.Summary + if vars.Summary.Resolved() != "" { + pkgInfo.RPM.Summary = vars.Summary.Resolved() } else { - lines := strings.SplitN(vars.Description, "\n", 2) + lines := strings.SplitN(vars.Description.Resolved(), "\n", 2) pkgInfo.RPM.Summary = lines[0] } } @@ -250,17 +251,17 @@ func buildPkgMetadata( } 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) - err = f.FindProvides(ctx, pkgInfo, dirs, vars.AutoProvSkipList) + err = f.FindProvides(ctx, pkgInfo, dirs, vars.AutoProvSkipList.Resolved()) if err != nil { 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) - err = f.FindRequires(ctx, pkgInfo, dirs, vars.AutoReqSkipList) + err = f.FindRequires(ctx, pkgInfo, dirs, vars.AutoReqSkipList.Resolved()) if err != nil { return nil, err } diff --git a/internal/build/script_resolver.go b/internal/build/script_resolver.go index 06edcfb..70bf763 100644 --- a/internal/build/script_resolver.go +++ b/internal/build/script_resolver.go @@ -20,7 +20,7 @@ import ( "context" "path/filepath" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/db" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" ) type ScriptResolver struct { @@ -34,7 +34,7 @@ type ScriptInfo struct { func (s *ScriptResolver) ResolveScript( ctx context.Context, - pkg *db.Package, + pkg *alrsh.Package, ) *ScriptInfo { var repository, script string diff --git a/internal/build/script_view.go b/internal/build/script_view.go index 52f47c3..e72cdfa 100644 --- a/internal/build/script_view.go +++ b/internal/build/script_view.go @@ -34,7 +34,7 @@ type ScriptViewer struct { func (s *ScriptViewer) ViewScript( ctx context.Context, input *BuildInput, - a *alrsh.ALRSh, + a *alrsh.ScriptFile, basePkg string, ) error { return cliutils.PromptViewScript( diff --git a/internal/build/utils.go b/internal/build/utils.go index fd7569a..1ef2f9d 100644 --- a/internal/build/utils.go +++ b/internal/build/utils.go @@ -40,6 +40,7 @@ import ( "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/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/types" ) @@ -59,7 +60,7 @@ func prepareDirs(dirs types.Directories) error { // Функция 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{} 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" } @@ -155,7 +156,7 @@ func buildContents(vars *types.BuildVars, dirs types.Directories, preferedConten var RegexpALRPackageName = regexp.MustCompile(`^(?P[^+]+)\+alr-(?P.+)$`) -func getBasePkgInfo(vars *types.BuildVars, input interface { +func getBasePkgInfo(vars *alrsh.Package, input interface { RepositoryProvider OsInfoProvider }, @@ -211,39 +212,39 @@ func createBuildEnvVars(info *distro.OSRelease, dirs types.Directories) []string } // Функция setScripts добавляет скрипты-перехватчики к метаданным пакета. -func setScripts(vars *types.BuildVars, info *nfpm.Info, scriptDir string) { - if vars.Scripts.PreInstall != "" { - info.Scripts.PreInstall = filepath.Join(scriptDir, vars.Scripts.PreInstall) +func setScripts(vars *alrsh.Package, info *nfpm.Info, scriptDir string) { + if vars.Scripts.Resolved().PreInstall != "" { + info.Scripts.PreInstall = filepath.Join(scriptDir, vars.Scripts.Resolved().PreInstall) } - if vars.Scripts.PostInstall != "" { - info.Scripts.PostInstall = filepath.Join(scriptDir, vars.Scripts.PostInstall) + if vars.Scripts.Resolved().PostInstall != "" { + info.Scripts.PostInstall = filepath.Join(scriptDir, vars.Scripts.Resolved().PostInstall) } - if vars.Scripts.PreRemove != "" { - info.Scripts.PreRemove = filepath.Join(scriptDir, vars.Scripts.PreRemove) + if vars.Scripts.Resolved().PreRemove != "" { + info.Scripts.PreRemove = filepath.Join(scriptDir, vars.Scripts.Resolved().PreRemove) } - if vars.Scripts.PostRemove != "" { - info.Scripts.PostRemove = filepath.Join(scriptDir, vars.Scripts.PostRemove) + if vars.Scripts.Resolved().PostRemove != "" { + info.Scripts.PostRemove = filepath.Join(scriptDir, vars.Scripts.Resolved().PostRemove) } - if vars.Scripts.PreUpgrade != "" { - info.ArchLinux.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.PreUpgrade) - info.APK.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.PreUpgrade) + if vars.Scripts.Resolved().PreUpgrade != "" { + info.ArchLinux.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PreUpgrade) + info.APK.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PreUpgrade) } - if vars.Scripts.PostUpgrade != "" { - info.ArchLinux.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.PostUpgrade) - info.APK.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.PostUpgrade) + if vars.Scripts.Resolved().PostUpgrade != "" { + info.ArchLinux.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PostUpgrade) + info.APK.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PostUpgrade) } - if vars.Scripts.PreTrans != "" { - info.RPM.Scripts.PreTrans = filepath.Join(scriptDir, vars.Scripts.PreTrans) + if vars.Scripts.Resolved().PreTrans != "" { + info.RPM.Scripts.PreTrans = filepath.Join(scriptDir, vars.Scripts.Resolved().PreTrans) } - if vars.Scripts.PostTrans != "" { - info.RPM.Scripts.PostTrans = filepath.Join(scriptDir, vars.Scripts.PostTrans) + if vars.Scripts.Resolved().PostTrans != "" { + info.RPM.Scripts.PostTrans = filepath.Join(scriptDir, vars.Scripts.Resolved().PostTrans) } } diff --git a/internal/cliutils/app_builder/builder.go b/internal/cliutils/app_builder/builder.go index 0d8fe40..a946a12 100644 --- a/internal/cliutils/app_builder/builder.go +++ b/internal/cliutils/app_builder/builder.go @@ -123,8 +123,15 @@ func (b *AppBuilder) withRepos(enablePull, forcePull bool) *AppBuilder { cfg := b.deps.Cfg db := b.deps.DB - if cfg == nil || db == nil { - b.err = errors.New("config and db are required before initializing repos") + info := b.deps.Info + + 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 } diff --git a/internal/cliutils/prompt.go b/internal/cliutils/prompt.go index af04fa0..bc07c39 100644 --- a/internal/cliutils/prompt.go +++ b/internal/cliutils/prompt.go @@ -28,8 +28,8 @@ import ( "github.com/AlecAivazis/survey/v2" "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/pkg/alrsh" ) // 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 // 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 { - var outPkgs []db.Package +func FlattenPkgs(ctx context.Context, found map[string][]alrsh.Package, verb string, interactive bool) []alrsh.Package { + var outPkgs []alrsh.Package for _, pkgs := range found { if len(pkgs) > 1 && 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. -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 { return options[0], nil } @@ -138,7 +138,7 @@ func PkgPrompt(ctx context.Context, options []db.Package, verb string, interacti var choice int err := survey.AskOne(prompt, &choice) if err != nil { - return db.Package{}, err + return alrsh.Package{}, err } return options[choice], nil diff --git a/internal/cliutils/utils.go b/internal/cliutils/utils.go index 010d2e0..48c4dc7 100644 --- a/internal/cliutils/utils.go +++ b/internal/cliutils/utils.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "log/slog" + "runtime/debug" "github.com/leonelquinteros/gotext" "github.com/urfave/cli/v2" @@ -44,10 +45,12 @@ func HandleExitCoder(err error) { slog.Error(err.Error()) } } + debug.PrintStack() cli.OsExiter(exitErr.ExitCode()) return } + debug.PrintStack() slog.Error(err.Error()) cli.OsExiter(1) } diff --git a/internal/db/db.go b/internal/db/db.go index 62ebff9..ffb9298 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -28,32 +28,11 @@ import ( "xorm.io/xorm" "gitea.plemya-x.ru/Plemya-x/ALR/internal/config" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" ) 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 { Version int `xorm:"'version'"` } @@ -76,6 +55,8 @@ func New(config Config) *Database { func (d *Database) Connect() error { dsn := d.config.GetPaths().DBPath engine, err := xorm.NewEngine("sqlite", dsn) + // engine.SetLogLevel(log.LOG_DEBUG) + // engine.ShowSQL(true) if err != nil { return err } @@ -87,7 +68,7 @@ func (d *Database) Init(ctx context.Context) error { if err := d.Connect(); err != nil { 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 } ver, ok := d.GetVersion(ctx) @@ -119,10 +100,10 @@ func (d *Database) addVersion(ver int) 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) 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 } -func (d *Database) GetPkgs(_ context.Context, where string, args ...any) ([]Package, error) { - var pkgs []Package +func (d *Database) GetPkgs(_ context.Context, where string, args ...any) ([]alrsh.Package, error) { + var pkgs []alrsh.Package err := d.engine.Where(where, args...).Find(&pkgs) return pkgs, err } -func (d *Database) GetPkg(where string, args ...any) (*Package, error) { - var pkg Package +func (d *Database) GetPkg(where string, args ...any) (*alrsh.Package, error) { + var pkg alrsh.Package has, err := d.engine.Where(where, args...).Get(&pkg) if err != nil || !has { 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 { - _, err := d.engine.Where(where, args...).Delete(&Package{}) + _, err := d.engine.Where(where, args...).Delete(&alrsh.Package{}) return err } 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 } diff --git a/internal/db/db_test.go b/internal/db/db_test.go index 3621905..1962604 100644 --- a/internal/db/db_test.go +++ b/internal/db/db_test.go @@ -25,8 +25,11 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "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/pkg/alrsh" ) type TestALRConfig struct{} @@ -43,35 +46,38 @@ func prepareDb() *db.Database { return database } -var testPkg = db.Package{ +var testPkg = alrsh.Package{ Name: "test", Version: "0.0.1", Release: 1, Epoch: 2, - Description: map[string]string{ + Description: alrsh.OverridableFromMap(map[string]string{ "en": "Test package", "ru": "Проверочный пакет", - }, - Homepage: map[string]string{ + }), + Homepage: alrsh.OverridableFromMap(map[string]string{ "en": "https://gitea.plemya-x.ru/xpamych/ALR", - }, - Maintainer: map[string]string{ + }), + Maintainer: alrsh.OverridableFromMap(map[string]string{ "en": "Evgeniy Khramov ", "ru": "Евгений Храмов ", - }, + }), Architectures: []string{"arm64", "amd64"}, Licenses: []string{"GPL-3.0-or-later"}, Provides: []string{"test"}, Conflicts: []string{"test"}, Replaces: []string{"test-old"}, - Depends: map[string][]string{ + Depends: alrsh.OverridableFromMap(map[string][]string{ "": {"sudo"}, - }, - BuildDepends: map[string][]string{ + }), + BuildDepends: alrsh.OverridableFromMap(map[string][]string{ "": {"golang"}, "arch": {"go"}, - }, + }), 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) { @@ -106,9 +112,7 @@ func TestInsertPackage(t *testing.T) { t.Fatalf("Expected 1 package, got %d", len(pkgs)) } - if !reflect.DeepEqual(testPkg, pkgs[0]) { - t.Errorf("Expected test package to be the same as database package") - } + assert.Equal(t, testPkg, pkgs[0]) } func TestGetPkgs(t *testing.T) { diff --git a/internal/overrides/overrides.go b/internal/overrides/overrides.go index 8d42f8a..00bdc48 100644 --- a/internal/overrides/overrides.go +++ b/internal/overrides/overrides.go @@ -21,7 +21,6 @@ package overrides import ( "fmt" - "reflect" "regexp" "strings" @@ -29,7 +28,6 @@ import ( "golang.org/x/text/language" "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" ) @@ -150,65 +148,6 @@ func (o *Opts) WithLanguageTags(langs []string) *Opts { 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) { out := make([]string, len(tags)+len(langs)) for i, tag := range tags { diff --git a/internal/repos/find.go b/internal/repos/find.go index b978cc6..957b3e3 100644 --- a/internal/repos/find.go +++ b/internal/repos/find.go @@ -22,11 +22,11 @@ package repos import ( "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) { - found := map[string][]db.Package{} +func (rs *Repos) FindPkgs(ctx context.Context, pkgs []string) (map[string][]alrsh.Package, []string, error) { + found := map[string][]alrsh.Package{} notFound := []string(nil) for _, pkgName := range pkgs { diff --git a/internal/repos/find_test.go b/internal/repos/find_test.go index 384a31b..93fbfa9 100644 --- a/internal/repos/find_test.go +++ b/internal/repos/find_test.go @@ -24,8 +24,8 @@ import ( "strings" "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/pkg/alrsh" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) @@ -89,31 +89,31 @@ func TestFindPkgsEmpty(t *testing.T) { e.Db, ) - err := e.Db.InsertPackage(e.Ctx, db.Package{ + err := e.Db.InsertPackage(e.Ctx, alrsh.Package{ Name: "test1", Repository: "default", Version: "0.0.1", Release: 1, - Description: map[string]string{ + Provides: []string{""}, + Description: alrsh.OverridableFromMap(map[string]string{ "en": "Test package 1", "ru": "Проверочный пакет 1", - }, - Provides: []string{""}, + }), }) if err != nil { 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", Repository: "default", Version: "0.0.1", Release: 1, - Description: map[string]string{ + Provides: []string{"test"}, + Description: alrsh.OverridableFromMap(map[string]string{ "en": "Test package 2", "ru": "Проверочный пакет 2", - }, - Provides: []string{"test"}, + }), }) if err != nil { t.Fatalf("Expected no error, got %s", err) diff --git a/internal/repos/pull_internal_test.go b/internal/repos/pull_internal_test.go index 8192cfe..6bd325b 100644 --- a/internal/repos/pull_internal_test.go +++ b/internal/repos/pull_internal_test.go @@ -27,6 +27,7 @@ import ( "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/pkg/alrsh" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) @@ -84,10 +85,10 @@ build_deps=('golang') result, err := database.GetPkgs(ctx, "1 = 1") assert.NoError(t, err) pkgCount := 0 - for _, dbPkg := range result { - assert.Equal(t, "foo", dbPkg.Name) - assert.Equal(t, map[string]string{"": "main desc"}, dbPkg.Description) - assert.Equal(t, map[string][]string{"": {"sudo"}}, dbPkg.Depends) + for _, pkg := range result { + assert.Equal(t, "foo", pkg.Name) + assert.Equal(t, alrsh.OverridableFromMap(map[string]string{"": "main desc"}), pkg.Description) + assert.Equal(t, alrsh.OverridableFromMap(map[string][]string{"": {"sudo"}}), pkg.Depends) pkgCount++ } assert.Equal(t, 1, pkgCount) @@ -119,18 +120,18 @@ meta_buz() { assert.NoError(t, err) pkgCount := 0 - for _, dbPkg := range result { + for _, pkg := range result { if err != nil { t.Errorf("Expected no error, got %s", err) } - if dbPkg.Name == "bar" { - assert.Equal(t, map[string]string{"": "foo desc"}, dbPkg.Description) - assert.Equal(t, map[string][]string{"": {"sudo"}}, dbPkg.Depends) + if pkg.Name == "bar" { + assert.Equal(t, alrsh.OverridableFromMap(map[string]string{"": "foo desc"}), pkg.Description) + assert.Equal(t, alrsh.OverridableFromMap(map[string][]string{"": {"sudo"}}), pkg.Depends) } - if dbPkg.Name == "buz" { - assert.Equal(t, map[string]string{"": "main desc"}, dbPkg.Description) - assert.Equal(t, map[string][]string{"": {"sudo", "doas"}}, dbPkg.Depends) + if pkg.Name == "buz" { + assert.Equal(t, alrsh.OverridableFromMap(map[string]string{"": "main desc"}), pkg.Description) + assert.Equal(t, alrsh.OverridableFromMap(map[string][]string{"": {"sudo", "doas"}}), pkg.Depends) } pkgCount++ } diff --git a/internal/repos/utils.go b/internal/repos/utils.go index 6bd93e0..5b6e1cd 100644 --- a/internal/repos/utils.go +++ b/internal/repos/utils.go @@ -18,12 +18,9 @@ package repos import ( "context" - "errors" "fmt" "io" "path/filepath" - "reflect" - "strings" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" @@ -34,9 +31,7 @@ import ( "mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/syntax" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/db" - "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/alrsh" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) @@ -63,151 +58,21 @@ func parseScript( syntaxParser *syntax.Parser, runner *interp.Runner, r io.ReadCloser, -) ([]*db.Package, error) { - fl, err := syntaxParser.Parse(r, "alr.sh") +) ([]*alrsh.Package, error) { + f, err := alrsh.ReadFromIOReader(r, "/tmp") if err != nil { return nil, err } - - runner.Reset() - err = runner.Run(ctx, fl) + _, dbPkgs, err := f.ParseBuildVars(ctx, &distro.OSRelease{}, []string{}) if err != nil { return nil, err } - - d := decoder.New(&distro.OSRelease{}, runner) - d.Overrides = false - d.LikeDistros = false - - pkgNames, err := parser.ParseNames(d) - if err != nil { - return nil, fmt.Errorf("failed parsing package names: %w", err) + for _, pkg := range dbPkgs { + pkg.Repository = repo.Name } - - 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 } -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) { remote, err := r.Remote(git.DefaultRemoteName) if err != nil { diff --git a/internal/search/search.go b/internal/search/search.go index 326906a..ca31bdc 100644 --- a/internal/search/search.go +++ b/internal/search/search.go @@ -22,12 +22,11 @@ package search import ( "context" - "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/pkg/alrsh" ) 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 { @@ -43,7 +42,7 @@ func New(pp PackagesProvider) *Searcher { func (s *Searcher) Search( ctx context.Context, opts *SearchOptions, -) ([]database.Package, error) { +) ([]alrsh.Package, error) { where, args := opts.WhereClause() packages, err := s.pp.GetPkgs(ctx, where, args...) return packages, err diff --git a/internal/shutils/decoder/decoder.go b/internal/shutils/decoder/decoder.go index ba31b12..0119664 100644 --- a/internal/shutils/decoder/decoder.go +++ b/internal/shutils/decoder/decoder.go @@ -22,6 +22,8 @@ package decoder import ( "context" "errors" + "fmt" + "log/slog" "reflect" "strings" @@ -52,7 +54,7 @@ type InvalidTypeError struct { } 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 @@ -80,10 +82,58 @@ func (d *Decoder) DecodeVar(name string, val any) error { dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ WeaklyTypedInput: true, - Result: val, - TagName: "sh", + DecodeHook: mapstructure.DecodeHookFuncValue(func(from, to reflect.Value) (interface{}, error) { + 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 { + slog.Warn("err", "err", err) return err } @@ -243,23 +293,31 @@ func (d *Decoder) getVar(name string) *expand.Variable { } for _, varName := range names { - val, ok := d.Runner.Vars[varName] - 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 + res := d.getVarNoOverrides(varName) + if res != nil { + return res } } 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 { value = strings.ToLower(strings.TrimSpace(value)) return value == "true" || value == "yes" || value == "1" diff --git a/internal/translations/default.pot b/internal/translations/default.pot index 305ee50..ce8bc93 100644 --- a/internal/translations/default.pot +++ b/internal/translations/default.pot @@ -114,35 +114,35 @@ msgstr "" msgid "Error parsing os-release file" msgstr "" -#: info.go:41 +#: info.go:42 msgid "Print information about a package" msgstr "" -#: info.go:46 +#: info.go:47 msgid "Show all information, not just for the current distro" msgstr "" -#: info.go:67 +#: info.go:68 msgid "Error getting packages" msgstr "" -#: info.go:82 +#: info.go:83 msgid "Command info expected at least 1 argument, got %d" msgstr "" -#: info.go:102 +#: info.go:104 msgid "Error finding packages" msgstr "" -#: info.go:116 +#: info.go:118 msgid "Can't detect system language" msgstr "" -#: info.go:133 +#: info.go:135 msgid "Error resolving overrides" msgstr "" -#: info.go:141 info.go:146 +#: info.go:144 info.go:149 msgid "Error encoding script variables" msgstr "" @@ -174,19 +174,19 @@ msgstr "" msgid "Error removing packages" msgstr "" -#: internal/build/build.go:375 +#: internal/build/build.go:376 msgid "Building package" msgstr "" -#: internal/build/build.go:404 +#: internal/build/build.go:405 msgid "The checksums array must be the same length as sources" msgstr "" -#: internal/build/build.go:446 +#: internal/build/build.go:447 msgid "Downloading sources" msgstr "" -#: internal/build/build.go:538 +#: internal/build/build.go:539 msgid "Installing dependencies" msgstr "" @@ -224,15 +224,15 @@ msgstr "" msgid "Building package metadata" msgstr "" -#: internal/build/script_executor.go:275 +#: internal/build/script_executor.go:276 msgid "Executing prepare()" msgstr "" -#: internal/build/script_executor.go:284 +#: internal/build/script_executor.go:285 msgid "Executing build()" 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()" msgstr "" @@ -244,15 +244,15 @@ msgstr "" msgid "Error initialization database" msgstr "" -#: internal/cliutils/app_builder/builder.go:135 +#: internal/cliutils/app_builder/builder.go:142 msgid "Error pulling repositories" msgstr "" -#: internal/cliutils/app_builder/builder.go:152 +#: internal/cliutils/app_builder/builder.go:159 msgid "Error parsing os release" 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" msgstr "" @@ -336,17 +336,17 @@ msgstr "" msgid "OPTIONS" msgstr "" -#: internal/cliutils/utils.go:69 +#: internal/cliutils/utils.go:72 msgid "" "This command is deprecated and would be removed in the future, use \"%s\" " "instead!" msgstr "" -#: internal/db/db.go:95 +#: internal/db/db.go:76 msgid "Database version mismatch; resetting" msgstr "" -#: internal/db/db.go:101 +#: internal/db/db.go:82 msgid "" "Database version does not exist. Run alr fix if something isn't working." msgstr "" @@ -541,14 +541,14 @@ msgstr "" msgid "Error while executing search" msgstr "" -#: upgrade.go:47 +#: upgrade.go:48 msgid "Upgrade all installed packages" msgstr "" -#: upgrade.go:105 upgrade.go:122 +#: upgrade.go:106 upgrade.go:123 msgid "Error checking for updates" msgstr "" -#: upgrade.go:125 +#: upgrade.go:126 msgid "There is nothing to do." msgstr "" diff --git a/internal/translations/po/ru/default.po b/internal/translations/po/ru/default.po index 7df88f9..dd7d42c 100644 --- a/internal/translations/po/ru/default.po +++ b/internal/translations/po/ru/default.po @@ -121,35 +121,35 @@ msgstr "Такой вспомогательной команды нет" msgid "Error parsing os-release file" msgstr "Ошибка при разборе файла выпуска операционной системы" -#: info.go:41 +#: info.go:42 msgid "Print information about a package" msgstr "Отобразить информацию о пакете" -#: info.go:46 +#: info.go:47 msgid "Show all information, not just for the current distro" msgstr "Показывать всю информацию, не только для текущего дистрибутива" -#: info.go:67 +#: info.go:68 msgid "Error getting packages" msgstr "Ошибка при получении пакетов" -#: info.go:82 +#: info.go:83 msgid "Command info expected at least 1 argument, got %d" msgstr "Для команды info ожидался хотя бы 1 аргумент, получено %d" -#: info.go:102 +#: info.go:104 msgid "Error finding packages" msgstr "Ошибка при поиске пакетов" -#: info.go:116 +#: info.go:118 msgid "Can't detect system language" msgstr "Ошибка при определении языка системы" -#: info.go:133 +#: info.go:135 msgid "Error resolving overrides" msgstr "Ошибка устранения переорпеделений" -#: info.go:141 info.go:146 +#: info.go:144 info.go:149 msgid "Error encoding script variables" msgstr "Ошибка кодирования переменных скрита" @@ -181,19 +181,19 @@ msgstr "Для команды remove ожидался хотя бы 1 аргум msgid "Error removing packages" msgstr "Ошибка при удалении пакетов" -#: internal/build/build.go:375 +#: internal/build/build.go:376 msgid "Building package" msgstr "Сборка пакета" -#: internal/build/build.go:404 +#: internal/build/build.go:405 msgid "The checksums array must be the same length as sources" msgstr "Массив контрольных сумм должен быть той же длины, что и источники" -#: internal/build/build.go:446 +#: internal/build/build.go:447 msgid "Downloading sources" msgstr "Скачивание источников" -#: internal/build/build.go:538 +#: internal/build/build.go:539 msgid "Installing dependencies" msgstr "Установка зависимостей" @@ -235,15 +235,15 @@ msgstr "" msgid "Building package metadata" msgstr "Сборка метаданных пакета" -#: internal/build/script_executor.go:275 +#: internal/build/script_executor.go:276 msgid "Executing prepare()" msgstr "Выполнение prepare()" -#: internal/build/script_executor.go:284 +#: internal/build/script_executor.go:285 msgid "Executing 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()" msgstr "Выполнение %s()" @@ -255,15 +255,15 @@ msgstr "Ошибка при загрузке" msgid "Error initialization database" msgstr "Ошибка инициализации базы данных" -#: internal/cliutils/app_builder/builder.go:135 +#: internal/cliutils/app_builder/builder.go:142 msgid "Error pulling repositories" msgstr "Ошибка при извлечении репозиториев" -#: internal/cliutils/app_builder/builder.go:152 +#: internal/cliutils/app_builder/builder.go:159 msgid "Error parsing os release" 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" msgstr "Не удалось обнаружить поддерживаемый менеджер пакетов в системе" @@ -347,7 +347,7 @@ msgstr "КАТЕГОРИЯ" msgid "OPTIONS" msgstr "ПАРАМЕТРЫ" -#: internal/cliutils/utils.go:69 +#: internal/cliutils/utils.go:72 msgid "" "This command is deprecated and would be removed in the future, use \"%s\" " "instead!" @@ -355,11 +355,11 @@ msgstr "" "Эта команда устарела и будет удалена в будущем, используйте вместо нее \"%s" "\"!" -#: internal/db/db.go:95 +#: internal/db/db.go:76 msgid "Database version mismatch; resetting" msgstr "Несоответствие версий базы данных; сброс настроек" -#: internal/db/db.go:101 +#: internal/db/db.go:82 msgid "" "Database version does not exist. Run alr fix if something isn't working." msgstr "" @@ -557,15 +557,15 @@ msgstr "Иcкать по provides" msgid "Error while executing search" msgstr "Ошибка при выполнении поиска" -#: upgrade.go:47 +#: upgrade.go:48 msgid "Upgrade all installed packages" msgstr "Обновить все установленные пакеты" -#: upgrade.go:105 upgrade.go:122 +#: upgrade.go:106 upgrade.go:123 msgid "Error checking for updates" msgstr "Ошибка при проверке обновлений" -#: upgrade.go:125 +#: upgrade.go:126 msgid "There is nothing to do." msgstr "Здесь нечего делать." diff --git a/list.go b/list.go index 4fbcd14..8d1ba69 100644 --- a/list.go +++ b/list.go @@ -32,9 +32,9 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/build" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" 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/utils" + "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" ) func ListCmd() *cli.Command { @@ -69,9 +69,9 @@ func ListCmd() *cli.Command { WithConfig(). WithDB(). WithManager(). + WithDistroInfo(). // autoPull only WithRepos(). - WithDistroInfo(). Build() if err != nil { return err @@ -159,7 +159,7 @@ func ListCmd() *cli.Command { } type packageInfo struct { - Package *database.Package + Package *alrsh.Package Version string } diff --git a/pkg/alrsh/alrsh.go b/pkg/alrsh/alrsh.go index 37a723e..f2237b9 100644 --- a/pkg/alrsh/alrsh.go +++ b/pkg/alrsh/alrsh.go @@ -38,7 +38,7 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" ) -type ALRSh struct { +type ScriptFile struct { file *syntax.File path string } @@ -72,97 +72,134 @@ func createBuildEnvVars(info *distro.OSRelease, dirs types.Directories) []string return env } -func (s *ALRSh) ParseBuildVars(ctx context.Context, info *distro.OSRelease, packages []string) (string, []*types.BuildVars, error) { - varsOfPackages := []*types.BuildVars{} - - 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), - ) +func (s *ScriptFile) ParseBuildVars(ctx context.Context, info *distro.OSRelease, packages []string) (string, []*Package, error) { + runner, err := s.createRunner(info) if err != nil { 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 { return "", nil, err } - dec := decoder.New(info, runner) // Создаём новый декодер - - 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 { + if len(pkgNames.Names) == 0 { return "", nil, errors.New("package name is missing") } - var vars types.BuildVars - - if len(pkgs.Names) == 1 { - err = dec.DecodeVars(&vars) - if err != nil { - return "", nil, err - } - varsOfPackages = append(varsOfPackages, &vars) - - return vars.Name, varsOfPackages, nil + targetPackages := packages + if len(targetPackages) == 0 { + targetPackages = pkgNames.Names } - var pkgNames []string - - if len(packages) != 0 { - pkgNames = packages - } else { - pkgNames = pkgs.Names + varsOfPackages, err := s.createPackagesForBuildVars(ctx, dec, pkgNames, targetPackages) + if err != nil { + return "", nil, err } - for _, pkgName := range pkgNames { - var preVars types.BuildVarsPre - funcName := fmt.Sprintf("meta_%s", pkgName) - 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) + baseName := pkgNames.BasePkgName + if len(pkgNames.Names) == 1 { + baseName = pkgNames.Names[0] } - 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 } -func (a *ALRSh) File() *syntax.File { +func (a *ScriptFile) File() *syntax.File { return a.file } diff --git a/pkg/alrsh/gob.go b/pkg/alrsh/gob.go index e1ad501..bb81815 100644 --- a/pkg/alrsh/gob.go +++ b/pkg/alrsh/gob.go @@ -24,7 +24,7 @@ import ( "mvdan.cc/sh/v3/syntax/typedjson" ) -func (s *ALRSh) GobEncode() ([]byte, error) { +func (s *ScriptFile) GobEncode() ([]byte, error) { var buf bytes.Buffer enc := gob.NewEncoder(&buf) if err := enc.Encode(s.path); err != nil { @@ -41,7 +41,7 @@ func (s *ALRSh) GobEncode() ([]byte, error) { return buf.Bytes(), nil } -func (s *ALRSh) GobDecode(data []byte) error { +func (s *ScriptFile) GobDecode(data []byte) error { buf := bytes.NewBuffer(data) dec := gob.NewDecoder(buf) if err := dec.Decode(&s.path); err != nil { diff --git a/pkg/alrsh/overridable.go b/pkg/alrsh/overridable.go new file mode 100644 index 0000000..f0ab785 --- /dev/null +++ b/pkg/alrsh/overridable.go @@ -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 . + +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, + } +} diff --git a/pkg/alrsh/package.go b/pkg/alrsh/package.go new file mode 100644 index 0000000..c24d0b2 --- /dev/null +++ b/pkg/alrsh/package.go @@ -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 . + +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) + } + } + } +} diff --git a/pkg/alrsh/read.go b/pkg/alrsh/read.go index 360e44d..d5d7d74 100644 --- a/pkg/alrsh/read.go +++ b/pkg/alrsh/read.go @@ -18,6 +18,7 @@ package alrsh import ( "fmt" + "io" "io/fs" "os" @@ -30,23 +31,27 @@ func (fs *localFs) Open(name string) (fs.File, error) { 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) if err != nil { return nil, fmt.Errorf("failed to open alr.sh: %w", err) } defer fl.Close() - file, err := syntax.NewParser().Parse(fl, "alr.sh") - if err != nil { - return nil, err - } - return &ALRSh{ - file: file, - path: script, - }, nil + return ReadFromIOReader(fl, script) } -func ReadFromLocal(script string) (*ALRSh, error) { +func ReadFromLocal(script string) (*ScriptFile, error) { return ReadFromFS(&localFs{}, script) } diff --git a/pkg/types/build.go b/pkg/types/build.go index 350a1f0..7e253b0 100644 --- a/pkg/types/build.go +++ b/pkg/types/build.go @@ -24,49 +24,6 @@ type BuildOpts struct { 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 { PreInstall string `sh:"preinstall"` PostInstall string `sh:"postinstall"` diff --git a/search.go b/search.go index 5b32685..02c88ae 100644 --- a/search.go +++ b/search.go @@ -27,10 +27,10 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" 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/search" "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" ) @@ -139,27 +139,16 @@ func SearchCmd() *cli.Command { } } - for _, dbPkg := range packages { - var pkg any - if !all { - pkg = overrides.ResolvePackage(&dbPkg, names) - } else { - pkg = &dbPkg - } - + for _, pkg := range packages { + alrsh.ResolvePackage(&pkg, names) if tmpl != nil { - err = tmpl.Execute(os.Stdout, pkg) + err = tmpl.Execute(os.Stdout, &pkg) if err != nil { return cliutils.FormatCliExit(gotext.Get("Error executing template"), err) } fmt.Println() } else { - switch v := pkg.(type) { - case *overrides.ResolvedPackage: - fmt.Println(v.Name) - case *db.Package: - fmt.Println(v.Name) - } + fmt.Println(pkg.Name) } } diff --git a/upgrade.go b/upgrade.go index 2183e84..254edaa 100644 --- a/upgrade.go +++ b/upgrade.go @@ -37,6 +37,7 @@ import ( "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/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/types" ) @@ -130,8 +131,8 @@ func UpgradeCmd() *cli.Command { } } -func mapUptatesInfoToPackages(updates []UpdateInfo) []database.Package { - var pkgs []database.Package +func mapUptatesInfoToPackages(updates []UpdateInfo) []alrsh.Package { + var pkgs []alrsh.Package for _, info := range updates { pkgs = append(pkgs, *info.Package) } @@ -139,7 +140,7 @@ func mapUptatesInfoToPackages(updates []UpdateInfo) []database.Package { } type UpdateInfo struct { - Package *database.Package + Package *alrsh.Package FromVersion string ToVersion string -- 2.49.1 From d286041864a24a134ddcb9d2d95270fa2b6e2a8c Mon Sep 17 00:00:00 2001 From: Maxim Slipenko Date: Thu, 12 Jun 2025 16:57:35 +0300 Subject: [PATCH 6/6] ci: add alr-git update --- .gitea/workflows/update-alr-git.yaml | 69 ++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 .gitea/workflows/update-alr-git.yaml diff --git a/.gitea/workflows/update-alr-git.yaml b/.gitea/workflows/update-alr-git.yaml new file mode 100644 index 0000000..b4130c5 --- /dev/null +++ b/.gitea/workflows/update-alr-git.yaml @@ -0,0 +1,69 @@ +# 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 . + +name: Update alr-git + +on: + push: + branches: + - master + +jobs: + changelog: + runs-on: ubuntu-latest + steps: + - name: Install the latest version of uv + uses: astral-sh/setup-uv@v6 + + - name: Setup alr-spec + run: | + uv tool install alr-spec==0.0.4 + + - name: Install alr + run: | + apt-get update && apt-get install -y libcap2-bin + curl -fsS https://gitea.plemya-x.ru/Plemya-x/ALR/raw/branch/master/scripts/install.sh | bash + + - name: Checkout this repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set ALR version + run: | + echo "NEW_ALR_VERSION=$(alr helper git-version)" >> $GITHUB_ENV + + - name: Checkout alr-default repository + uses: actions/checkout@v4 + with: + repository: Plemya-x/alr-default + token: ${{ secrets.GITEAPUBLIC }} + path: alr-default + + - name: Update version + working-directory: ./alr-default/alr-git + run: | + alr-spec set-filed version $NEW_ALR_VERSION + alr-spec set-filed release 1 + + - name: Commit changes + run: | + cd alr-default + git config user.name "gitea" + git config user.email "admin@plemya-x.ru" + git add . + git commit -m "Обновление версии до $NEW_ALR_VERSION" + git push -- 2.49.1