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"> <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="15" fill="#010101" fill-opacity=".3">coverage</text>
<text x="33.5" y="14">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="15" fill="#010101" fill-opacity=".3">17.2%</text>
<text x="86" y="14">17.0%</text> <text x="86" y="14">17.2%</text>
</g> </g>
</svg> </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) 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{ scriptArgs = &build.BuildPackageFromScriptArgs{
Script: script, Script: script,

View File

@ -188,3 +188,5 @@ func runTestCommands(t *testing.T, r e2e.Runnable, timeout time.Duration, expect
) )
assert.NoError(t, err) 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) out = append(out, opts.Name)
for index, item := range out { for index, item := range out {
out[index] = strings.TrimPrefix(strings.ReplaceAll(item, "-", "_"), "_") out[index] = strings.TrimPrefix(item, "_")
} }
return out, nil return out, nil

View File

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

View File

@ -45,23 +45,23 @@ msgstr "Ошибка при получении рабочего каталога
msgid "Cannot get absolute script path" msgid "Cannot get absolute script path"
msgstr "Невозможно получить абсолютный путь к скрипту" msgstr "Невозможно получить абсолютный путь к скрипту"
#: build.go:148 #: build.go:152
msgid "Package not found" msgid "Package not found"
msgstr "Пакет не найден" msgstr "Пакет не найден"
#: build.go:161 #: build.go:165
msgid "Nothing to build" msgid "Nothing to build"
msgstr "Нечего собирать" msgstr "Нечего собирать"
#: build.go:218 #: build.go:222
msgid "Error building package" msgid "Error building package"
msgstr "Ошибка при сборке пакета" msgstr "Ошибка при сборке пакета"
#: build.go:225 #: build.go:229
msgid "Error moving the package" msgid "Error moving the package"
msgstr "Ошибка при перемещении пакета" msgstr "Ошибка при перемещении пакета"
#: build.go:229 #: build.go:233
msgid "Done" msgid "Done"
msgstr "Сделано" msgstr "Сделано"
@ -409,35 +409,35 @@ msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr "" msgstr ""
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено" "AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
#: pkg/build/script_executor.go:237 #: pkg/build/script_executor.go:241
msgid "Building package metadata" msgid "Building package metadata"
msgstr "Сборка метаданных пакета" msgstr "Сборка метаданных пакета"
#: pkg/build/script_executor.go:368 #: pkg/build/script_executor.go:372
msgid "Executing prepare()" msgid "Executing prepare()"
msgstr "Выполнение prepare()" msgstr "Выполнение prepare()"
#: pkg/build/script_executor.go:377 #: pkg/build/script_executor.go:381
msgid "Executing build()" msgid "Executing build()"
msgstr "Выполнение 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()" msgid "Executing %s()"
msgstr "Выполнение %s()" msgstr "Выполнение %s()"
#: pkg/repos/pull.go:80 #: pkg/repos/pull.go:77
msgid "Pulling repository" msgid "Pulling repository"
msgstr "Скачивание репозитория" msgstr "Скачивание репозитория"
#: pkg/repos/pull.go:116 #: pkg/repos/pull.go:113
msgid "Repository up to date" msgid "Repository up to date"
msgstr "Репозиторий уже обновлён" msgstr "Репозиторий уже обновлён"
#: pkg/repos/pull.go:207 #: pkg/repos/pull.go:204
msgid "Git repository does not appear to be a valid ALR repo" msgid "Git repository does not appear to be a valid ALR repo"
msgstr "Репозиторий Git не поддерживается репозиторием ALR" msgstr "Репозиторий Git не поддерживается репозиторием ALR"
#: pkg/repos/pull.go:223 #: pkg/repos/pull.go:220
msgid "" msgid ""
"ALR repo's minimum ALR version is greater than the current version. Try " "ALR repo's minimum ALR version is greater than the current version. Try "
"updating ALR if something doesn't work." "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 return vars.Name, varsOfPackages, nil
} }
if len(input.packages) == 0 { var pkgNames []string
return "", nil, errors.New("script has multiple packages but package is not specified")
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 var preVars types.BuildVarsPre
funcName := fmt.Sprintf("meta_%s", pkgName) funcName := fmt.Sprintf("meta_%s", pkgName)
meta, ok := dec.GetFuncWithSubshell(funcName) meta, ok := dec.GetFuncWithSubshell(funcName)
if !ok { if !ok {
return "", nil, errors.New("func is missing") return "", nil, fmt.Errorf("func %s is missing", funcName)
} }
r, err := meta(ctx) r, err := meta(ctx)
if err != nil { 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" "mvdan.cc/sh/v3/syntax"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config" "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/shutils/handlers"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
) )
type actionType uint8 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 { func (rs *Repos) updatePkg(ctx context.Context, repo types.Repo, runner *interp.Runner, scriptFl io.ReadCloser) error {
parser := syntax.NewParser() parser := syntax.NewParser()
defer scriptFl.Close() pkgs, err := parseScript(ctx, repo, parser, runner, scriptFl)
fl, err := parser.Parse(scriptFl, "alr.sh")
if err != nil { if err != nil {
return err return err
} }
runner.Reset() for _, pkg := range pkgs {
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
err = rs.db.InsertPackage(ctx, *pkg) err = rs.db.InsertPackage(ctx, *pkg)
if err != nil { if err != nil {
return err return err
} }
} }
return nil
}
pkg := EmptyPackage(repo.Name) return nil
err = d.DecodeVars(pkg)
if err != nil {
return err
}
resolveOverrides(runner, pkg)
return rs.db.InsertPackage(ctx, *pkg)
} }
func (rs *Repos) processRepoChangesRunner(repoDir, scriptDir string) (*interp.Runner, error) { 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 return nil
} }
var pkg db.Package pkgs, err := parseScript(ctx, repo, parser, runner, r)
err = parseScript(ctx, parser, runner, r, &pkg)
if err != nil { if err != nil {
return err return err
} }
for _, pkg := range pkgs {
err = rs.db.DeletePkgs(ctx, "name = ? AND repository = ?", pkg.Name, repo.Name) err = rs.db.DeletePkgs(ctx, "name = ? AND repository = ?", pkg.Name, repo.Name)
if err != nil { if err != nil {
return err return err
} }
}
case actionUpdate: case actionUpdate:
if filepath.Base(action.File) != "alr.sh" { if filepath.Base(action.File) != "alr.sh" {
action.File = filepath.Join(filepath.Dir(action.File), "alr.sh") action.File = filepath.Join(filepath.Dir(action.File), "alr.sh")

View File

@ -18,6 +18,7 @@ package repos
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"io" "io"
"path/filepath" "path/filepath"
@ -35,7 +36,9 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db" "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/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/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/parser"
) )
// isValid makes sure the path of the file being updated is valid. // 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 return match
} }
func parseScript(ctx context.Context, parser *syntax.Parser, runner *interp.Runner, r io.ReadCloser, pkg *db.Package) error { func parseScript(
defer r.Close() ctx context.Context,
fl, err := parser.Parse(r, "alr.sh") 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 { if err != nil {
return err return nil, err
} }
runner.Reset() runner.Reset()
err = runner.Run(ctx, fl) err = runner.Run(ctx, fl)
if err != nil { if err != nil {
return err return nil, err
} }
d := decoder.New(&distro.OSRelease{}, runner) d := decoder.New(&distro.OSRelease{}, runner)
d.Overrides = false d.Overrides = false
d.LikeDistros = 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 { type PackageInfo struct {