fix support of multiple packages in one alr.sh

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

@ -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 _, pkg := range pkgs {
err = rs.db.InsertPackage(ctx, *pkg)
if err != nil {
return err
}
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)
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,15 +336,16 @@ 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
}
err = rs.db.DeletePkgs(ctx, "name = ? AND repository = ?", pkg.Name, repo.Name)
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" {

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 {