fix support of multiple packages in one alr.sh
All checks were successful
Pre-commit / pre-commit (pull_request) Successful in 1m37s

This commit is contained in:
2025-05-13 21:55:23 +03:00
parent c892310f69
commit 443e481561
11 changed files with 224 additions and 114 deletions

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.0%</text>
<text x="86" y="14">17.0%</text>
<text x="86" y="15" fill="#010101" fill-opacity=".3">17.2%</text>
<text x="86" y="14">17.2%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 926 B

After

Width:  |  Height:  |  Size: 926 B

View File

@ -118,7 +118,11 @@ func BuildCmd() *cli.Command {
return cliutils.FormatCliExit(gotext.Get("Cannot get absolute script path"), err)
}
packages = append(packages, c.String("script-package"))
subpackage := c.String("subpackage")
if subpackage != "" {
packages = append(packages, subpackage)
}
scriptArgs = &build.BuildPackageFromScriptArgs{
Script: script,

View File

@ -188,3 +188,5 @@ func runTestCommands(t *testing.T, r e2e.Runnable, timeout time.Duration, expect
)
assert.NoError(t, err)
}
const REPO_FOR_E2E_TESTS = "https://gitea.plemya-x.ru/Maks1mS/repo-for-tests.git"

View File

@ -0,0 +1,59 @@
// 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"
"github.com/stretchr/testify/assert"
)
func TestE2EIssue81MultiplePackages(t *testing.T) {
dockerMultipleRun(
t,
"issue-81-multiple-packages",
COMMON_SYSTEMS,
func(t *testing.T, r e2e.Runnable) {
err := r.Exec(e2e.NewCommand(
"sudo",
"alr",
"addrepo",
"--name",
"alr-repo",
"--url",
REPO_FOR_E2E_TESTS,
))
assert.NoError(t, err)
err = r.Exec(e2e.NewCommand(
"sudo", "alr", "ref",
))
assert.NoError(t, err)
err = r.Exec(e2e.NewCommand(
"sudo", "alr", "in", "first-package-with-dashes",
))
assert.NoError(t, err)
err = r.Exec(e2e.NewCommand("cat", "/opt/first-package"))
assert.NoError(t, err)
},
)
}

View File

