forked from Plemya-x/ALR
		
	refactor: move alr.sh parsing to pkg
This commit is contained in:
		| @@ -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">16.9%</text> |         <text x="86" y="15" fill="#010101" fill-opacity=".3">16.7%</text> | ||||||
|         <text x="86" y="14">16.9%</text> |         <text x="86" y="14">16.7%</text> | ||||||
|     </g> |     </g> | ||||||
| </svg> | </svg> | ||||||
|   | |||||||
| Before Width: | Height: | Size: 926 B After Width: | Height: | Size: 926 B | 
| @@ -27,14 +27,13 @@ import ( | |||||||
| 	"log/slog" | 	"log/slog" | ||||||
|  |  | ||||||
| 	"github.com/leonelquinteros/gotext" | 	"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/cliutils" | ||||||
| 	"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/db" | ||||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/distro" | 	"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/internal/manager" | ||||||
|  | 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" | ||||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" | 	"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 { | type BuiltDep struct { | ||||||
| 	Name string | 	Name string | ||||||
| 	Path string | 	Path string | ||||||
| @@ -219,8 +177,8 @@ type ScriptResolverExecutor interface { | |||||||
| } | } | ||||||
|  |  | ||||||
| type ScriptExecutor interface { | type ScriptExecutor interface { | ||||||
| 	ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error) | 	ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) | ||||||
| 	ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error) | 	ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) | ||||||
| 	PrepareDirs( | 	PrepareDirs( | ||||||
| 		ctx context.Context, | 		ctx context.Context, | ||||||
| 		input *BuildInput, | 		input *BuildInput, | ||||||
| @@ -229,7 +187,7 @@ type ScriptExecutor interface { | |||||||
| 	ExecuteSecondPass( | 	ExecuteSecondPass( | ||||||
| 		ctx context.Context, | 		ctx context.Context, | ||||||
| 		input *BuildInput, | 		input *BuildInput, | ||||||
| 		sf *ScriptFile, | 		sf *alrsh.ALRSh, | ||||||
| 		varsOfPackages []*types.BuildVars, | 		varsOfPackages []*types.BuildVars, | ||||||
| 		repoDeps []string, | 		repoDeps []string, | ||||||
| 		builtDeps []*BuiltDep, | 		builtDeps []*BuiltDep, | ||||||
| @@ -242,7 +200,7 @@ type CacheExecutor interface { | |||||||
| } | } | ||||||
|  |  | ||||||
| type ScriptViewerExecutor 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 { | type CheckerExecutor interface { | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ import ( | |||||||
| 	"github.com/hashicorp/go-plugin" | 	"github.com/hashicorp/go-plugin" | ||||||
|  |  | ||||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/logger" | 	"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" | 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -50,13 +51,13 @@ type ScriptExecutorRPCServer struct { | |||||||
| // ReadScript | // ReadScript | ||||||
| // | // | ||||||
|  |  | ||||||
| func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error) { | func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) { | ||||||
| 	var resp *ScriptFile | 	var resp *alrsh.ALRSh | ||||||
| 	err := s.client.Call("Plugin.ReadScript", scriptPath, &resp) | 	err := s.client.Call("Plugin.ReadScript", scriptPath, &resp) | ||||||
| 	return resp, err | 	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) | 	file, err := s.Impl.ReadScript(context.Background(), scriptPath) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| @@ -72,7 +73,7 @@ func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *ScriptFile | |||||||
|  |  | ||||||
| type ExecuteFirstPassArgs struct { | type ExecuteFirstPassArgs struct { | ||||||
| 	Input *BuildInput | 	Input *BuildInput | ||||||
| 	Sf    *ScriptFile | 	Sf    *alrsh.ALRSh | ||||||
| } | } | ||||||
|  |  | ||||||
| type ExecuteFirstPassResp struct { | type ExecuteFirstPassResp struct { | ||||||
| @@ -80,7 +81,7 @@ type ExecuteFirstPassResp struct { | |||||||
| 	VarsOfPackages []*types.BuildVars | 	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 | 	var resp *ExecuteFirstPassResp | ||||||
| 	err := s.client.Call("Plugin.ExecuteFirstPass", &ExecuteFirstPassArgs{ | 	err := s.client.Call("Plugin.ExecuteFirstPass", &ExecuteFirstPassArgs{ | ||||||
| 		Input: input, | 		Input: input, | ||||||
| @@ -148,7 +149,7 @@ func (s *ScriptExecutorRPCServer) PrepareDirs(args *PrepareDirsArgs, reply *stru | |||||||
|  |  | ||||||
| type ExecuteSecondPassArgs struct { | type ExecuteSecondPassArgs struct { | ||||||
| 	Input          *BuildInput | 	Input          *BuildInput | ||||||
| 	Sf             *ScriptFile | 	Sf             *alrsh.ALRSh | ||||||
| 	VarsOfPackages []*types.BuildVars | 	VarsOfPackages []*types.BuildVars | ||||||
| 	RepoDeps       []string | 	RepoDeps       []string | ||||||
| 	BuiltDeps      []*BuiltDep | 	BuiltDeps      []*BuiltDep | ||||||
| @@ -158,7 +159,7 @@ type ExecuteSecondPassArgs struct { | |||||||
| func (s *ScriptExecutorRPC) ExecuteSecondPass( | func (s *ScriptExecutorRPC) ExecuteSecondPass( | ||||||
| 	ctx context.Context, | 	ctx context.Context, | ||||||
| 	input *BuildInput, | 	input *BuildInput, | ||||||
| 	sf *ScriptFile, | 	sf *alrsh.ALRSh, | ||||||
| 	varsOfPackages []*types.BuildVars, | 	varsOfPackages []*types.BuildVars, | ||||||
| 	repoDeps []string, | 	repoDeps []string, | ||||||
| 	builtDeps []*BuiltDep, | 	builtDeps []*BuiltDep, | ||||||
|   | |||||||
| @@ -19,7 +19,6 @@ package build | |||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"context" | 	"context" | ||||||
| 	"errors" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"log/slog" | 	"log/slog" | ||||||
| 	"os" | 	"os" | ||||||
| @@ -37,10 +36,10 @@ import ( | |||||||
| 	"mvdan.cc/sh/v3/syntax" | 	"mvdan.cc/sh/v3/syntax" | ||||||
|  |  | ||||||
| 	finddeps "gitea.plemya-x.ru/Plemya-x/ALR/internal/build/find_deps" | 	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/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/shutils/helpers" | 	"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" | 	"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) { | func (e *LocalScriptExecutor) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ALRSh, error) { | ||||||
| 	fl, err := readScript(scriptPath) | 	return alrsh.ReadFromLocal(scriptPath) | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	return &ScriptFile{ |  | ||||||
| 		Path: scriptPath, |  | ||||||
| 		File: fl, |  | ||||||
| 	}, nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error) { | func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ALRSh) (string, []*types.BuildVars, error) { | ||||||
| 	varsOfPackages := []*types.BuildVars{} | 	return sf.ParseBuildVars(ctx, input.info, input.packages) | ||||||
|  |  | ||||||
| 	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) PrepareDirs( | func (e *LocalScriptExecutor) PrepareDirs( | ||||||
| @@ -177,13 +86,13 @@ func (e *LocalScriptExecutor) PrepareDirs( | |||||||
| func (e *LocalScriptExecutor) ExecuteSecondPass( | func (e *LocalScriptExecutor) ExecuteSecondPass( | ||||||
| 	ctx context.Context, | 	ctx context.Context, | ||||||
| 	input *BuildInput, | 	input *BuildInput, | ||||||
| 	sf *ScriptFile, | 	sf *alrsh.ALRSh, | ||||||
| 	varsOfPackages []*types.BuildVars, | 	varsOfPackages []*types.BuildVars, | ||||||
| 	repoDeps []string, | 	repoDeps []string, | ||||||
| 	builtDeps []*BuiltDep, | 	builtDeps []*BuiltDep, | ||||||
| 	basePkg string, | 	basePkg string, | ||||||
| ) ([]*BuiltDep, error) { | ) ([]*BuiltDep, error) { | ||||||
| 	dirs, err := getDirs(e.cfg, sf.Path, basePkg) | 	dirs, err := getDirs(e.cfg, sf.Path(), basePkg) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| @@ -201,7 +110,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass( | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	err = runner.Run(ctx, sf.File) | 	err = runner.Run(ctx, sf.File()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
|  |  | ||||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" | 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" | ||||||
|  | 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type ScriptViewerConfig interface { | type ScriptViewerConfig interface { | ||||||
| @@ -33,12 +34,12 @@ type ScriptViewer struct { | |||||||
| func (s *ScriptViewer) ViewScript( | func (s *ScriptViewer) ViewScript( | ||||||
| 	ctx context.Context, | 	ctx context.Context, | ||||||
| 	input *BuildInput, | 	input *BuildInput, | ||||||
| 	sf *ScriptFile, | 	a *alrsh.ALRSh, | ||||||
| 	basePkg string, | 	basePkg string, | ||||||
| ) error { | ) error { | ||||||
| 	return cliutils.PromptViewScript( | 	return cliutils.PromptViewScript( | ||||||
| 		ctx, | 		ctx, | ||||||
| 		sf.Path, | 		a.Path(), | ||||||
| 		basePkg, | 		basePkg, | ||||||
| 		s.config.PagerStyle(), | 		s.config.PagerStyle(), | ||||||
| 		input.opts.Interactive, | 		input.opts.Interactive, | ||||||
|   | |||||||
| @@ -33,7 +33,6 @@ import ( | |||||||
| 	_ "github.com/goreleaser/nfpm/v2/arch" | 	_ "github.com/goreleaser/nfpm/v2/arch" | ||||||
| 	_ "github.com/goreleaser/nfpm/v2/deb" | 	_ "github.com/goreleaser/nfpm/v2/deb" | ||||||
| 	_ "github.com/goreleaser/nfpm/v2/rpm" | 	_ "github.com/goreleaser/nfpm/v2/rpm" | ||||||
| 	"mvdan.cc/sh/v3/syntax" |  | ||||||
|  |  | ||||||
| 	"github.com/goreleaser/nfpm/v2" | 	"github.com/goreleaser/nfpm/v2" | ||||||
| 	"github.com/goreleaser/nfpm/v2/files" | 	"github.com/goreleaser/nfpm/v2/files" | ||||||
| @@ -45,22 +44,6 @@ import ( | |||||||
| 	"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types" | 	"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 подготавливает директории для сборки. | // Функция prepareDirs подготавливает директории для сборки. | ||||||
| func prepareDirs(dirs types.Directories) error { | func prepareDirs(dirs types.Directories) error { | ||||||
| 	err := os.RemoveAll(dirs.BaseDir) // Удаляем базовую директорию, если она существует | 	err := os.RemoveAll(dirs.BaseDir) // Удаляем базовую директорию, если она существует | ||||||
|   | |||||||
| @@ -178,19 +178,19 @@ msgstr "" | |||||||
| msgid "Error removing packages" | msgid "Error removing packages" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: internal/build/build.go:417 | #: internal/build/build.go:375 | ||||||
| msgid "Building package" | msgid "Building package" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: internal/build/build.go:446 | #: internal/build/build.go:404 | ||||||
| msgid "The checksums array must be the same length as sources" | msgid "The checksums array must be the same length as sources" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: internal/build/build.go:488 | #: internal/build/build.go:446 | ||||||
| msgid "Downloading sources" | msgid "Downloading sources" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: internal/build/build.go:580 | #: internal/build/build.go:538 | ||||||
| msgid "Installing dependencies" | msgid "Installing dependencies" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| @@ -224,19 +224,19 @@ 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 "" | ||||||
|  |  | ||||||
| #: internal/build/script_executor.go:236 | #: internal/build/script_executor.go:145 | ||||||
| msgid "Building package metadata" | msgid "Building package metadata" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: internal/build/script_executor.go:366 | #: internal/build/script_executor.go:275 | ||||||
| msgid "Executing prepare()" | msgid "Executing prepare()" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: internal/build/script_executor.go:375 | #: internal/build/script_executor.go:284 | ||||||
| msgid "Executing build()" | msgid "Executing build()" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: internal/build/script_executor.go:404 internal/build/script_executor.go:424 | #: internal/build/script_executor.go:313 internal/build/script_executor.go:333 | ||||||
| msgid "Executing %s()" | msgid "Executing %s()" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -185,19 +185,19 @@ msgstr "Для команды remove ожидался хотя бы 1 аргум | |||||||
| msgid "Error removing packages" | msgid "Error removing packages" | ||||||
| msgstr "Ошибка при удалении пакетов" | msgstr "Ошибка при удалении пакетов" | ||||||
|  |  | ||||||
| #: internal/build/build.go:417 | #: internal/build/build.go:375 | ||||||
| msgid "Building package" | msgid "Building package" | ||||||
| msgstr "Сборка пакета" | msgstr "Сборка пакета" | ||||||
|  |  | ||||||
| #: internal/build/build.go:446 | #: internal/build/build.go:404 | ||||||
| msgid "The checksums array must be the same length as sources" | msgid "The checksums array must be the same length as sources" | ||||||
| msgstr "Массив контрольных сумм должен быть той же длины, что и источники" | msgstr "Массив контрольных сумм должен быть той же длины, что и источники" | ||||||
|  |  | ||||||
| #: internal/build/build.go:488 | #: internal/build/build.go:446 | ||||||
| msgid "Downloading sources" | msgid "Downloading sources" | ||||||
| msgstr "Скачивание источников" | msgstr "Скачивание источников" | ||||||
|  |  | ||||||
| #: internal/build/build.go:580 | #: internal/build/build.go:538 | ||||||
| msgid "Installing dependencies" | msgid "Installing dependencies" | ||||||
| msgstr "Установка зависимостей" | msgstr "Установка зависимостей" | ||||||
|  |  | ||||||
| @@ -235,19 +235,19 @@ msgid "AutoReq is not implemented for this package format, so it's skipped" | |||||||
| msgstr "" | msgstr "" | ||||||
| "AutoReq не реализовано для этого формата пакета, поэтому будет пропущено" | "AutoReq не реализовано для этого формата пакета, поэтому будет пропущено" | ||||||
|  |  | ||||||
| #: internal/build/script_executor.go:236 | #: internal/build/script_executor.go:145 | ||||||
| msgid "Building package metadata" | msgid "Building package metadata" | ||||||
| msgstr "Сборка метаданных пакета" | msgstr "Сборка метаданных пакета" | ||||||
|  |  | ||||||
| #: internal/build/script_executor.go:366 | #: internal/build/script_executor.go:275 | ||||||
| msgid "Executing prepare()" | msgid "Executing prepare()" | ||||||
| msgstr "Выполнение prepare()" | msgstr "Выполнение prepare()" | ||||||
|  |  | ||||||
| #: internal/build/script_executor.go:375 | #: internal/build/script_executor.go:284 | ||||||
| msgid "Executing build()" | msgid "Executing build()" | ||||||
| msgstr "Выполнение build()" | msgstr "Выполнение build()" | ||||||
|  |  | ||||||
| #: internal/build/script_executor.go:404 internal/build/script_executor.go:424 | #: internal/build/script_executor.go:313 internal/build/script_executor.go:333 | ||||||
| msgid "Executing %s()" | msgid "Executing %s()" | ||||||
| msgstr "Выполнение %s()" | msgstr "Выполнение %s()" | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										168
									
								
								pkg/alrsh/alrsh.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								pkg/alrsh/alrsh.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | |||||||
|  | // 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 alrsh | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"runtime" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  |  | ||||||
|  | 	"mvdan.cc/sh/v3/expand" | ||||||
|  | 	"mvdan.cc/sh/v3/interp" | ||||||
|  | 	"mvdan.cc/sh/v3/syntax" | ||||||
|  |  | ||||||
|  | 	"gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu" | ||||||
|  | 	"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/types" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type ALRSh struct { | ||||||
|  | 	file *syntax.File | ||||||
|  | 	path string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func createBuildEnvVars(info *distro.OSRelease, dirs types.Directories) []string { | ||||||
|  | 	env := os.Environ() | ||||||
|  |  | ||||||
|  | 	env = append( | ||||||
|  | 		env, | ||||||
|  | 		"DISTRO_NAME="+info.Name, | ||||||
|  | 		"DISTRO_PRETTY_NAME="+info.PrettyName, | ||||||
|  | 		"DISTRO_ID="+info.ID, | ||||||
|  | 		"DISTRO_VERSION_ID="+info.VersionID, | ||||||
|  | 		"DISTRO_ID_LIKE="+strings.Join(info.Like, " "), | ||||||
|  | 		"ARCH="+cpu.Arch(), | ||||||
|  | 		"NCPU="+strconv.Itoa(runtime.NumCPU()), | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	if dirs.ScriptDir != "" { | ||||||
|  | 		env = append(env, "scriptdir="+dirs.ScriptDir) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if dirs.PkgDir != "" { | ||||||
|  | 		env = append(env, "pkgdir="+dirs.PkgDir) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if dirs.SrcDir != "" { | ||||||
|  | 		env = append(env, "srcdir="+dirs.SrcDir) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return env | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *ALRSh) ParseBuildVars(ctx context.Context, info *distro.OSRelease, packages []string) (string, []*types.BuildVars, error) { | ||||||
|  | 	varsOfPackages := []*types.BuildVars{} | ||||||
|  |  | ||||||
|  | 	scriptDir := filepath.Dir(s.path) | ||||||
|  | 	env := createBuildEnvVars(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, s.file) // Запускаем скрипт | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	dec := decoder.New(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(packages) != 0 { | ||||||
|  | 		pkgNames = 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 (a *ALRSh) Path() string { | ||||||
|  | 	return a.path | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (a *ALRSh) File() *syntax.File { | ||||||
|  | 	return a.file | ||||||
|  | } | ||||||
							
								
								
									
										61
									
								
								pkg/alrsh/gob.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								pkg/alrsh/gob.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | // 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 alrsh | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"encoding/gob" | ||||||
|  |  | ||||||
|  | 	"mvdan.cc/sh/v3/syntax" | ||||||
|  | 	"mvdan.cc/sh/v3/syntax/typedjson" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (s *ALRSh) 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 *ALRSh) 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 | ||||||
|  | } | ||||||
							
								
								
									
										52
									
								
								pkg/alrsh/read.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								pkg/alrsh/read.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | // 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 alrsh | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io/fs" | ||||||
|  | 	"os" | ||||||
|  |  | ||||||
|  | 	"mvdan.cc/sh/v3/syntax" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type localFs struct{} | ||||||
|  |  | ||||||
|  | func (fs *localFs) Open(name string) (fs.File, error) { | ||||||
|  | 	return os.Open(name) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ReadFromFS(fsys fs.FS, script string) (*ALRSh, error) { | ||||||
|  | 	fl, err := fsys.Open(script) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("failed to open alr.sh: %w", err) | ||||||
|  | 	} | ||||||
|  | 	defer fl.Close() | ||||||
|  |  | ||||||
|  | 	file, err := syntax.NewParser().Parse(fl, "alr.sh") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return &ALRSh{ | ||||||
|  | 		file: file, | ||||||
|  | 		path: script, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ReadFromLocal(script string) (*ALRSh, error) { | ||||||
|  | 	return ReadFromFS(&localFs{}, script) | ||||||
|  | } | ||||||
							
								
								
									
										66
									
								
								pkg/types/script.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								pkg/types/script.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | // 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 types | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"encoding/gob" | ||||||
|  |  | ||||||
|  | 	"mvdan.cc/sh/v3/syntax" | ||||||
|  | 	"mvdan.cc/sh/v3/syntax/typedjson" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user