feat: add group and summary fields #69

Merged
xpamych merged 4 commits from Maks1mS/ALR:add-new-fileds into master 2025-04-20 06:45:42 +00:00
10 changed files with 179 additions and 55 deletions
Showing only changes of commit c51d1d9202 - Show all commits

@ -113,6 +113,10 @@ var AUTOREQ_AUTOPROV_SYSTEMS []string = []string{
"fedora-41", "fedora-41",
} }
var RPM_SYSTEMS []string = []string{
"fedora-41",
}
var COMMON_SYSTEMS []string = []string{ var COMMON_SYSTEMS []string = []string{
"ubuntu-24.04", "ubuntu-24.04",
} }

@ -0,0 +1,56 @@
// 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 <http://www.gnu.org/licenses/>.
//go:build e2e
package e2etests_test
import (
"testing"
"github.com/alecthomas/assert/v2"
"github.com/efficientgo/e2e"
)
func TestE2EGroupAndSummaryField(t *testing.T) {
dockerMultipleRun(
t,
"group-and-summary-field",
RPM_SYSTEMS,
func(t *testing.T, r e2e.Runnable) {
err := r.Exec(e2e.NewCommand(
"sudo",
"alr",
"addrepo",
"--name",
"alr-repo",
"--url",
"https://gitea.plemya-x.ru/Maks1mS/repo-for-tests.git",
))
assert.NoError(t, err)
err = r.Exec(e2e.NewCommand(
"sh", "-c", "alr search --name test-group-and-summary --format \"{{.Group}}\" | grep ^System/Base$",
))
assert.NoError(t, err)
err = r.Exec(e2e.NewCommand(
"sh", "-c", "alr search --name test-group-and-summary --format \"{{.Summary}}\" | grep \"^Custom summary$\"",
))
assert.NoError(t, err)
},
)
}