@ -104,7 +104,7 @@ func Resolve(info *distro.OSRelease, opts *Opts) ([]string, error) {
out = append(out, opts.Name)
for index, item := range out {
out[index] = strings.TrimPrefix(strings.ReplaceAll(item, "-", "_"), "_")
out[index] = strings.TrimPrefix(item, "_")
}
return out, nil

View File

@ -38,23 +38,23 @@ msgstr ""
msgid "Cannot get absolute script path"
msgstr ""
#: build.go:148
#: build.go:152
msgid "Package not found"
msgstr ""
#: build.go:161
#: build.go:165
msgid "Nothing to build"
msgstr ""
#: build.go:218
#: build.go:222
msgid "Error building package"
msgstr ""
#: build.go:225
#: build.go:229
msgid "Error moving the package"
msgstr ""
#: build.go:229
#: build.go:233
msgid "Done"
msgstr ""
@ -397,35 +397,35 @@ msgstr ""
msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr ""
#: pkg/build/script_executor.go:237
#: pkg/build/script_executor.go:241
msgid "Building package metadata"
msgstr ""
#: pkg/build/script_executor.go:368
#: pkg/build/script_executor.go:372
msgid "Executing prepare()"
msgstr ""
#: pkg/build/script_executor.go:377
#: pkg/build/script_executor.go:381
msgid "Executing build()"
msgstr ""
#: pkg/build/script_executor.go:406 pkg/build/script_executor.go:426
#: pkg/build/script_executor.go:410 pkg/build/script_executor.go:430
msgid "Executing %s()"
msgstr ""
#: pkg/repos/pull.go:80
#: pkg/repos/pull.go:77
msgid "Pulling repository"
msgstr ""
#: pkg/repos/pull.go:116
#: pkg/repos/pull.go:113
msgid "Repository up to date"
msgstr ""
#: pkg/repos/pull.go:207
#: pkg/repos/pull.go:204
msgid "Git repository does not appear to be a valid ALR repo"
msgstr ""
#: pkg/repos/pull.go:223
#: pkg/repos/pull.go:220
msgid ""
"ALR repo's minimum ALR version is greater than the current version. Try "
"updating ALR if something doesn't work."

View File

@ -45,23 +45,23 @@ msgstr "Ошибка при получении рабочего каталога
msgid "Cannot get absolute script path"
msgstr "Невозможно получить абсолютный путь к скрипту"
#: build.go:148
#: build.go:152
msgid "Package not found"
msgstr "Пакет не найден"
#: build.go:161
#: build.go:165
msgid "Nothing to build"
msgstr "Нечего собирать"
#: build.go:218
#: build.go:222
msgid "Error building package"
msgstr "Ошибка при сборке пакета"
#: build.go:225
#: build.go:229
msgid "Error moving the package"
msgstr "Ошибка при перемещении пакета"
#: build.go:229
#: build.go:233
msgid "Done"
msgstr "Сделано"
@ -409,35 +409,35 @@ msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr ""
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
#: pkg/build/script_executor.go:237
#: pkg/build/script_executor.go:241
msgid "Building package metadata"
msgstr "Сборка метаданных пакета"
#: pkg/build/script_executor.go:368
#: pkg/build/script_executor.go:372
msgid "Executing prepare()"
msgstr "Выполнение prepare()"
#: pkg/build/script_executor.go:377
#: pkg/build/script_executor.go:381
msgid "Executing build()"
msgstr "Выполнение build()"
#: pkg/build/script_executor.go:406 pkg/build/script_executor.go:426
#: pkg/build/script_executor.go:410 pkg/build/script_executor.go:430
msgid "Executing %s()"
msgstr "Выполнение %s()"
#: pkg/repos/pull.go:80
#: pkg/repos/pull.go:77
msgid "Pulling repository"
msgstr "Скачивание репозитория"
#: pkg/repos/pull.go:116
#: pkg/repos/pull.go:113
msgid "Repository up to date"
msgstr "Репозиторий уже обновлён"
#: pkg/repos/pull.go:207
#: pkg/repos/pull.go:204
msgid "Git repository does not appear to be a valid ALR repo"
msgstr "Репозиторий Git не поддерживается репозиторием ALR"
#: pkg/repos/pull.go:223
#: pkg/repos/pull.go:220
msgid ""
"ALR repo's minimum ALR version is greater than the current version. Try "
"updating ALR if something doesn't work."

View File

@ -118,16 +118,20 @@ func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *Build
return vars.Name, varsOfPackages, nil
}
if len(input.packages) == 0 {
return "", nil, errors.New("script has multiple packages but package is not specified")
var pkgNames []string
if len(input.packages) != 0 {
pkgNames = input.packages
} else {
pkgNames = pkgs.Names
}
for _, pkgName := range input.packages {
for _, pkgName := range pkgNames {
var preVars types.BuildVarsPre
funcName := fmt.Sprintf("meta_%s", pkgName)
meta, ok := dec.GetFuncWithSubshell(funcName)
if !ok {
return "", nil, errors.New("func is missing")
return "", nil, fmt.Errorf("func %s is missing", funcName)
}
r, err := meta(ctx)
if err != nil {

38
pkg/parser/parser.go Normal file
View File

@ -0,0 +1,38 @@
// 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/>.
package parser
import (
"fmt"
"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
}

View File

@ -43,11 +43,8 @@ import (
"mvdan.cc/sh/v3/syntax"
"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/shutils/decoder"
"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/distro"
)
type actionType uint8
@ -231,79 +228,19 @@ func (rs *Repos) Pull(ctx context.Context, repos []types.Repo) error {
func (rs *Repos) updatePkg(ctx context.Context, repo types.Repo, runner *interp.Runner, scriptFl io.ReadCloser) error {
parser := syntax.NewParser()
defer scriptFl.Close()
fl, err := parser.Parse(scriptFl, "alr.sh")
pkgs, err := parseScript(ctx, repo, parser, runner, scriptFl)
if err != nil {
return err
}
runner.Reset()
err = runner.Run(ctx, fl)
if err != nil {
return err
}
type packages struct {
BasePkgName string `sh:"basepkg_name"`
Names []string `sh:"name"`
}
var pkgs packages
d := decoder.New(&distro.OSRelease{}, runner)
d.Overrides = false
d.LikeDistros = false
err = d.DecodeVars(&pkgs)
if err != nil {
return err
}
if len(pkgs.Names) > 1 {
if pkgs.BasePkgName == "" {
pkgs.BasePkgName = pkgs.Names[0]
}
for _, pkgName := range pkgs.Names {
pkgInfo := PackageInfo{}
funcName := fmt.Sprintf("meta_%s", pkgName)
runner.Reset()
err = runner.Run(ctx, fl)
if err != nil {
return err
}
meta, ok := d.GetFuncWithSubshell(funcName)
if !ok {
return errors.New("func is missing")
}
r, err := meta(ctx)
if err != nil {
return err
}
d := decoder.New(&distro.OSRelease{}, r)
d.Overrides = false
d.LikeDistros = false
err = d.DecodeVars(&pkgInfo)
if err != nil {
return err
}
pkg := pkgInfo.ToPackage(repo.Name)
resolveOverrides(r, pkg)
pkg.Name = pkgName
pkg.BasePkgName = pkgs.BasePkgName
for _, pkg := range pkgs {
err = rs.db.InsertPackage(ctx, *pkg)
if err != nil {
return err
}
}
return nil
}
pkg := EmptyPackage(repo.Name)
err = d.DecodeVars(pkg)
if err != nil {
return err
}
resolveOverrides(runner, pkg)
return rs.db.InsertPackage(ctx, *pkg)
return nil
}
func (rs *Repos) processRepoChangesRunner(repoDir, scriptDir string) (*interp.Runner, error) {
@ -399,16 +336,17 @@ func (rs *Repos) processRepoChanges(ctx context.Context, repo types.Repo, r *git
return nil
}
var pkg db.Package
err = parseScript(ctx, parser, runner, r, &pkg)
pkgs, err := parseScript(ctx, repo, parser, runner, r)
if err != nil {
return err
}
for _, pkg := range pkgs {
err = rs.db.DeletePkgs(ctx, "name = ? AND repository = ?", pkg.Name, repo.Name)
if err != nil {
return err
}
}
case actionUpdate:
if filepath.Base(action.File) != "alr.sh" {
action.File = filepath.Join(filepath.Dir(action.File), "alr.sh")

View File

@ -18,6 +18,7 @@ package repos
import (
"context"
"errors"
"fmt"
"io"
"path/filepath"
@ -35,7 +36,9 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"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/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/parser"
)
// isValid makes sure the path of the file being updated is valid.
@ -54,23 +57,85 @@ func isValid(from, to diff.File) bool {
return match
}
func parseScript(ctx context.Context, parser *syntax.Parser, runner *interp.Runner, r io.ReadCloser, pkg *db.Package) error {
defer r.Close()
fl, err := parser.Parse(r, "alr.sh")
func parseScript(
ctx context.Context,
repo types.Repo,
syntaxParser *syntax.Parser,
runner *interp.Runner,
r io.ReadCloser,
) ([]*db.Package, error) {
fl, err := syntaxParser.Parse(r, "alr.sh")
if err != nil {
return err
return nil, err
}
runner.Reset()
err = runner.Run(ctx, fl)
if err != nil {
return err
return nil, err
}
d := decoder.New(&distro.OSRelease{}, runner)
d.Overrides = false
d.LikeDistros = false
return d.DecodeVars(pkg)
pkgNames, err := parser.ParseNames(d)
if err != nil {
return nil, fmt.Errorf("failed parsing package names: %w", err)
}
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 {