From 587abf7aad69836e31633831d6d7748d78cb83d9 Mon Sep 17 00:00:00 2001 From: Maxim Slipenko Date: Sun, 13 Apr 2025 19:12:02 +0300 Subject: [PATCH] refactor --- assets/coverage-badge.svg | 4 +- fix.go | 44 ++++---- info.go | 46 +++------ internal/cliutils/app_builder/builder.go | 126 +++++++++++++++++++++++ internal/translations/default.pot | 68 ++++++------ internal/translations/po/ru/default.po | 69 +++++++------ internal/utils/cmd.go | 2 +- list.go | 37 +++---- search.go | 48 ++++----- 9 files changed, 275 insertions(+), 169 deletions(-) create mode 100644 internal/cliutils/app_builder/builder.go diff --git a/assets/coverage-badge.svg b/assets/coverage-badge.svg index 5a9d2fc..cfa4439 100644 --- a/assets/coverage-badge.svg +++ b/assets/coverage-badge.svg @@ -11,7 +11,7 @@ coverage coverage - 15.8% - 15.8% + 15.7% + 15.7% diff --git a/fix.go b/fix.go index 218b389..ed08ad7 100644 --- a/fix.go +++ b/fix.go @@ -27,10 +27,8 @@ import ( "github.com/leonelquinteros/gotext" "github.com/urfave/cli/v2" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/config" - database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db" + appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" - "gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos" ) func FixCmd() *cli.Command { @@ -38,19 +36,22 @@ func FixCmd() *cli.Command { Name: "fix", Usage: gotext.Get("Attempt to fix problems with ALR"), Action: func(c *cli.Context) error { - err := utils.DropCapsToAlrUser() - if err != nil { - slog.Error(gotext.Get("Can't drop privileges")) - return cli.Exit(err, 1) + if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil { + return err } ctx := c.Context - cfg := config.New() - err = cfg.Load() + + deps, err := appbuilder. + New(ctx). + WithConfig(). + Build() if err != nil { - slog.Error(gotext.Get("Error loading config")) return cli.Exit(err, 1) } + defer deps.Defer() + + cfg := deps.Cfg paths := cfg.GetPaths() @@ -86,25 +87,16 @@ func FixCmd() *cli.Command { return cli.Exit(err, 1) } - cfg = config.New() - err = cfg.Load() + deps, err = appbuilder. + New(ctx). + WithConfig(). + WithDB(). + WithRepos(). + Build() if err != nil { - slog.Error(gotext.Get("Error loading config")) - return cli.Exit(err, 1) - } - - db := database.New(cfg) - err = db.Init(ctx) - if err != nil { - slog.Error(gotext.Get("Error initialization database")) - return cli.Exit(err, 1) - } - rs := repos.New(cfg, db) - err = rs.Pull(ctx, cfg.Repos()) - if err != nil { - slog.Error(gotext.Get("Error pulling repos")) return cli.Exit(err, 1) } + defer deps.Defer() slog.Info(gotext.Get("Done")) diff --git a/info.go b/info.go index 69429ea..02f462c 100644 --- a/info.go +++ b/info.go @@ -30,12 +30,12 @@ import ( "gopkg.in/yaml.v3" "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/config" 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" - "gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos" ) func InfoCmd() *cli.Command { @@ -50,15 +50,14 @@ func InfoCmd() *cli.Command { }, }, BashComplete: func(c *cli.Context) { - err := utils.ExitIfCantDropCapsToAlrUser() - if err != nil { + if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil { slog.Error("Can't drop caps") os.Exit(1) } ctx := c.Context cfg := config.New() - err = cfg.Load() + err := cfg.Load() if err != nil { slog.Error(gotext.Get("Error loading config"), "err", err) os.Exit(1) @@ -90,40 +89,29 @@ func InfoCmd() *cli.Command { } }, Action: func(c *cli.Context) error { - err := utils.ExitIfCantDropCapsToAlrUser() - if err != nil { + if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil { return err } - ctx := c.Context - - cfg := config.New() - err = cfg.Load() - if err != nil { - slog.Error(gotext.Get("Error loading config")) - return cli.Exit(err, 1) - } - - db := database.New(cfg) - err = db.Init(ctx) - if err != nil { - slog.Error(gotext.Get("Error initialization database")) - return cli.Exit(err, 1) - } - rs := repos.New(cfg, db) - args := c.Args() if args.Len() < 1 { return cli.Exit(gotext.Get("Command info expected at least 1 argument, got %d", args.Len()), 1) } - if cfg.AutoPull() { - err := rs.Pull(ctx, cfg.Repos()) - if err != nil { - slog.Error(gotext.Get("Error pulling repos")) - return cli.Exit(err, 1) - } + ctx := c.Context + + deps, err := appbuilder. + New(ctx). + WithConfig(). + WithDB(). + WithRepos(). + Build() + if err != nil { + return cli.Exit(err, 1) } + defer deps.Defer() + + rs := deps.Repos found, _, err := rs.FindPkgs(ctx, args.Slice()) if err != nil { diff --git a/internal/cliutils/app_builder/builder.go b/internal/cliutils/app_builder/builder.go new file mode 100644 index 0000000..6ced528 --- /dev/null +++ b/internal/cliutils/app_builder/builder.go @@ -0,0 +1,126 @@ +// ALR - Any Linux Repository +// Copyright (C) 2025 Евгений Храмов +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package appbuilder + +import ( + "context" + "errors" + "log/slog" + + "github.com/leonelquinteros/gotext" + "github.com/urfave/cli/v2" + + "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/repos" +) + +type AppDeps struct { + Cfg *config.ALRConfig + DB *db.Database + Repos *repos.Repos +} + +func (d *AppDeps) Defer() { + if d.DB != nil { + if err := d.DB.Close(); err != nil { + slog.Warn("failed to close db", "err", err) + } + } +} + +type AppBuilder struct { + deps AppDeps + err error + ctx context.Context +} + +func New(ctx context.Context) *AppBuilder { + return &AppBuilder{ctx: ctx} +} + +func (b *AppBuilder) WithConfig() *AppBuilder { + if b.err != nil { + return b + } + + cfg := config.New() + if err := cfg.Load(); err != nil { + slog.Error(gotext.Get("Error loading config"), "err", err) + b.err = cli.Exit("", 1) + return b + } + + b.deps.Cfg = cfg + return b +} + +func (b *AppBuilder) WithDB() *AppBuilder { + if b.err != nil { + return b + } + + cfg := b.deps.Cfg + if cfg == nil { + b.err = errors.New("config is required before initializing DB") + return b + } + + db := db.New(cfg) + if err := db.Init(b.ctx); err != nil { + slog.Error(gotext.Get("Error initialization database"), "err", err) + b.err = cli.Exit("", 1) + return b + } + + b.deps.DB = db + return b +} + +func (b *AppBuilder) WithRepos() *AppBuilder { + if b.err != nil { + return b + } + + 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") + return b + } + + rs := repos.New(cfg, db) + + if cfg.AutoPull() { + if err := rs.Pull(b.ctx, cfg.Repos()); err != nil { + slog.Error(gotext.Get("Error pulling repositories"), "err", err) + b.err = cli.Exit("", 1) + return b + } + } + + b.deps.Repos = rs + + return b +} + +func (b *AppBuilder) Build() (*AppDeps, error) { + if b.err != nil { + return nil, b.err + } + return &b.deps, nil +} diff --git a/internal/translations/default.pot b/internal/translations/default.pot index c19b262..2a9d038 100644 --- a/internal/translations/default.pot +++ b/internal/translations/default.pot @@ -70,43 +70,35 @@ msgstr "" msgid "Error moving the package" msgstr "" -#: fix.go:39 +#: fix.go:37 msgid "Attempt to fix problems with ALR" msgstr "" -#: fix.go:43 -msgid "Can't drop privileges" -msgstr "" - -#: fix.go:57 +#: fix.go:58 msgid "Clearing cache directory" msgstr "" -#: fix.go:62 +#: fix.go:63 msgid "Unable to open cache directory" msgstr "" -#: fix.go:69 +#: fix.go:70 msgid "Unable to read cache directory contents" msgstr "" -#: fix.go:76 +#: fix.go:77 msgid "Unable to remove cache item" msgstr "" -#: fix.go:81 +#: fix.go:82 msgid "Rebuilding cache" msgstr "" -#: fix.go:85 +#: fix.go:86 msgid "Unable to create new cache directory" msgstr "" -#: fix.go:105 -msgid "Error pulling repos" -msgstr "" - -#: fix.go:109 +#: fix.go:101 msgid "Done" msgstr "" @@ -142,35 +134,35 @@ msgstr "" msgid "Show all information, not just for the current distro" msgstr "" -#: info.go:76 +#: info.go:75 msgid "Error getting packages" msgstr "" -#: info.go:85 +#: info.go:84 msgid "Error iterating over packages" msgstr "" -#: info.go:117 +#: info.go:98 msgid "Command info expected at least 1 argument, got %d" msgstr "" -#: info.go:130 +#: info.go:118 msgid "Error finding packages" msgstr "" -#: info.go:146 +#: info.go:134 msgid "Can't detect system language" msgstr "" -#: info.go:156 +#: info.go:144 msgid "Error parsing os-release file" msgstr "" -#: info.go:165 +#: info.go:153 msgid "Error resolving overrides" msgstr "" -#: info.go:174 info.go:180 +#: info.go:162 info.go:168 msgid "Error encoding script variables" msgstr "" @@ -443,6 +435,14 @@ msgstr "" msgid "Error saving config" msgstr "" +#: repo.go:97 repo.go:199 +msgid "Can't drop privileges" +msgstr "" + +#: repo.go:104 repo.go:110 repo.go:219 +msgid "Error pulling repos" +msgstr "" + #: repo.go:122 msgid "Remove an existing repository" msgstr "" @@ -467,35 +467,39 @@ msgstr "" msgid "Pull all repositories that have changed" msgstr "" -#: search.go:37 +#: search.go:36 msgid "Search packages" msgstr "" -#: search.go:43 +#: search.go:42 msgid "Search by name" msgstr "" -#: search.go:48 +#: search.go:47 msgid "Search by description" msgstr "" -#: search.go:53 +#: search.go:52 msgid "Search by repository" msgstr "" -#: search.go:58 +#: search.go:57 msgid "Search by provides" msgstr "" -#: search.go:63 +#: search.go:62 msgid "Format output using a Go template" msgstr "" -#: search.go:95 search.go:112 +#: search.go:96 +msgid "Error while executing search" +msgstr "" + +#: search.go:105 msgid "Error parsing format template" msgstr "" -#: search.go:120 +#: search.go:114 msgid "Error executing template" msgstr "" diff --git a/internal/translations/po/ru/default.po b/internal/translations/po/ru/default.po index b58547b..285a637 100644 --- a/internal/translations/po/ru/default.po +++ b/internal/translations/po/ru/default.po @@ -80,47 +80,39 @@ msgstr "Исполнение build()" msgid "Error moving the package" msgstr "Ошибка при перемещении пакета" -#: fix.go:39 +#: fix.go:37 msgid "Attempt to fix problems with ALR" msgstr "Попытка устранить проблемы с ALR" -#: fix.go:43 -msgid "Can't drop privileges" -msgstr "" - -#: fix.go:57 +#: fix.go:58 #, fuzzy msgid "Clearing cache directory" msgstr "Удаление каталога кэша" -#: fix.go:62 +#: fix.go:63 #, fuzzy msgid "Unable to open cache directory" msgstr "Не удалось удалить каталог кэша" -#: fix.go:69 +#: fix.go:70 #, fuzzy msgid "Unable to read cache directory contents" msgstr "Не удалось удалить каталог кэша" -#: fix.go:76 +#: fix.go:77 #, fuzzy msgid "Unable to remove cache item" msgstr "Не удалось удалить каталог кэша" -#: fix.go:81 +#: fix.go:82 msgid "Rebuilding cache" msgstr "Восстановление кэша" -#: fix.go:85 +#: fix.go:86 msgid "Unable to create new cache directory" msgstr "Не удалось создать новый каталог кэша" -#: fix.go:105 -msgid "Error pulling repos" -msgstr "Ошибка при извлечении репозиториев" - -#: fix.go:109 +#: fix.go:101 msgid "Done" msgstr "Сделано" @@ -156,36 +148,36 @@ msgstr "Отобразить информацию о пакете" msgid "Show all information, not just for the current distro" msgstr "Показывать всю информацию, не только для текущего дистрибутива" -#: info.go:76 +#: info.go:75 msgid "Error getting packages" msgstr "Ошибка при получении пакетов" -#: info.go:85 +#: info.go:84 msgid "Error iterating over packages" msgstr "Ошибка при переборе пакетов" -#: info.go:117 +#: info.go:98 msgid "Command info expected at least 1 argument, got %d" msgstr "Для команды info ожидался хотя бы 1 аргумент, получено %d" -#: info.go:130 +#: info.go:118 msgid "Error finding packages" msgstr "Ошибка при поиске пакетов" -#: info.go:146 +#: info.go:134 #, fuzzy msgid "Can't detect system language" msgstr "Ошибка при парсинге языка системы" -#: info.go:156 +#: info.go:144 msgid "Error parsing os-release file" msgstr "Ошибка при разборе файла выпуска операционной системы" -#: info.go:165 +#: info.go:153 msgid "Error resolving overrides" msgstr "Ошибка устранения переорпеделений" -#: info.go:174 info.go:180 +#: info.go:162 info.go:168 msgid "Error encoding script variables" msgstr "Ошибка кодирования переменных скрита" @@ -466,6 +458,14 @@ msgstr "URL-адрес нового репозитория" msgid "Error saving config" msgstr "Ошибка при кодировании конфигурации" +#: repo.go:97 repo.go:199 +msgid "Can't drop privileges" +msgstr "" + +#: repo.go:104 repo.go:110 repo.go:219 +msgid "Error pulling repos" +msgstr "Ошибка при извлечении репозиториев" + #: repo.go:122 msgid "Remove an existing repository" msgstr "Удалить существующий репозиторий" @@ -490,35 +490,40 @@ msgstr "Ошибка при удалении пакетов из базы дан msgid "Pull all repositories that have changed" msgstr "Скачать все изменённые репозитории" -#: search.go:37 +#: search.go:36 msgid "Search packages" msgstr "Поиск пакетов" -#: search.go:43 +#: search.go:42 msgid "Search by name" msgstr "Искать по имени" -#: search.go:48 +#: search.go:47 msgid "Search by description" msgstr "Искать по описанию" -#: search.go:53 +#: search.go:52 msgid "Search by repository" msgstr "Искать по репозиторию" -#: search.go:58 +#: search.go:57 msgid "Search by provides" msgstr "Иcкать по provides" -#: search.go:63 +#: search.go:62 msgid "Format output using a Go template" msgstr "Формат выходных данных с использованием шаблона Go" -#: search.go:95 search.go:112 +#: search.go:96 +#, fuzzy +msgid "Error while executing search" +msgstr "Ошибка при запуске приложения" + +#: search.go:105 msgid "Error parsing format template" msgstr "Ошибка при разборе шаблона" -#: search.go:120 +#: search.go:114 msgid "Error executing template" msgstr "Ошибка при выполнении шаблона" diff --git a/internal/utils/cmd.go b/internal/utils/cmd.go index bfdd8da..cb10e51 100644 --- a/internal/utils/cmd.go +++ b/internal/utils/cmd.go @@ -80,7 +80,7 @@ func DropCapsToAlrUser() error { } // Returns cli.Exit to -func ExitIfCantDropCapsToAlrUser() error { +func ExitIfCantDropCapsToAlrUser() cli.ExitCoder { err := DropCapsToAlrUser() if err != nil { slog.Debug("dropping capabilities error", "err", err) diff --git a/list.go b/list.go index 4af5d6d..413951a 100644 --- a/list.go +++ b/list.go @@ -28,11 +28,11 @@ import ( "github.com/urfave/cli/v2" "golang.org/x/exp/slices" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/config" + 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/utils" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/build" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager" - "gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos" ) func ListCmd() *cli.Command { @@ -47,29 +47,26 @@ func ListCmd() *cli.Command { }, }, Action: func(c *cli.Context) error { + if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil { + return err + } + ctx := c.Context - cfg := config.New() - err := cfg.Load() - if err != nil { - slog.Error(gotext.Get("Error loading config"), "err", err) - os.Exit(1) - } - db := database.New(cfg) - err = db.Init(ctx) + deps, err := appbuilder. + New(ctx). + WithConfig(). + WithDB(). + // autoPull only + WithRepos(). + Build() if err != nil { - slog.Error(gotext.Get("Error initialization database"), "err", err) - os.Exit(1) + return err } - rs := repos.New(cfg, db) + defer deps.Defer() - if cfg.AutoPull() { - err = rs.Pull(ctx, cfg.Repos()) - if err != nil { - slog.Error(gotext.Get("Error pulling repositories"), "err", err) - os.Exit(1) - } - } + cfg := deps.Cfg + db := deps.DB where := "true" args := []any(nil) diff --git a/search.go b/search.go index 3e874ca..dda4757 100644 --- a/search.go +++ b/search.go @@ -25,8 +25,7 @@ import ( "github.com/leonelquinteros/gotext" "github.com/urfave/cli/v2" - "gitea.plemya-x.ru/Plemya-x/ALR/internal/config" - database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db" + appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/search" ) @@ -64,38 +63,23 @@ func SearchCmd() *cli.Command { }, }, Action: func(c *cli.Context) error { - err := utils.ExitIfCantDropCapsToAlrUser() - if err != nil { + if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil { return err } ctx := c.Context - cfg := config.New() - err = cfg.Load() + deps, err := appbuilder. + New(ctx). + WithConfig(). + WithDB(). + Build() if err != nil { - slog.Error(gotext.Get("Error loading config")) - return cli.Exit(err, 1) + return err } + defer deps.Defer() - db := database.New(cfg) - err = db.Init(ctx) - defer db.Close() - - if err != nil { - slog.Error(gotext.Get("Error initialization database"), "err", err) - return cli.Exit(err, 1) - } - - format := c.String("format") - var tmpl *template.Template - if format != "" { - tmpl, err = template.New("format").Parse(format) - if err != nil { - slog.Error(gotext.Get("Error parsing format template")) - return cli.Exit(err, 1) - } - } + db := deps.DB s := search.New(db) @@ -109,10 +93,20 @@ func SearchCmd() *cli.Command { Build(), ) if err != nil { - slog.Error(gotext.Get("Error parsing format template")) + slog.Error(gotext.Get("Error while executing search")) return cli.Exit(err, 1) } + format := c.String("format") + var tmpl *template.Template + if format != "" { + tmpl, err = template.New("format").Parse(format) + if err != nil { + slog.Error(gotext.Get("Error parsing format template")) + return cli.Exit(err, 1) + } + } + for _, dbPkg := range packages { if tmpl != nil { err = tmpl.Execute(os.Stdout, dbPkg)