@ -31,7 +31,7 @@ import (
// CurrentVersion is the current version of the database. // CurrentVersion is the current version of the database.
// The database is reset if its version doesn't match this. // The database is reset if its version doesn't match this.
const CurrentVersion = 3 const CurrentVersion = 4
// Package is a ALR package's database representation // Package is a ALR package's database representation
type Package struct { type Package struct {
@ -40,7 +40,9 @@ type Package struct {
Version string `sh:"version,required" db:"version"` Version string `sh:"version,required" db:"version"`
Release int `sh:"release,required" db:"release"` Release int `sh:"release,required" db:"release"`
Epoch uint `sh:"epoch" db:"epoch"` Epoch uint `sh:"epoch" db:"epoch"`
Summary JSON[map[string]string] `db:"summary"`
Description JSON[map[string]string] `db:"description"` Description JSON[map[string]string] `db:"description"`
Group JSON[map[string]string] `db:"group_name"`
Homepage JSON[map[string]string] `db:"homepage"` Homepage JSON[map[string]string] `db:"homepage"`
Maintainer JSON[map[string]string] `db:"maintainer"` Maintainer JSON[map[string]string] `db:"maintainer"`
Architectures JSON[[]string] `sh:"architectures" db:"architectures"` Architectures JSON[[]string] `sh:"architectures" db:"architectures"`
@ -106,7 +108,9 @@ func (d *Database) initDB(ctx context.Context) error {
version TEXT NOT NULL, version TEXT NOT NULL,
release INT NOT NULL, release INT NOT NULL,
epoch INT, 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')), 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')), 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')), 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')), architectures TEXT CHECK(architectures = 'null' OR (JSON_VALID(architectures) AND JSON_TYPE(architectures) = 'array')),
@ -204,7 +208,9 @@ func (d *Database) InsertPackage(ctx context.Context, pkg Package) error {
version, version,
release, release,
epoch, epoch,
summary,
description, description,
group_name,
homepage, homepage,
maintainer, maintainer,
architectures, architectures,
@ -222,7 +228,9 @@ func (d *Database) InsertPackage(ctx context.Context, pkg Package) error {
:version, :version,
:release, :release,
:epoch, :epoch,
:summary,
:description, :description,
:group_name,
:homepage, :homepage,
:maintainer, :maintainer,
:architectures, :architectures,

@ -157,6 +157,8 @@ type ResolvedPackage struct {
Version string `sh:"version"` Version string `sh:"version"`
Release int `sh:"release"` Release int `sh:"release"`
Epoch uint `sh:"epoch"` Epoch uint `sh:"epoch"`
Group string `db:"group_name"`
Summary string `db:"summary"`
Description string `db:"description"` Description string `db:"description"`
Homepage string `db:"homepage"` Homepage string `db:"homepage"`
Maintainer string `db:"maintainer"` Maintainer string `db:"maintainer"`

@ -274,11 +274,11 @@ msgstr ""
msgid "OPTIONS" msgid "OPTIONS"
msgstr "" msgstr ""
#: internal/db/db.go:133 #: internal/db/db.go:137
msgid "Database version mismatch; resetting" msgid "Database version mismatch; resetting"
msgstr "" msgstr ""
#: internal/db/db.go:140 #: internal/db/db.go:144
msgid "" msgid ""
"Database version does not exist. Run alr fix if something isn't working." "Database version does not exist. Run alr fix if something isn't working."
msgstr "" msgstr ""
@ -397,15 +397,15 @@ msgstr ""
msgid "Building package metadata" msgid "Building package metadata"
msgstr "" msgstr ""
#: pkg/build/script_executor.go:356 #: pkg/build/script_executor.go:368
msgid "Executing prepare()" msgid "Executing prepare()"
msgstr "" msgstr ""
#: pkg/build/script_executor.go:365 #: pkg/build/script_executor.go:377
msgid "Executing build()" msgid "Executing build()"
msgstr "" msgstr ""
#: pkg/build/script_executor.go:394 pkg/build/script_executor.go:414 #: pkg/build/script_executor.go:406 pkg/build/script_executor.go:426
msgid "Executing %s()" msgid "Executing %s()"
msgstr "" msgstr ""
@ -471,39 +471,39 @@ msgstr ""
msgid "Pull all repositories that have changed" msgid "Pull all repositories that have changed"
msgstr "" msgstr ""
#: search.go:36 #: search.go:40
msgid "Search packages" msgid "Search packages"
msgstr "" msgstr ""
#: search.go:42 #: search.go:51
msgid "Search by name" msgid "Search by name"
msgstr "" msgstr ""
#: search.go:47 #: search.go:56
msgid "Search by description" msgid "Search by description"
msgstr "" msgstr ""
#: search.go:52 #: search.go:61
msgid "Search by repository" msgid "Search by repository"
msgstr "" msgstr ""
#: search.go:57 #: search.go:66
msgid "Search by provides" msgid "Search by provides"
msgstr "" msgstr ""
#: search.go:62 #: search.go:71
msgid "Format output using a Go template" msgid "Format output using a Go template"
msgstr "" msgstr ""
#: search.go:96 #: search.go:130
msgid "Error while executing search" msgid "Error while executing search"
msgstr "" msgstr ""
#: search.go:104 #: search.go:138
msgid "Error parsing format template" msgid "Error parsing format template"
msgstr "" msgstr ""
#: search.go:112 #: search.go:153
msgid "Error executing template" msgid "Error executing template"
msgstr "" msgstr ""

@ -12,8 +12,8 @@ msgstr ""
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Gtranslator 48.0\n" "X-Generator: Gtranslator 48.0\n"
#: build.go:42 #: build.go:42
@ -281,11 +281,11 @@ msgstr "КАТЕГОРИЯ"
msgid "OPTIONS" msgid "OPTIONS"
msgstr "ПАРАМЕТРЫ" msgstr "ПАРАМЕТРЫ"
#: internal/db/db.go:133 #: internal/db/db.go:137
msgid "Database version mismatch; resetting" msgid "Database version mismatch; resetting"
msgstr "Несоответствие версий базы данных; сброс настроек" msgstr "Несоответствие версий базы данных; сброс настроек"
#: internal/db/db.go:140 #: internal/db/db.go:144
msgid "" msgid ""
"Database version does not exist. Run alr fix if something isn't working." "Database version does not exist. Run alr fix if something isn't working."
msgstr "" msgstr ""
@ -409,15 +409,15 @@ msgstr ""
msgid "Building package metadata" msgid "Building package metadata"
msgstr "Сборка метаданных пакета" msgstr "Сборка метаданных пакета"
#: pkg/build/script_executor.go:356 #: pkg/build/script_executor.go:368
msgid "Executing prepare()" msgid "Executing prepare()"
msgstr "Выполнение prepare()" msgstr "Выполнение prepare()"
#: pkg/build/script_executor.go:365 #: pkg/build/script_executor.go:377
msgid "Executing build()" msgid "Executing build()"
msgstr "Выполнение build()" msgstr "Выполнение build()"
#: pkg/build/script_executor.go:394 pkg/build/script_executor.go:414 #: pkg/build/script_executor.go:406 pkg/build/script_executor.go:426
msgid "Executing %s()" msgid "Executing %s()"
msgstr "Выполнение %s()" msgstr "Выполнение %s()"
@ -485,39 +485,39 @@ msgstr "Ошибка при удалении пакетов из базы дан
msgid "Pull all repositories that have changed" msgid "Pull all repositories that have changed"
msgstr "Скачать все изменённые репозитории" msgstr "Скачать все изменённые репозитории"
#: search.go:36 #: search.go:40
msgid "Search packages" msgid "Search packages"
msgstr "Поиск пакетов" msgstr "Поиск пакетов"
#: search.go:42 #: search.go:51
msgid "Search by name" msgid "Search by name"
msgstr "Искать по имени" msgstr "Искать по имени"
#: search.go:47 #: search.go:56
msgid "Search by description" msgid "Search by description"
msgstr "Искать по описанию" msgstr "Искать по описанию"
#: search.go:52 #: search.go:61
msgid "Search by repository" msgid "Search by repository"
msgstr "Искать по репозиторию" msgstr "Искать по репозиторию"
#: search.go:57 #: search.go:66
msgid "Search by provides" msgid "Search by provides"
msgstr "Иcкать по provides" msgstr "Иcкать по provides"
#: search.go:62 #: search.go:71
msgid "Format output using a Go template" msgid "Format output using a Go template"
msgstr "Формат выходных данных с использованием шаблона Go" msgstr "Формат выходных данных с использованием шаблона Go"
#: search.go:96 #: search.go:130
msgid "Error while executing search" msgid "Error while executing search"
msgstr "Ошибка при выполнении поиска" msgstr "Ошибка при выполнении поиска"
#: search.go:104 #: search.go:138
msgid "Error parsing format template" msgid "Error parsing format template"
msgstr "Ошибка при разборе шаблона" msgstr "Ошибка при разборе шаблона"
#: search.go:112 #: search.go:153
msgid "Error executing template" msgid "Error executing template"
msgstr "Ошибка при выполнении шаблона" msgstr "Ошибка при выполнении шаблона"

@ -20,10 +20,6 @@
package types package types
type BuildOpts struct { type BuildOpts struct {
// Script string
// Repository string
// Packages []string
// Manager manager.Manager
Clean bool Clean bool
Interactive bool Interactive bool
} }
@ -32,7 +28,9 @@ type BuildVarsPre struct {
Version string `sh:"version,required"` Version string `sh:"version,required"`
Release int `sh:"release,required"` Release int `sh:"release,required"`
Epoch uint `sh:"epoch"` Epoch uint `sh:"epoch"`
Summary string `sh:"summary"`
Description string `sh:"desc"` Description string `sh:"desc"`
Group string `sh:"group"`
Homepage string `sh:"homepage"` Homepage string `sh:"homepage"`
Maintainer string `sh:"maintainer"` Maintainer string `sh:"maintainer"`
Architectures []string `sh:"architectures"` Architectures []string `sh:"architectures"`

@ -304,6 +304,7 @@ func buildPkgMetadata(
Provides: append(vars.Provides, vars.Name), Provides: append(vars.Provides, vars.Name),
Depends: deps, Depends: deps,
} }
pkgInfo.Section = vars.Group
pkgFormat := input.PkgFormat() pkgFormat := input.PkgFormat()
info := input.OSRelease() info := input.OSRelease()
@ -315,6 +316,17 @@ func buildPkgMetadata(
}) })
} }
if pkgFormat == "rpm" {
pkgInfo.RPM.Group = vars.Group
if vars.Summary != "" {
pkgInfo.RPM.Summary = vars.Summary
} else {
lines := strings.SplitN(vars.Description, "\n", 2)
pkgInfo.RPM.Summary = lines[0]
}
}
if vars.Epoch != 0 { if vars.Epoch != 0 {
pkgInfo.Epoch = strconv.FormatUint(uint64(vars.Epoch), 10) pkgInfo.Epoch = strconv.FormatUint(uint64(vars.Epoch), 10)
} }

