fix: prevent for building dependencies twice
This commit is contained in:
		| @@ -174,9 +174,29 @@ func (s *ScriptFile) GobDecode(data []byte) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type BuildResult struct { | ||||
| 	PackagePaths []string | ||||
| 	PackageNames []string | ||||
| type BuiltDep struct { | ||||
| 	Name string | ||||
| 	Path string | ||||
| } | ||||
|  | ||||
| func Map[T, R any](items []T, f func(T) R) []R { | ||||
| 	res := make([]R, len(items)) | ||||
| 	for i, item := range items { | ||||
| 		res[i] = f(item) | ||||
| 	} | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| func GetBuiltPaths(deps []*BuiltDep) []string { | ||||
| 	return Map(deps, func(dep *BuiltDep) string { | ||||
| 		return dep.Path | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func GetBuiltName(deps []*BuiltDep) []string { | ||||
| 	return Map(deps, func(dep *BuiltDep) string { | ||||
| 		return dep.Name | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| type PackageFinder interface { | ||||
| @@ -212,9 +232,9 @@ type ScriptExecutor interface { | ||||
| 		sf *ScriptFile, | ||||
| 		varsOfPackages []*types.BuildVars, | ||||
| 		repoDeps []string, | ||||
| 		builtNames []string, | ||||
| 		builtDeps []*BuiltDep, | ||||
| 		basePkg string, | ||||
| 	) (*SecondPassResult, error) | ||||
| 	) ([]*BuiltDep, error) | ||||
| } | ||||
|  | ||||
| type CacheExecutor interface { | ||||
| @@ -320,7 +340,7 @@ type BuildPackageFromScriptArgs struct { | ||||
| func (b *Builder) BuildPackageFromDb( | ||||
| 	ctx context.Context, | ||||
| 	args *BuildPackageFromDbArgs, | ||||
| ) (*BuildResult, error) { | ||||
| ) ([]*BuiltDep, error) { | ||||
| 	scriptInfo := b.scriptResolver.ResolveScript(ctx, args.Package) | ||||
|  | ||||
| 	return b.BuildPackage(ctx, &BuildInput{ | ||||
| @@ -336,7 +356,7 @@ func (b *Builder) BuildPackageFromDb( | ||||
| func (b *Builder) BuildPackageFromScript( | ||||
| 	ctx context.Context, | ||||
| 	args *BuildPackageFromScriptArgs, | ||||
| ) (*BuildResult, error) { | ||||
| ) ([]*BuiltDep, error) { | ||||
| 	return b.BuildPackage(ctx, &BuildInput{ | ||||
| 		script:     args.Script, | ||||
| 		repository: "default", | ||||
| @@ -350,7 +370,7 @@ func (b *Builder) BuildPackageFromScript( | ||||
| func (b *Builder) BuildPackage( | ||||
| 	ctx context.Context, | ||||
| 	input *BuildInput, | ||||
| ) (*BuildResult, error) { | ||||
| ) ([]*BuiltDep, error) { | ||||
| 	scriptPath := input.script | ||||
|  | ||||
| 	slog.Debug("ReadScript") | ||||
| @@ -365,7 +385,7 @@ func (b *Builder) BuildPackage( | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	builtPaths := make([]string, 0) | ||||
| 	var builtDeps []*BuiltDep | ||||
|  | ||||
| 	if !input.opts.Clean { | ||||
| 		var remainingVars []*types.BuildVars | ||||
| @@ -375,14 +395,16 @@ func (b *Builder) BuildPackage( | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			if ok { | ||||
| 				builtPaths = append(builtPaths, builtPkgPath) | ||||
| 				builtDeps = append(builtDeps, &BuiltDep{ | ||||
| 					Path: builtPkgPath, | ||||
| 				}) | ||||
| 			} else { | ||||
| 				remainingVars = append(remainingVars, vars) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if len(remainingVars) == 0 { | ||||
| 			return &BuildResult{builtPaths, nil}, nil | ||||
| 			return builtDeps, nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -427,19 +449,32 @@ func (b *Builder) BuildPackage( | ||||
| 	sources, checksums = removeDuplicatesSources(sources, checksums) | ||||
|  | ||||
| 	slog.Debug("installBuildDeps") | ||||
| 	err = b.installBuildDeps(ctx, input, buildDepends) | ||||
| 	alrBuildDeps, err := b.installBuildDeps(ctx, input, buildDepends) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	slog.Debug("installOptDeps") | ||||
| 	err = b.installOptDeps(ctx, input, optDepends) | ||||
| 	_, err = b.installOptDeps(ctx, input, optDepends) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	depNames := make(map[string]struct{}) | ||||
| 	for _, dep := range alrBuildDeps { | ||||
| 		depNames[dep.Name] = struct{}{} | ||||
| 	} | ||||
|  | ||||
| 	// We filter so as not to re-build what has already been built at the `installBuildDeps` stage. | ||||
| 	var filteredDepends []string | ||||
| 	for _, d := range depends { | ||||
| 		if _, found := depNames[d]; !found { | ||||
| 			filteredDepends = append(filteredDepends, d) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	slog.Debug("BuildALRDeps") | ||||
| 	builtPaths, builtNames, repoDeps, err := b.BuildALRDeps(ctx, input, depends) | ||||
| 	newBuiltDeps, repoDeps, err := b.BuildALRDeps(ctx, input, filteredDepends) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -450,8 +485,6 @@ func (b *Builder) BuildPackage( | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// builtPaths = append(builtPaths, newBuildPaths...) | ||||
|  | ||||
| 	slog.Info(gotext.Get("Downloading sources")) | ||||
| 	slog.Debug("DownloadSources") | ||||
| 	err = b.sourceExecutor.DownloadSources( | ||||
| @@ -467,6 +500,8 @@ func (b *Builder) BuildPackage( | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	builtDeps = removeDuplicates(append(builtDeps, newBuiltDeps...)) | ||||
|  | ||||
| 	slog.Debug("ExecuteSecondPass") | ||||
| 	res, err := b.scriptExecutor.ExecuteSecondPass( | ||||
| 		ctx, | ||||
| @@ -474,20 +509,16 @@ func (b *Builder) BuildPackage( | ||||
| 		sf, | ||||
| 		varsOfPackages, | ||||
| 		repoDeps, | ||||
| 		builtNames, | ||||
| 		builtDeps, | ||||
| 		basePkg, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	pkgPaths := removeDuplicates(append(builtPaths, res.BuiltPaths...)) | ||||
| 	pkgNames := removeDuplicates(append(builtNames, res.BuiltNames...)) | ||||
| 	builtDeps = removeDuplicates(append(builtDeps, res...)) | ||||
|  | ||||
| 	return &BuildResult{ | ||||
| 		PackagePaths: pkgPaths, | ||||
| 		PackageNames: pkgNames, | ||||
| 	}, nil | ||||
| 	return builtDeps, nil | ||||
| } | ||||
|  | ||||
| type InstallPkgsArgs struct { | ||||
| @@ -523,7 +554,7 @@ func (b *Builder) InstallALRPackages( | ||||
| 		} | ||||
|  | ||||
| 		err = b.installerExecutor.InstallLocal( | ||||
| 			res.PackagePaths, | ||||
| 			GetBuiltPaths(res), | ||||
| 			&manager.Opts{ | ||||
| 				NoConfirm: !input.BuildOpts().Interactive, | ||||
| 			}, | ||||
| @@ -544,13 +575,13 @@ func (b *Builder) BuildALRDeps( | ||||
| 		PkgFormatProvider | ||||
| 	}, | ||||
| 	depends []string, | ||||
| ) (builtPaths, builtNames, repoDeps []string, err error) { | ||||
| ) (buildDeps []*BuiltDep, repoDeps []string, err error) { | ||||
| 	if len(depends) > 0 { | ||||
| 		slog.Info(gotext.Get("Installing dependencies")) | ||||
|  | ||||
| 		found, notFound, err := b.repos.FindPkgs(ctx, depends) // Поиск зависимостей | ||||
| 		if err != nil { | ||||
| 			return nil, nil, nil, err | ||||
| 			return nil, nil, err | ||||
| 		} | ||||
| 		repoDeps = notFound | ||||
|  | ||||
| @@ -597,20 +628,17 @@ func (b *Builder) BuildALRDeps( | ||||
| 				}, | ||||
| 			) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, nil, err | ||||
| 				return nil, nil, err | ||||
| 			} | ||||
|  | ||||
| 			builtPaths = append(builtPaths, res.PackagePaths...) | ||||
| 			builtNames = append(builtNames, res.PackageNames...) | ||||
| 			buildDeps = append(buildDeps, res...) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Удаляем возможные дубликаты, которые могут быть введены, если | ||||
| 	// несколько зависимостей зависят от одних и тех же пакетов. | ||||
| 	repoDeps = removeDuplicates(repoDeps) | ||||
| 	builtPaths = removeDuplicates(builtPaths) | ||||
| 	builtNames = removeDuplicates(builtNames) | ||||
| 	return builtPaths, builtNames, repoDeps, nil | ||||
| 	buildDeps = removeDuplicates(buildDeps) | ||||
|  | ||||
| 	return buildDeps, repoDeps, nil | ||||
| } | ||||
|  | ||||
| func (i *Builder) installBuildDeps( | ||||
| @@ -621,19 +649,20 @@ func (i *Builder) installBuildDeps( | ||||
| 		PkgFormatProvider | ||||
| 	}, | ||||
| 	pkgs []string, | ||||
| ) error { | ||||
| ) ([]*BuiltDep, error) { | ||||
| 	var builtDeps []*BuiltDep | ||||
| 	if len(pkgs) > 0 { | ||||
| 		deps, err := i.installerExecutor.RemoveAlreadyInstalled(pkgs) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		err = i.InstallPkgs(ctx, input, deps) // Устанавливаем выбранные пакеты | ||||
| 		builtDeps, err = i.InstallPkgs(ctx, input, deps) // Устанавливаем выбранные пакеты | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| 	return builtDeps, nil | ||||
| } | ||||
|  | ||||
| func (i *Builder) installOptDeps( | ||||
| @@ -644,10 +673,11 @@ func (i *Builder) installOptDeps( | ||||
| 		PkgFormatProvider | ||||
| 	}, | ||||
| 	pkgs []string, | ||||
| ) error { | ||||
| ) ([]*BuiltDep, error) { | ||||
| 	var builtDeps []*BuiltDep | ||||
| 	optDeps, err := i.installerExecutor.RemoveAlreadyInstalled(pkgs) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if len(optDeps) > 0 { | ||||
| 		optDeps, err := cliutils.ChooseOptDepends( | ||||
| @@ -657,19 +687,19 @@ func (i *Builder) installOptDeps( | ||||
| 			input.BuildOpts().Interactive, | ||||
| 		) // Пользователя просят выбрать опциональные зависимости | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		if len(optDeps) == 0 { | ||||
| 			return nil | ||||
| 			return builtDeps, nil | ||||
| 		} | ||||
|  | ||||
| 		err = i.InstallPkgs(ctx, input, optDeps) // Устанавливаем выбранные пакеты | ||||
| 		builtDeps, err = i.InstallPkgs(ctx, input, optDeps) // Устанавливаем выбранные пакеты | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| 	return builtDeps, nil | ||||
| } | ||||
|  | ||||
| func (i *Builder) InstallPkgs( | ||||
| @@ -680,18 +710,18 @@ func (i *Builder) InstallPkgs( | ||||
| 		PkgFormatProvider | ||||
| 	}, | ||||
| 	pkgs []string, | ||||
| ) error { | ||||
| 	builtPaths, _, repoDeps, err := i.BuildALRDeps(ctx, input, pkgs) | ||||
| ) ([]*BuiltDep, error) { | ||||
| 	builtDeps, repoDeps, err := i.BuildALRDeps(ctx, input, pkgs) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(builtPaths) > 0 { | ||||
| 		err = i.installerExecutor.InstallLocal(builtPaths, &manager.Opts{ | ||||
| 	if len(builtDeps) > 0 { | ||||
| 		err = i.installerExecutor.InstallLocal(GetBuiltPaths(builtDeps), &manager.Opts{ | ||||
| 			NoConfirm: !input.BuildOpts().Interactive, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -700,9 +730,9 @@ func (i *Builder) InstallPkgs( | ||||
| 			NoConfirm: !input.BuildOpts().Interactive, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| 	return builtDeps, nil | ||||
| } | ||||
|   | ||||
| @@ -151,7 +151,7 @@ type ExecuteSecondPassArgs struct { | ||||
| 	Sf             *ScriptFile | ||||
| 	VarsOfPackages []*types.BuildVars | ||||
| 	RepoDeps       []string | ||||
| 	BuiltNames     []string | ||||
| 	BuiltDeps      []*BuiltDep | ||||
| 	BasePkg        string | ||||
| } | ||||
|  | ||||
| @@ -161,16 +161,16 @@ func (s *ScriptExecutorRPC) ExecuteSecondPass( | ||||
| 	sf *ScriptFile, | ||||
| 	varsOfPackages []*types.BuildVars, | ||||
| 	repoDeps []string, | ||||
| 	builtNames []string, | ||||
| 	builtDeps []*BuiltDep, | ||||
| 	basePkg string, | ||||
| ) (*SecondPassResult, error) { | ||||
| 	var resp *SecondPassResult | ||||
| ) ([]*BuiltDep, error) { | ||||
| 	var resp []*BuiltDep | ||||
| 	err := s.client.Call("Plugin.ExecuteSecondPass", &ExecuteSecondPassArgs{ | ||||
| 		Input:          input, | ||||
| 		Sf:             sf, | ||||
| 		VarsOfPackages: varsOfPackages, | ||||
| 		RepoDeps:       repoDeps, | ||||
| 		BuiltNames:     builtNames, | ||||
| 		BuiltDeps:      builtDeps, | ||||
| 		BasePkg:        basePkg, | ||||
| 	}, &resp) | ||||
| 	if err != nil { | ||||
| @@ -179,20 +179,20 @@ func (s *ScriptExecutorRPC) ExecuteSecondPass( | ||||
| 	return resp, nil | ||||
| } | ||||
|  | ||||
| func (s *ScriptExecutorRPCServer) ExecuteSecondPass(args *ExecuteSecondPassArgs, resp *SecondPassResult) error { | ||||
| func (s *ScriptExecutorRPCServer) ExecuteSecondPass(args *ExecuteSecondPassArgs, resp *[]*BuiltDep) error { | ||||
| 	res, err := s.Impl.ExecuteSecondPass( | ||||
| 		context.Background(), | ||||
| 		args.Input, | ||||
| 		args.Sf, | ||||
| 		args.VarsOfPackages, | ||||
| 		args.RepoDeps, | ||||
| 		args.BuiltNames, | ||||
| 		args.BuiltDeps, | ||||
| 		args.BasePkg, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*resp = *res | ||||
| 	*resp = res | ||||
| 	return err | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -152,11 +152,6 @@ func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *Build | ||||
| 	return pkgs.BasePkgName, varsOfPackages, nil | ||||
| } | ||||
|  | ||||
| type SecondPassResult struct { | ||||
| 	BuiltPaths []string | ||||
| 	BuiltNames []string | ||||
| } | ||||
|  | ||||
| func (e *LocalScriptExecutor) PrepareDirs( | ||||
| 	ctx context.Context, | ||||
| 	input *BuildInput, | ||||
| @@ -185,9 +180,9 @@ func (e *LocalScriptExecutor) ExecuteSecondPass( | ||||
| 	sf *ScriptFile, | ||||
| 	varsOfPackages []*types.BuildVars, | ||||
| 	repoDeps []string, | ||||
| 	builtNames []string, | ||||
| 	builtDeps []*BuiltDep, | ||||
| 	basePkg string, | ||||
| ) (*SecondPassResult, error) { | ||||
| ) ([]*BuiltDep, error) { | ||||
| 	dirs, err := getDirs(e.cfg, sf.Path, basePkg) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -213,7 +208,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass( | ||||
|  | ||||
| 	dec := decoder.New(input.info, runner) | ||||
|  | ||||
| 	var builtPaths []string | ||||
| 	// var builtPaths []string | ||||
|  | ||||
| 	err = e.ExecuteFunctions(ctx, dirs, dec) | ||||
| 	if err != nil { | ||||
| @@ -247,7 +242,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass( | ||||
| 			dirs, | ||||
| 			append( | ||||
| 				repoDeps, | ||||
| 				builtNames..., | ||||
| 				GetBuiltName(builtDeps)..., | ||||
| 			), | ||||
| 			funcOut.Contents, | ||||
| 		) | ||||
| @@ -273,14 +268,13 @@ func (e *LocalScriptExecutor) ExecuteSecondPass( | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		builtPaths = append(builtPaths, pkgPath) | ||||
| 		builtNames = append(builtNames, vars.Name) | ||||
| 		builtDeps = append(builtDeps, &BuiltDep{ | ||||
| 			Name: vars.Name, | ||||
| 			Path: pkgPath, | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	return &SecondPassResult{ | ||||
| 		BuiltPaths: builtPaths, | ||||
| 		BuiltNames: builtNames, | ||||
| 	}, nil | ||||
| 	return builtDeps, nil | ||||
| } | ||||
|  | ||||
| func buildPkgMetadata( | ||||
|   | ||||
| @@ -288,14 +288,14 @@ func packageNames(pkgs []db.Package) []string { | ||||
| */ | ||||
|  | ||||
| // Функция removeDuplicates убирает любые дубликаты из предоставленного среза. | ||||
| func removeDuplicates(slice []string) []string { | ||||
| 	seen := map[string]struct{}{} | ||||
| 	result := []string{} | ||||
| func removeDuplicates[T comparable](slice []T) []T { | ||||
| 	seen := map[T]struct{}{} | ||||
| 	result := []T{} | ||||
|  | ||||
| 	for _, s := range slice { | ||||
| 		if _, ok := seen[s]; !ok { | ||||
| 			seen[s] = struct{}{} | ||||
| 			result = append(result, s) | ||||
| 	for _, item := range slice { | ||||
| 		if _, ok := seen[item]; !ok { | ||||
| 			seen[item] = struct{}{} | ||||
| 			result = append(result, item) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -41,7 +41,7 @@ func TestFindPkgs(t *testing.T) { | ||||
| 	err := rs.Pull(e.Ctx, []types.Repo{ | ||||
| 		{ | ||||
| 			Name: "default", | ||||
| 			URL:  "https://gitea.plemya-x.ru/xpamych/xpamych-alr-repo.git", | ||||
| 			URL:  "https://gitea.plemya-x.ru/Plemya-x/alr-default.git", | ||||
| 		}, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user