diff --git a/Makefile b/Makefile index ae74c6f..09b742b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ NAME := alr GIT_VERSION = $(shell git describe --tags ) - +IGNORE_ROOT_CHECK ?= 0 DESTDIR ?= PREFIX ?= /usr/local BIN := ./$(NAME) @@ -24,8 +24,9 @@ $(BIN): go build -ldflags="-X 'gitea.plemya-x.ru/Plemya-x/ALR/internal/config.Version=$(GIT_VERSION)'" -o $@ check-no-root: - @if [[ "$$(whoami)" == 'root' ]]; then \ + @if [[ "$(IGNORE_ROOT_CHECK)" != "1" ]] && [[ "$$(whoami)" == 'root' ]]; then \ echo "This target shouldn't run as root" 1>&2; \ + echo "Set IGNORE_ROOT_CHECK=1 to override" 1>&2; \ exit 1; \ fi diff --git a/assets/coverage-badge.svg b/assets/coverage-badge.svg index 776bb24..b891de3 100644 --- a/assets/coverage-badge.svg +++ b/assets/coverage-badge.svg @@ -11,7 +11,7 @@ coverage coverage - 17.1% - 17.1% + 17.0% + 17.0% diff --git a/assets/i18n-ru-badge.svg b/assets/i18n-ru-badge.svg index 2a5d418..56d2e1c 100644 --- a/assets/i18n-ru-badge.svg +++ b/assets/i18n-ru-badge.svg @@ -12,7 +12,7 @@ ru translate ru translate - 100.00% - 100.00% + 96.00% + 96.00% diff --git a/internal/cliutils/utils.go b/internal/cliutils/utils.go index 24c1760..010d2e0 100644 --- a/internal/cliutils/utils.go +++ b/internal/cliutils/utils.go @@ -21,6 +21,7 @@ import ( "fmt" "log/slog" + "github.com/leonelquinteros/gotext" "github.com/urfave/cli/v2" ) @@ -61,3 +62,11 @@ func FormatCliExitWithCode(msg string, err error, exitCode int) cli.ExitCoder { } return cli.Exit(fmt.Errorf("%s: %w", msg, err), exitCode) } + +func WarnLegacyCommand(newSyntax string) { + slog.Warn( + gotext.Get( + "This command is deprecated and would be removed in the future, use \"%s\" instead!", newSyntax, + ), + ) +} diff --git a/internal/translations/default.pot b/internal/translations/default.pot index c39fb78..c36c01d 100644 --- a/internal/translations/default.pot +++ b/internal/translations/default.pot @@ -278,6 +278,12 @@ msgstr "" msgid "OPTIONS" msgstr "" +#: internal/cliutils/utils.go:69 +msgid "" +"This command is deprecated and would be removed in the future, use \"%s\" " +"instead!" +msgstr "" + #: internal/db/db.go:137 msgid "Database version mismatch; resetting" msgstr "" @@ -363,11 +369,11 @@ msgstr "" msgid "Enable interactive questions and prompts" msgstr "" -#: main.go:145 +#: main.go:146 msgid "Show help" msgstr "" -#: main.go:149 +#: main.go:150 msgid "Error while running app" msgstr "" @@ -451,48 +457,60 @@ msgid "" "updating ALR if something doesn't work." msgstr "" -#: repo.go:39 -msgid "Add a new repository" +#: refresh.go:30 +msgid "Pull all repositories that have changed" msgstr "" -#: repo.go:46 -msgid "Name of the new repo" +#: repo.go:39 +msgid "Manage repos" +msgstr "" + +#: repo.go:50 repo.go:220 +msgid "Remove an existing repository" msgstr "" #: repo.go:52 -msgid "URL of the new repo" +msgid "" msgstr "" -#: repo.go:75 -msgid "Repo \"%s\" already exists" +#: repo.go:82 +msgid "Repo \"%s\" does not exist" msgstr "" -#: repo.go:86 repo.go:159 +#: repo.go:89 +msgid "Error removing repo directory" +msgstr "" + +#: repo.go:93 repo.go:160 msgid "Error saving config" msgstr "" #: repo.go:112 -msgid "Remove an existing repository" -msgstr "" - -#: repo.go:119 -msgid "Name of the repo to be deleted" -msgstr "" - -#: repo.go:148 -msgid "Repo \"%s\" does not exist" -msgstr "" - -#: repo.go:155 -msgid "Error removing repo directory" -msgstr "" - -#: repo.go:178 msgid "Error removing packages from database" msgstr "" -#: repo.go:189 -msgid "Pull all repositories that have changed" +#: repo.go:123 repo.go:190 +msgid "Add a new repository" +msgstr "" + +#: repo.go:124 +msgid " " +msgstr "" + +#: repo.go:149 +msgid "Repo \"%s\" already exists" +msgstr "" + +#: repo.go:197 +msgid "Name of the new repo" +msgstr "" + +#: repo.go:203 +msgid "URL of the new repo" +msgstr "" + +#: repo.go:227 +msgid "Name of the repo to be deleted" msgstr "" #: search.go:40 diff --git a/internal/translations/po/ru/default.po b/internal/translations/po/ru/default.po index 9d7fc9c..26217bc 100644 --- a/internal/translations/po/ru/default.po +++ b/internal/translations/po/ru/default.po @@ -12,8 +12,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " -"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Gtranslator 48.0\n" #: build.go:42 @@ -285,6 +285,12 @@ msgstr "КАТЕГОРИЯ" msgid "OPTIONS" msgstr "ПАРАМЕТРЫ" +#: internal/cliutils/utils.go:69 +msgid "" +"This command is deprecated and would be removed in the future, use \"%s\" " +"instead!" +msgstr "" + #: internal/db/db.go:137 msgid "Database version mismatch; resetting" msgstr "Несоответствие версий базы данных; сброс настроек" @@ -371,11 +377,11 @@ msgstr "Аргументы, которые будут переданы мене msgid "Enable interactive questions and prompts" msgstr "Включение интерактивных вопросов и запросов" -#: main.go:145 +#: main.go:146 msgid "Show help" msgstr "Показать справку" -#: main.go:149 +#: main.go:150 msgid "Error while running app" msgstr "Ошибка при запуске приложения" @@ -465,49 +471,61 @@ msgstr "" "Минимальная версия ALR для ALR-репозитория выше текущей версии. Попробуйте " "обновить ALR, если что-то не работает." -#: repo.go:39 -msgid "Add a new repository" -msgstr "Добавить новый репозиторий" +#: refresh.go:30 +msgid "Pull all repositories that have changed" +msgstr "Скачать все изменённые репозитории" -#: repo.go:46 -msgid "Name of the new repo" -msgstr "Название нового репозитория" +#: repo.go:39 +msgid "Manage repos" +msgstr "" + +#: repo.go:50 repo.go:220 +msgid "Remove an existing repository" +msgstr "Удалить существующий репозиторий" #: repo.go:52 -msgid "URL of the new repo" -msgstr "URL-адрес нового репозитория" +msgid "" +msgstr "" -#: repo.go:75 -msgid "Repo \"%s\" already exists" -msgstr "Репозиторий \"%s\" уже существует" +#: repo.go:82 +msgid "Repo \"%s\" does not exist" +msgstr "Репозитория \"%s\" не существует" -#: repo.go:86 repo.go:159 +#: repo.go:89 +msgid "Error removing repo directory" +msgstr "Ошибка при удалении каталога репозитория" + +#: repo.go:93 repo.go:160 msgid "Error saving config" msgstr "Ошибка при сохранении конфигурации" #: repo.go:112 -msgid "Remove an existing repository" -msgstr "Удалить существующий репозиторий" - -#: repo.go:119 -msgid "Name of the repo to be deleted" -msgstr "Название репозитория удалён" - -#: repo.go:148 -msgid "Repo \"%s\" does not exist" -msgstr "Репозитория \"%s\" не существует" - -#: repo.go:155 -msgid "Error removing repo directory" -msgstr "Ошибка при удалении каталога репозитория" - -#: repo.go:178 msgid "Error removing packages from database" msgstr "Ошибка при удалении пакетов из базы данных" -#: repo.go:189 -msgid "Pull all repositories that have changed" -msgstr "Скачать все изменённые репозитории" +#: repo.go:123 repo.go:190 +msgid "Add a new repository" +msgstr "Добавить новый репозиторий" + +#: repo.go:124 +msgid " " +msgstr "" + +#: repo.go:149 +msgid "Repo \"%s\" already exists" +msgstr "Репозиторий \"%s\" уже существует" + +#: repo.go:197 +msgid "Name of the new repo" +msgstr "Название нового репозитория" + +#: repo.go:203 +msgid "URL of the new repo" +msgstr "URL-адрес нового репозитория" + +#: repo.go:227 +msgid "Name of the repo to be deleted" +msgstr "Название репозитория удалён" #: search.go:40 msgid "Search packages" diff --git a/main.go b/main.go index 53c63bc..80a0315 100644 --- a/main.go +++ b/main.go @@ -74,14 +74,15 @@ func GetApp() *cli.App { InfoCmd(), ListCmd(), BuildCmd(), - AddRepoCmd(), - RemoveRepoCmd(), + LegacyAddRepoCmd(), + LegacyRemoveRepoCmd(), RefreshCmd(), FixCmd(), GenCmd(), HelperCmd(), VersionCmd(), SearchCmd(), + RepoCmd(), // Internal commands InternalBuildCmd(), InternalInstallCmd(), diff --git a/refresh.go b/refresh.go new file mode 100644 index 0000000..6b031dd --- /dev/null +++ b/refresh.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 main + +import ( + "github.com/leonelquinteros/gotext" + "github.com/urfave/cli/v2" + + appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder" + "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" +) + +func RefreshCmd() *cli.Command { + return &cli.Command{ + Name: "refresh", + Usage: gotext.Get("Pull all repositories that have changed"), + Aliases: []string{"ref"}, + Action: func(c *cli.Context) error { + if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil { + return err + } + + ctx := c.Context + + deps, err := appbuilder. + New(ctx). + WithConfig(). + WithDB(). + WithReposForcePull(). + Build() + if err != nil { + return err + } + defer deps.Defer() + return nil + }, + } +} diff --git a/repo.go b/repo.go index c679c95..c6b25f5 100644 --- a/repo.go +++ b/repo.go @@ -33,96 +33,30 @@ import ( "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" ) -func AddRepoCmd() *cli.Command { +func RepoCmd() *cli.Command { return &cli.Command{ - Name: "addrepo", - Usage: gotext.Get("Add a new repository"), - Aliases: []string{"ar"}, - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "name", - Aliases: []string{"n"}, - Required: true, - Usage: gotext.Get("Name of the new repo"), - }, - &cli.StringFlag{ - Name: "url", - Aliases: []string{"u"}, - Required: true, - Usage: gotext.Get("URL of the new repo"), - }, + Name: "repo", + Usage: gotext.Get("Manage repos"), + Subcommands: []*cli.Command{ + RemoveRepoCmd(), + AddRepoCmd(), }, - Action: utils.RootNeededAction(func(c *cli.Context) error { - name := c.String("name") - repoURL := c.String("url") - - ctx := c.Context - - deps, err := appbuilder. - New(ctx). - WithConfig(). - Build() - if err != nil { - return err - } - defer deps.Defer() - - cfg := deps.Cfg - - reposSlice := cfg.Repos() - for _, repo := range reposSlice { - if repo.URL == repoURL || repo.Name == name { - return cliutils.FormatCliExit(gotext.Get("Repo \"%s\" already exists", repo.Name), nil) - } - } - reposSlice = append(reposSlice, types.Repo{ - Name: name, - URL: repoURL, - }) - cfg.SetRepos(reposSlice) - - err = cfg.SaveUserConfig() - if err != nil { - return cliutils.FormatCliExit(gotext.Get("Error saving config"), err) - } - - if err := utils.ExitIfCantDropCapsToAlrUserNoPrivs(); err != nil { - return err - } - - deps, err = appbuilder. - New(ctx). - UseConfig(cfg). - WithDB(). - WithReposForcePull(). - Build() - if err != nil { - return err - } - defer deps.Defer() - - return nil - }), } } func RemoveRepoCmd() *cli.Command { return &cli.Command{ - Name: "removerepo", - Usage: gotext.Get("Remove an existing repository"), - Aliases: []string{"rr"}, - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "name", - Aliases: []string{"n"}, - Required: true, - Usage: gotext.Get("Name of the repo to be deleted"), - }, - }, + Name: "remove", + Usage: gotext.Get("Remove an existing repository"), + Aliases: []string{"rm"}, + ArgsUsage: gotext.Get(""), Action: utils.RootNeededAction(func(c *cli.Context) error { - ctx := c.Context + if c.Args().Len() < 1 { + return cliutils.FormatCliExit("missing args", nil) + } + name := c.Args().Get(0) - name := c.String("name") + ctx := c.Context deps, err := appbuilder. New(ctx). @@ -183,21 +117,56 @@ func RemoveRepoCmd() *cli.Command { } } -func RefreshCmd() *cli.Command { +func AddRepoCmd() *cli.Command { return &cli.Command{ - Name: "refresh", - Usage: gotext.Get("Pull all repositories that have changed"), - Aliases: []string{"ref"}, - Action: func(c *cli.Context) error { - if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil { - return err + Name: "add", + Usage: gotext.Get("Add a new repository"), + ArgsUsage: gotext.Get(" "), + Action: utils.RootNeededAction(func(c *cli.Context) error { + if c.Args().Len() < 2 { + return cliutils.FormatCliExit("missing args", nil) } + name := c.Args().Get(0) + repoURL := c.Args().Get(1) + ctx := c.Context deps, err := appbuilder. New(ctx). WithConfig(). + Build() + if err != nil { + return err + } + defer deps.Defer() + + cfg := deps.Cfg + + reposSlice := cfg.Repos() + for _, repo := range reposSlice { + if repo.URL == repoURL || repo.Name == name { + return cliutils.FormatCliExit(gotext.Get("Repo \"%s\" already exists", repo.Name), nil) + } + } + reposSlice = append(reposSlice, types.Repo{ + Name: name, + URL: repoURL, + }) + cfg.SetRepos(reposSlice) + + err = cfg.SaveUserConfig() + if err != nil { + return cliutils.FormatCliExit(gotext.Get("Error saving config"), err) + } + + if err := utils.ExitIfCantDropCapsToAlrUserNoPrivs(); err != nil { + return err + } + + deps, err = appbuilder. + New(ctx). + UseConfig(cfg). WithDB(). WithReposForcePull(). Build() @@ -205,7 +174,62 @@ func RefreshCmd() *cli.Command { return err } defer deps.Defer() + return nil - }, + }), + } +} + +// TODO: remove +// +// Deprecated: use "alr repo add" +func LegacyAddRepoCmd() *cli.Command { + return &cli.Command{ + Hidden: true, + Name: "addrepo", + Usage: gotext.Get("Add a new repository"), + Aliases: []string{"ar"}, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "name", + Aliases: []string{"n"}, + Required: true, + Usage: gotext.Get("Name of the new repo"), + }, + &cli.StringFlag{ + Name: "url", + Aliases: []string{"u"}, + Required: true, + Usage: gotext.Get("URL of the new repo"), + }, + }, + Action: utils.RootNeededAction(func(c *cli.Context) error { + cliutils.WarnLegacyCommand("alr repo add ") + return c.App.RunContext(c.Context, []string{"", "repo", "add", c.String("name"), c.String("url")}) + }), + } +} + +// TODO: remove +// +// Deprecated: use "alr repo rm" +func LegacyRemoveRepoCmd() *cli.Command { + return &cli.Command{ + Hidden: true, + Name: "removerepo", + Usage: gotext.Get("Remove an existing repository"), + Aliases: []string{"rr"}, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "name", + Aliases: []string{"n"}, + Required: true, + Usage: gotext.Get("Name of the repo to be deleted"), + }, + }, + Action: utils.RootNeededAction(func(c *cli.Context) error { + cliutils.WarnLegacyCommand("alr repo remove ") + return c.App.RunContext(c.Context, []string{"", "repo", "remove", c.String("name")}) + }), } }