@ -79,26 +79,22 @@ type PackageInfo struct {
} }
func (inf *PackageInfo) ToPackage(repoName string) *db.Package { func (inf *PackageInfo) ToPackage(repoName string) *db.Package {
return &db.Package{ pkg := EmptyPackage(repoName)
Version: inf.Version, pkg.Version = inf.Version
Release: inf.Release, pkg.Release = inf.Release
Epoch: inf.Epoch, pkg.Epoch = inf.Epoch
Architectures: inf.Architectures, pkg.Architectures = inf.Architectures
Licenses: inf.Licenses, pkg.Licenses = inf.Licenses
Provides: inf.Provides, pkg.Provides = inf.Provides
Conflicts: inf.Conflicts, pkg.Conflicts = inf.Conflicts
Replaces: inf.Replaces, pkg.Replaces = inf.Replaces
Description: db.NewJSON(map[string]string{}), return pkg
Homepage: db.NewJSON(map[string]string{}),
Maintainer: db.NewJSON(map[string]string{}),
Depends: db.NewJSON(map[string][]string{}),
BuildDepends: db.NewJSON(map[string][]string{}),
Repository: repoName,
}
} }
func EmptyPackage(repoName string) *db.Package { func EmptyPackage(repoName string) *db.Package {
return &db.Package{ return &db.Package{
Group: db.NewJSON(map[string]string{}),
Summary: db.NewJSON(map[string]string{}),
Description: db.NewJSON(map[string]string{}), Description: db.NewJSON(map[string]string{}),
Homepage: db.NewJSON(map[string]string{}), Homepage: db.NewJSON(map[string]string{}),
Maintainer: db.NewJSON(map[string]string{}), Maintainer: db.NewJSON(map[string]string{}),
@ -114,6 +110,8 @@ var overridable = map[string]string{
"desc": "Description", "desc": "Description",
"homepage": "Homepage", "homepage": "Homepage",
"maintainer": "Maintainer", "maintainer": "Maintainer",
"group": "Group",
"summary": "Summary",
} }
func resolveOverrides(runner *interp.Runner, pkg *db.Package) { func resolveOverrides(runner *interp.Runner, pkg *db.Package) {

@ -21,12 +21,16 @@ import (
"os" "os"
"text/template" "text/template"
"github.com/jeandeaual/go-locale"
"github.com/leonelquinteros/gotext" "github.com/leonelquinteros/gotext"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder" appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" "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/search" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/search"
) )
@ -36,6 +40,11 @@ func SearchCmd() *cli.Command {
Usage: gotext.Get("Search packages"), Usage: gotext.Get("Search packages"),
Aliases: []string{"s"}, Aliases: []string{"s"},
Flags: []cli.Flag{ Flags: []cli.Flag{
&cli.BoolFlag{
Name: "all",
Aliases: []string{"a"},
Usage: gotext.Get("Show all information, not just for the current distro"),
},
&cli.StringFlag{ &cli.StringFlag{
Name: "name", Name: "name",
Aliases: []string{"n"}, Aliases: []string{"n"},
@ -69,6 +78,31 @@ func SearchCmd() *cli.Command {
ctx := c.Context ctx := c.Context
var names []string
all := c.Bool("all")
systemLang, err := locale.GetLanguage()
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Can't detect system language"), err)
}
if systemLang == "" {
systemLang = "en"
}
if !all {
info, err := distro.ParseOSRelease(ctx)
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error parsing os-release file"), err)
}
names, err = overrides.Resolve(
info,
overrides.DefaultOpts.
WithLanguages([]string{systemLang}),
)
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error resolving overrides"), err)
}
}
deps, err := appbuilder. deps, err := appbuilder.
New(ctx). New(ctx).
WithConfig(). WithConfig().
@ -79,9 +113,9 @@ func SearchCmd() *cli.Command {
} }
defer deps.Defer() defer deps.Defer()
db := deps.DB database := deps.DB
s := search.New(db) s := search.New(database)
packages, err := s.Search( packages, err := s.Search(
ctx, ctx,
@ -106,14 +140,26 @@ func SearchCmd() *cli.Command {
} }
for _, dbPkg := range packages { for _, dbPkg := range packages {
var pkg any
if !all {
pkg = overrides.ResolvePackage(&dbPkg, names)
} else {
pkg = &dbPkg
}
if tmpl != nil { if tmpl != nil {
err = tmpl.Execute(os.Stdout, dbPkg) err = tmpl.Execute(os.Stdout, pkg)
if err != nil { if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error executing template"), err) return cliutils.FormatCliExit(gotext.Get("Error executing template"), err)
} }
fmt.Println() fmt.Println()
} else { } else {
fmt.Println(dbPkg.Name) switch v := pkg.(type) {
case *overrides.ResolvedPackage:
fmt.Println(v.Name)
case *db.Package:
fmt.Println(v.Name)
}
} }
} }