forked from Plemya-x/ALR
		
	refactor: move alr.sh parsing to pkg
This commit is contained in:
		| @@ -27,14 +27,13 @@ import ( | ||||
| 	"log/slog" | ||||
|  | ||||
| 	"github.com/leonelquinteros/gotext" | ||||
| 	"mvdan.cc/sh/v3/syntax" | ||||
| 	"mvdan.cc/sh/v3/syntax/typedjson" | ||||
|  | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" | ||||
| 	"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/distro" | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager" | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" | ||||
| ) | ||||
|  | ||||
| @@ -133,47 +132,6 @@ type RepositoryProvider interface { | ||||
|  | ||||
| // ================================================ | ||||
|  | ||||
| type ScriptFile struct { | ||||
| 	File *syntax.File | ||||
| 	Path string | ||||
| } | ||||
|  | ||||
| func (s *ScriptFile) GobEncode() ([]byte, error) { | ||||
| 	var buf bytes.Buffer | ||||
| 	enc := gob.NewEncoder(&buf) | ||||
| 	if err := enc.Encode(s.Path); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var fileBuf bytes.Buffer | ||||
| 	if err := typedjson.Encode(&fileBuf, s.File); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	fileData := fileBuf.Bytes() | ||||
| 	if err := enc.Encode(fileData); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return buf.Bytes(), nil | ||||
| } | ||||
|  | ||||
| func (s *ScriptFile) GobDecode(data []byte) error { | ||||
| 	buf := bytes.NewBuffer(data) | ||||
| 	dec := gob.NewDecoder(buf) | ||||
| 	if err := dec.Decode(&s.Path); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	var fileData []byte | ||||
| 	if err := dec.Decode(&fileData); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	fileReader := bytes.NewReader(fileData) | ||||
| 	file, err := typedjson.Decode(fileReader) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	s.File = file.(*syntax.File) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type BuiltDep struct { | ||||
| 	Name string | ||||
| 	Path string | ||||
| @@ -219,8 +177,8 @@ type ScriptResolverExecutor interface { | ||||
| } | ||||
|  | ||||
| type ScriptExecutor interface { | ||||
| 	ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error) | ||||
| 	ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error) | ||||
| 	ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) | ||||
| 	ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) | ||||
| 	PrepareDirs( | ||||
| 		ctx context.Context, | ||||
| 		input *BuildInput, | ||||
| @@ -229,7 +187,7 @@ type ScriptExecutor interface { | ||||
| 	ExecuteSecondPass( | ||||
| 		ctx context.Context, | ||||
| 		input *BuildInput, | ||||
| 		sf *ScriptFile, | ||||
| 		sf *alrsh.ALRSh, | ||||
| 		varsOfPackages []*types.BuildVars, | ||||
| 		repoDeps []string, | ||||
| 		builtDeps []*BuiltDep, | ||||
| @@ -242,7 +200,7 @@ type CacheExecutor interface { | ||||
| } | ||||
|  | ||||
| type ScriptViewerExecutor interface { | ||||
| 	ViewScript(ctx context.Context, input *BuildInput, sf *ScriptFile, basePkg string) error | ||||
| 	ViewScript(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh, basePkg string) error | ||||
| } | ||||
|  | ||||
| type CheckerExecutor interface { | ||||
|   | ||||
| @@ -28,6 +28,7 @@ import ( | ||||
| 	"github.com/hashicorp/go-plugin" | ||||
|  | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/logger" | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" | ||||
| ) | ||||
|  | ||||
| @@ -50,13 +51,13 @@ type ScriptExecutorRPCServer struct { | ||||
| // ReadScript | ||||
| // | ||||
|  | ||||
| func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error) { | ||||
| 	var resp *ScriptFile | ||||
| func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) { | ||||
| 	var resp *alrsh.ALRSh | ||||
| 	err := s.client.Call("Plugin.ReadScript", scriptPath, &resp) | ||||
| 	return resp, err | ||||
| } | ||||
|  | ||||
| func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *ScriptFile) error { | ||||
| func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *alrsh.ALRSh) error { | ||||
| 	file, err := s.Impl.ReadScript(context.Background(), scriptPath) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @@ -72,7 +73,7 @@ func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *ScriptFile | ||||
|  | ||||
| type ExecuteFirstPassArgs struct { | ||||
| 	Input *BuildInput | ||||
| 	Sf    *ScriptFile | ||||
| 	Sf    *alrsh.ALRSh | ||||
| } | ||||
|  | ||||
| type ExecuteFirstPassResp struct { | ||||
| @@ -80,7 +81,7 @@ type ExecuteFirstPassResp struct { | ||||
| 	VarsOfPackages []*types.BuildVars | ||||
| } | ||||
|  | ||||
| func (s *ScriptExecutorRPC) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error) { | ||||
| func (s *ScriptExecutorRPC) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) { | ||||
| 	var resp *ExecuteFirstPassResp | ||||
| 	err := s.client.Call("Plugin.ExecuteFirstPass", &ExecuteFirstPassArgs{ | ||||
| 		Input: input, | ||||
| @@ -148,7 +149,7 @@ func (s *ScriptExecutorRPCServer) PrepareDirs(args *PrepareDirsArgs, reply *stru | ||||
|  | ||||
| type ExecuteSecondPassArgs struct { | ||||
| 	Input          *BuildInput | ||||
| 	Sf             *ScriptFile | ||||
| 	Sf             *alrsh.ALRSh | ||||
| 	VarsOfPackages []*types.BuildVars | ||||
| 	RepoDeps       []string | ||||
| 	BuiltDeps      []*BuiltDep | ||||
| @@ -158,7 +159,7 @@ type ExecuteSecondPassArgs struct { | ||||
| func (s *ScriptExecutorRPC) ExecuteSecondPass( | ||||
| 	ctx context.Context, | ||||
| 	input *BuildInput, | ||||
| 	sf *ScriptFile, | ||||
| 	sf *alrsh.ALRSh, | ||||
| 	varsOfPackages []*types.BuildVars, | ||||
| 	repoDeps []string, | ||||
| 	builtDeps []*BuiltDep, | ||||
|   | ||||
| @@ -19,7 +19,6 @@ package build | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"log/slog" | ||||
| 	"os" | ||||
| @@ -37,10 +36,10 @@ import ( | ||||
| 	"mvdan.cc/sh/v3/syntax" | ||||
|  | ||||
| 	finddeps "gitea.plemya-x.ru/Plemya-x/ALR/internal/build/find_deps" | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" | ||||
| 	"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/helpers" | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" | ||||
| ) | ||||
|  | ||||
| @@ -54,102 +53,12 @@ func NewLocalScriptExecutor(cfg Config) *LocalScriptExecutor { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (e *LocalScriptExecutor) ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error) { | ||||
| 	fl, err := readScript(scriptPath) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &ScriptFile{ | ||||
| 		Path: scriptPath, | ||||
| 		File: fl, | ||||
| 	}, nil | ||||
| func (e *LocalScriptExecutor) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) { | ||||
| 	return alrsh.ReadFromLocal(scriptPath) | ||||
| } | ||||
|  | ||||
| func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error) { | ||||
| 	varsOfPackages := []*types.BuildVars{} | ||||
|  | ||||
| 	scriptDir := filepath.Dir(sf.Path) | ||||
| 	env := createBuildEnvVars(input.info, types.Directories{ScriptDir: scriptDir}) | ||||
|  | ||||
| 	runner, err := interp.New( | ||||
| 		interp.Env(expand.ListEnviron(env...)),                               // Устанавливаем окружение | ||||
| 		interp.StdIO(os.Stdin, os.Stderr, os.Stderr),                         // Устанавливаем стандартный ввод-вывод | ||||
| 		interp.ExecHandler(helpers.Restricted.ExecHandler(handlers.NopExec)), // Ограничиваем выполнение | ||||
| 		interp.ReadDirHandler2(handlers.RestrictedReadDir(scriptDir)),        // Ограничиваем чтение директорий | ||||
| 		interp.StatHandler(handlers.RestrictedStat(scriptDir)),               // Ограничиваем доступ к статистике файлов | ||||
| 		interp.OpenHandler(handlers.RestrictedOpen(scriptDir)),               // Ограничиваем открытие файлов | ||||
| 		interp.Dir(scriptDir), | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return "", nil, err | ||||
| 	} | ||||
|  | ||||
| 	err = runner.Run(ctx, sf.File) // Запускаем скрипт | ||||
| 	if err != nil { | ||||
| 		return "", nil, err | ||||
| 	} | ||||
|  | ||||
| 	dec := decoder.New(input.info, runner) // Создаём новый декодер | ||||
|  | ||||
| 	type packages struct { | ||||
| 		BasePkgName string   `sh:"basepkg_name"` | ||||
| 		Names       []string `sh:"name"` | ||||
| 	} | ||||
|  | ||||
| 	var pkgs packages | ||||
| 	err = dec.DecodeVars(&pkgs) | ||||
| 	if err != nil { | ||||
| 		return "", nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(pkgs.Names) == 0 { | ||||
| 		return "", nil, errors.New("package name is missing") | ||||
| 	} | ||||
|  | ||||
| 	var vars types.BuildVars | ||||
|  | ||||
| 	if len(pkgs.Names) == 1 { | ||||
| 		err = dec.DecodeVars(&vars) // Декодируем переменные | ||||
| 		if err != nil { | ||||
| 			return "", nil, err | ||||
| 		} | ||||
| 		varsOfPackages = append(varsOfPackages, &vars) | ||||
|  | ||||
| 		return vars.Name, varsOfPackages, nil | ||||
| 	} | ||||
|  | ||||
| 	var pkgNames []string | ||||
|  | ||||
| 	if len(input.packages) != 0 { | ||||
| 		pkgNames = input.packages | ||||
| 	} else { | ||||
| 		pkgNames = pkgs.Names | ||||
| 	} | ||||
|  | ||||
| 	for _, pkgName := range pkgNames { | ||||
| 		var preVars types.BuildVarsPre | ||||
| 		funcName := fmt.Sprintf("meta_%s", pkgName) | ||||
| 		meta, ok := dec.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) | ||||
| 		err = d.DecodeVars(&preVars) | ||||
| 		if err != nil { | ||||
| 			return "", nil, err | ||||
| 		} | ||||
| 		vars := preVars.ToBuildVars() | ||||
| 		vars.Name = pkgName | ||||
| 		vars.Base = pkgs.BasePkgName | ||||
|  | ||||
| 		varsOfPackages = append(varsOfPackages, &vars) | ||||
| 	} | ||||
|  | ||||
| 	return pkgs.BasePkgName, varsOfPackages, nil | ||||
| func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) { | ||||
| 	return sf.ParseBuildVars(ctx, input.info, input.packages) | ||||
| } | ||||
|  | ||||
| func (e *LocalScriptExecutor) PrepareDirs( | ||||
| @@ -177,13 +86,13 @@ func (e *LocalScriptExecutor) PrepareDirs( | ||||
| func (e *LocalScriptExecutor) ExecuteSecondPass( | ||||
| 	ctx context.Context, | ||||
| 	input *BuildInput, | ||||
| 	sf *ScriptFile, | ||||
| 	sf *alrsh.ALRSh, | ||||
| 	varsOfPackages []*types.BuildVars, | ||||
| 	repoDeps []string, | ||||
| 	builtDeps []*BuiltDep, | ||||
| 	basePkg string, | ||||
| ) ([]*BuiltDep, error) { | ||||
| 	dirs, err := getDirs(e.cfg, sf.Path, basePkg) | ||||
| 	dirs, err := getDirs(e.cfg, sf.Path(), basePkg) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -201,7 +110,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass( | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	err = runner.Run(ctx, sf.File) | ||||
| 	err = runner.Run(ctx, sf.File()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|   | ||||
| @@ -20,6 +20,7 @@ import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" | ||||
| ) | ||||
|  | ||||
| type ScriptViewerConfig interface { | ||||
| @@ -33,12 +34,12 @@ type ScriptViewer struct { | ||||
| func (s *ScriptViewer) ViewScript( | ||||
| 	ctx context.Context, | ||||
| 	input *BuildInput, | ||||
| 	sf *ScriptFile, | ||||
| 	a *alrsh.ALRSh, | ||||
| 	basePkg string, | ||||
| ) error { | ||||
| 	return cliutils.PromptViewScript( | ||||
| 		ctx, | ||||
| 		sf.Path, | ||||
| 		a.Path(), | ||||
| 		basePkg, | ||||
| 		s.config.PagerStyle(), | ||||
| 		input.opts.Interactive, | ||||
|   | ||||
| @@ -33,7 +33,6 @@ import ( | ||||
| 	_ "github.com/goreleaser/nfpm/v2/arch" | ||||
| 	_ "github.com/goreleaser/nfpm/v2/deb" | ||||
| 	_ "github.com/goreleaser/nfpm/v2/rpm" | ||||
| 	"mvdan.cc/sh/v3/syntax" | ||||
|  | ||||
| 	"github.com/goreleaser/nfpm/v2" | ||||
| 	"github.com/goreleaser/nfpm/v2/files" | ||||
| @@ -45,22 +44,6 @@ import ( | ||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" | ||||
| ) | ||||
|  | ||||
| // Функция readScript анализирует скрипт сборки с использованием встроенной реализации bash | ||||
| func readScript(script string) (*syntax.File, error) { | ||||
| 	fl, err := os.Open(script) // Открываем файл скрипта | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer fl.Close() // Закрываем файл после выполнения | ||||
|  | ||||
| 	file, err := syntax.NewParser().Parse(fl, "alr.sh") // Парсим скрипт с помощью синтаксического анализатора | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return file, nil // Возвращаем синтаксическое дерево | ||||
| } | ||||
|  | ||||
| // Функция prepareDirs подготавливает директории для сборки. | ||||
| func prepareDirs(dirs types.Directories) error { | ||||
| 	err := os.RemoveAll(dirs.BaseDir) // Удаляем базовую директорию, если она существует | ||||
|   | ||||
		Reference in New Issue
	
	Block a user