add --upgradable option for list
All checks were successful
Pre-commit / pre-commit (pull_request) Successful in 1m36s

This commit is contained in:
2025-05-13 23:26:12 +03:00
parent 443e481561
commit 40ec0ac6e1
8 changed files with 198 additions and 43 deletions

View File

@ -76,7 +76,9 @@ test-coverage:
update-deps-cve:
bash scripts/update-deps-cve.sh
e2e-test: clean build
prepare-for-e2e-test: clean build
rm -f ./e2e-tests/alr
cp alr e2e-tests
e2e-test: prepare-for-e2e-test
go test -tags=e2e ./...

View File

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

Before

Width:  |  Height:  |  Size: 926 B

After

Width:  |  Height:  |  Size: 926 B

View File

@ -175,6 +175,11 @@ func dockerMultipleRun(t *testing.T, name string, ids []string, f func(t *testin
})
}
func simpleExec(t *testing.T, r e2e.Runnable, cmd string, args ...string) {
err := r.Exec(e2e.NewCommand(cmd, args...))
assert.NoError(t, err)
}
func runTestCommands(t *testing.T, r e2e.Runnable, timeout time.Duration, expects []expect.Batcher) {
exp, _, err, _ := e2eSpawn(
r,

View File

@ -0,0 +1,50 @@
// ALR - Any Linux Repository
// Copyright (C) 2025 The ALR Authors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//go:build e2e
package e2etests_test
import (
"testing"
"github.com/efficientgo/e2e"
)
func TestE2EIssue74Upgradable(t *testing.T) {
dockerMultipleRun(
t,
"issue-74-upgradable",
COMMON_SYSTEMS,
func(t *testing.T, r e2e.Runnable) {
simpleExec(t, r, "sudo",
"alr",
"addrepo",
"--name",
"alr-repo",
"--url",
REPO_FOR_E2E_TESTS,
)
simpleExec(t, r, "sudo", "sh", "-c", "sed -i 's/ref = .*/ref = \"bd26236cd7\"/' /etc/alr/alr.toml")
simpleExec(t, r, "alr", "ref")
simpleExec(t, r, "sudo", "alr", "in", "bar-pkg")
simpleExec(t, r, "sh", "-c", "test $(alr list -U | wc -l) -eq 0 || exit 1")
simpleExec(t, r, "sudo", "sh", "-c", "sed -i 's/ref = .*/ref = \"d9a3541561\"/' /etc/alr/alr.toml")
simpleExec(t, r, "sudo", "alr", "ref")
simpleExec(t, r, "sh", "-c", "test $(alr list -U | wc -l) -eq 1 || exit 1")
},
)
}

View File

@ -327,10 +327,30 @@ msgstr ""
msgid "You need to be root to perform this action"
msgstr ""
#: list.go:41
#: list.go:43
msgid "List ALR repo packages"
msgstr ""
#: list.go:57
msgid "Format output using a Go template"
msgstr ""
#: list.go:89
msgid "Error getting packages for upgrade"
msgstr ""
#: list.go:92
msgid "No packages for upgrade"
msgstr ""
#: list.go:102 list.go:187
msgid "Error parsing format template"
msgstr ""
#: list.go:108 list.go:191
msgid "Error executing template"
msgstr ""
#: main.go:45
msgid "Print the current ALR version and exit"
msgstr ""
@ -495,22 +515,10 @@ msgstr ""
msgid "Search by provides"
msgstr ""
#: search.go:71
msgid "Format output using a Go template"
msgstr ""
#: search.go:130
msgid "Error while executing search"
msgstr ""
#: search.go:138
msgid "Error parsing format template"
msgstr ""
#: search.go:153
msgid "Error executing template"
msgstr ""
#: upgrade.go:47
msgid "Upgrade all installed packages"
msgstr ""

View File

@ -5,15 +5,15 @@
msgid ""
msgstr ""
"Project-Id-Version: unnamed project\n"
"PO-Revision-Date: 2025-04-27 18:27+0300\n"
"PO-Revision-Date: 2025-05-13 23:24+0300\n"
"Last-Translator: Maxim Slipenko <maks1ms@alt-gnome.ru>\n"
"Language-Team: Russian\n"
"Language: ru\n"
"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
@ -335,10 +335,30 @@ msgstr "Вы должны быть членом %s чтобы выполнить
msgid "You need to be root to perform this action"
msgstr "Вы должны быть root чтобы выполнить это"
#: list.go:41
#: list.go:43
msgid "List ALR repo packages"
msgstr "Список пакетов репозитория ALR"
#: list.go:57
msgid "Format output using a Go template"
msgstr "Формат выходных данных с использованием шаблона Go"
#: list.go:89
msgid "Error getting packages for upgrade"
msgstr "Ошибка при получении пакетов для обновления"
#: list.go:92
msgid "No packages for upgrade"
msgstr "Нет пакетов к обновлению"
#: list.go:102 list.go:187
msgid "Error parsing format template"
msgstr "Ошибка при разборе шаблона"
#: list.go:108 list.go:191
msgid "Error executing template"
msgstr "Ошибка при выполнении шаблона"
#: main.go:45
msgid "Print the current ALR version and exit"
msgstr "Показать текущую версию ALR и выйти"
@ -509,22 +529,10 @@ msgstr "Искать по репозиторию"
msgid "Search by provides"
msgstr "Иcкать по provides"
#: search.go:71
msgid "Format output using a Go template"
msgstr "Формат выходных данных с использованием шаблона Go"
#: search.go:130
msgid "Error while executing search"
msgstr "Ошибка при выполнении поиска"
#: search.go:138
msgid "Error parsing format template"
msgstr "Ошибка при разборе шаблона"
#: search.go:153
msgid "Error executing template"
msgstr "Ошибка при выполнении шаблона"
#: upgrade.go:47
msgid "Upgrade all installed packages"
msgstr "Обновить все установленные пакеты"

72
list.go
View File

@ -22,10 +22,12 @@ package main
import (
"fmt"
"log/slog"
"os"
"slices"
"text/template"
"github.com/leonelquinteros/gotext"
"github.com/urfave/cli/v2"
"golang.org/x/exp/slices"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
@ -45,6 +47,15 @@ func ListCmd() *cli.Command {
Name: "installed",
Aliases: []string{"I"},
},
&cli.BoolFlag{
Name: "upgradable",
Aliases: []string{"U"},
},
&cli.StringFlag{
Name: "format",
Aliases: []string{"f"},
Usage: gotext.Get("Format output using a Go template"),
},
},
Action: func(c *cli.Context) error {
if err := utils.ExitIfCantDropCapsToAlrUserNoPrivs(); err != nil {
@ -57,8 +68,10 @@ func ListCmd() *cli.Command {
New(ctx).
WithConfig().
WithDB().
WithManager().
// autoPull only
WithRepos().
WithDistroInfo().
Build()
if err != nil {
return err
@ -67,6 +80,39 @@ func ListCmd() *cli.Command {
cfg := deps.Cfg
db := deps.DB
mgr := deps.Manager
info := deps.Info
if c.Bool("upgradable") {
updates, err := checkForUpdates(ctx, mgr, db, info)
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error getting packages for upgrade"), err)
}
if len(updates) == 0 {
slog.Info(gotext.Get("No packages for upgrade"))
return nil
}
format := c.String("format")
if format == "" {
format = "{{.Package.Repository}}/{{.Package.Name}} {{.FromVersion}} -> {{.ToVersion}}\n"
}
tmpl, err := template.New("format").Parse(format)
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error parsing format template"), err)
}
for _, updateInfo := range updates {
err = tmpl.Execute(os.Stdout, updateInfo)
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error executing template"), err)
}
}
return nil
}
// TODO: refactor code below
where := "true"
args := []any(nil)
@ -115,17 +161,35 @@ func ListCmd() *cli.Command {
continue
}
version := pkg.Version
type packageInfo struct {
Package *database.Package
Version string
}
pkgInfo := &packageInfo{}
pkgInfo.Package = &pkg
pkgInfo.Version = pkg.Version
if c.Bool("installed") {
instVersion, ok := installedAlrPackages[fmt.Sprintf("%s/%s", pkg.Repository, pkg.Name)]
if !ok {
continue
} else {
version = instVersion
pkgInfo.Version = instVersion
}
}
fmt.Printf("%s/%s %s\n", pkg.Repository, pkg.Name, version)
format := c.String("format")
if format == "" {
format = "{{.Package.Repository}}/{{.Package.Name}} {{.Version}}\n"
}
tmpl, err := template.New("format").Parse(format)
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error parsing format template"), err)
}
err = tmpl.Execute(os.Stdout, pkg)
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error executing template"), err)
}
}
return nil

View File

@ -116,7 +116,7 @@ func UpgradeCmd() *cli.Command {
Info: deps.Info,
PkgFormat_: build.GetPkgFormat(deps.Manager),
},
updates,
mapUptatesInfoToPackages(updates),
)
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error checking for updates"), err)
@ -130,12 +130,27 @@ func UpgradeCmd() *cli.Command {
}
}
func mapUptatesInfoToPackages(updates []UpdateInfo) []database.Package {
var pkgs []database.Package
for _, info := range updates {
pkgs = append(pkgs, *info.Package)
}
return pkgs
}
type UpdateInfo struct {
Package *database.Package
FromVersion string
ToVersion string
}
func checkForUpdates(
ctx context.Context,
mgr manager.Manager,
db *database.Database,
info *distro.OSRelease,
) ([]database.Package, error) {
) ([]UpdateInfo, error) {
installed, err := mgr.ListInstalled(nil)
if err != nil {
return nil, err
@ -145,7 +160,7 @@ func checkForUpdates(
s := search.New(db)
var out []database.Package
var out []UpdateInfo
for _, pkgName := range pkgNames {
matches := build.RegexpALRPackageName.FindStringSubmatch(pkgName)
if matches != nil {
@ -179,10 +194,13 @@ func checkForUpdates(
}
c := vercmp.Compare(repoVer, installed[pkgName])
if c == 0 || c == -1 {
continue
} else if c == 1 {
out = append(out, pkg)
if c == 1 {
out = append(out, UpdateInfo{
Package: &pkg,
FromVersion: installed[pkgName],
ToVersion: repoVer,
})
}
}