forked from Plemya-x/ALR
		
	feat: add files() function
also add files-find-lang and files-find-doc helpers
This commit is contained in:
		@@ -156,7 +156,7 @@ func BuildPackage(ctx context.Context, opts types.BuildOpts) ([]string, []string
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = executeFunctions(ctx, dec, dirs, vars) // Выполняем специальные функции
 | 
			
		||||
	funcOut, err := executeFunctions(ctx, dec, dirs, vars) // Выполняем специальные функции
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -165,7 +165,7 @@ func BuildPackage(ctx context.Context, opts types.BuildOpts) ([]string, []string
 | 
			
		||||
 | 
			
		||||
	pkgFormat := getPkgFormat(opts.Manager) // Получаем формат пакета
 | 
			
		||||
 | 
			
		||||
	pkgInfo, err := buildPkgMetadata(ctx, vars, dirs, pkgFormat, info, append(repoDeps, builtNames...)) // Собираем метаданные пакета
 | 
			
		||||
	pkgInfo, err := buildPkgMetadata(ctx, vars, dirs, pkgFormat, info, append(repoDeps, builtNames...), funcOut.Contents) // Собираем метаданные пакета
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -428,40 +428,44 @@ func buildALRDeps(ctx context.Context, opts types.BuildOpts, vars *types.BuildVa
 | 
			
		||||
	return builtPaths, builtNames, repoDeps, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FunctionsOutput struct {
 | 
			
		||||
	Contents *[]string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Функция executeFunctions выполняет специальные функции ALR, такие как version(), prepare() и т.д.
 | 
			
		||||
func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Directories, vars *types.BuildVars) (err error) {
 | 
			
		||||
func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Directories, vars *types.BuildVars) (*FunctionsOutput, error) {
 | 
			
		||||
	version, ok := dec.GetFunc("version")
 | 
			
		||||
	if ok {
 | 
			
		||||
		slog.Info(gotext.Get("Executing version()"))
 | 
			
		||||
 | 
			
		||||
		buf := &bytes.Buffer{}
 | 
			
		||||
 | 
			
		||||
		err = version(
 | 
			
		||||
		err := version(
 | 
			
		||||
			ctx,
 | 
			
		||||
			interp.Dir(dirs.SrcDir),
 | 
			
		||||
			interp.StdIO(os.Stdin, buf, os.Stderr),
 | 
			
		||||
		)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		newVer := strings.TrimSpace(buf.String())
 | 
			
		||||
		err = setVersion(ctx, dec.Runner, newVer)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		vars.Version = newVer
 | 
			
		||||
 | 
			
		||||
		slog.Info("Updating version", "new", newVer)
 | 
			
		||||
		slog.Info(gotext.Get("Updating version"), "new", newVer)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	prepare, ok := dec.GetFunc("prepare")
 | 
			
		||||
	if ok {
 | 
			
		||||
		slog.Info(gotext.Get("Executing prepare()"))
 | 
			
		||||
 | 
			
		||||
		err = prepare(ctx, interp.Dir(dirs.SrcDir))
 | 
			
		||||
		err := prepare(ctx, interp.Dir(dirs.SrcDir))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -469,9 +473,9 @@ func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Dire
 | 
			
		||||
	if ok {
 | 
			
		||||
		slog.Info(gotext.Get("Executing build()"))
 | 
			
		||||
 | 
			
		||||
		err = build(ctx, interp.Dir(dirs.SrcDir))
 | 
			
		||||
		err := build(ctx, interp.Dir(dirs.SrcDir))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -480,9 +484,9 @@ func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Dire
 | 
			
		||||
		packageFn, ok := dec.GetFunc("package")
 | 
			
		||||
		if ok {
 | 
			
		||||
			slog.Info(gotext.Get("Executing package()"))
 | 
			
		||||
			err = packageFn(ctx, interp.Dir(dirs.SrcDir))
 | 
			
		||||
			err := packageFn(ctx, interp.Dir(dirs.SrcDir))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -502,11 +506,51 @@ func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Dire
 | 
			
		||||
		break
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
	output := &FunctionsOutput{}
 | 
			
		||||
 | 
			
		||||
	files, ok := dec.GetFuncP("files", func(ctx context.Context, s *interp.Runner) error {
 | 
			
		||||
		// It should be done via interp.RunnerOption,
 | 
			
		||||
		// but due to the issues below, it cannot be done.
 | 
			
		||||
		// - https://github.com/mvdan/sh/issues/962
 | 
			
		||||
		// - https://github.com/mvdan/sh/issues/1125
 | 
			
		||||
		script, err := syntax.NewParser().Parse(strings.NewReader("cd $pkgdir && shopt -s globstar"), "")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return s.Run(ctx, script)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if ok {
 | 
			
		||||
		slog.Info(gotext.Get("Executing files()"))
 | 
			
		||||
 | 
			
		||||
		buf := &bytes.Buffer{}
 | 
			
		||||
 | 
			
		||||
		err := files(
 | 
			
		||||
			ctx,
 | 
			
		||||
			interp.Dir(dirs.PkgDir),
 | 
			
		||||
			interp.StdIO(os.Stdin, buf, os.Stderr),
 | 
			
		||||
		)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		contents := strings.Fields(strings.TrimSpace(buf.String()))
 | 
			
		||||
		output.Contents = &contents
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return output, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Функция buildPkgMetadata создает метаданные для пакета, который будет собран.
 | 
			
		||||
func buildPkgMetadata(ctx context.Context, vars *types.BuildVars, dirs types.Directories, pkgFormat string, info *distro.OSRelease, deps []string) (*nfpm.Info, error) {
 | 
			
		||||
func buildPkgMetadata(
 | 
			
		||||
	ctx context.Context,
 | 
			
		||||
	vars *types.BuildVars,
 | 
			
		||||
	dirs types.Directories,
 | 
			
		||||
	pkgFormat string,
 | 
			
		||||
	info *distro.OSRelease,
 | 
			
		||||
	deps []string,
 | 
			
		||||
	preferedContents *[]string,
 | 
			
		||||
) (*nfpm.Info, error) {
 | 
			
		||||
	pkgInfo := getBasePkgInfo(vars)
 | 
			
		||||
	pkgInfo.Description = vars.Description
 | 
			
		||||
	pkgInfo.Platform = "linux"
 | 
			
		||||
@@ -541,7 +585,7 @@ func buildPkgMetadata(ctx context.Context, vars *types.BuildVars, dirs types.Dir
 | 
			
		||||
		pkgInfo.Arch = "all"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	contents, err := buildContents(vars, dirs)
 | 
			
		||||
	contents, err := buildContents(vars, dirs, preferedContents)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -574,21 +618,27 @@ func buildPkgMetadata(ctx context.Context, vars *types.BuildVars, dirs types.Dir
 | 
			
		||||
 | 
			
		||||
// Функция buildContents создает секцию содержимого пакета, которая содержит файлы,
 | 
			
		||||
// которые будут включены в конечный пакет.
 | 
			
		||||
func buildContents(vars *types.BuildVars, dirs types.Directories) ([]*files.Content, error) {
 | 
			
		||||
func buildContents(vars *types.BuildVars, dirs types.Directories, preferedContents *[]string) ([]*files.Content, error) {
 | 
			
		||||
	contents := []*files.Content{}
 | 
			
		||||
	err := filepath.Walk(dirs.PkgDir, func(path string, fi os.FileInfo, err error) error {
 | 
			
		||||
		trimmed := strings.TrimPrefix(path, dirs.PkgDir)
 | 
			
		||||
 | 
			
		||||
	processPath := func(path, trimmed string, prefered bool) error {
 | 
			
		||||
		fi, err := os.Lstat(path)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if fi.IsDir() {
 | 
			
		||||
			f, err := os.Open(path)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			defer f.Close()
 | 
			
		||||
 | 
			
		||||
			// Если директория пустая, пропускаем её
 | 
			
		||||
			_, err = f.Readdirnames(1)
 | 
			
		||||
			if err != io.EOF {
 | 
			
		||||
				return nil
 | 
			
		||||
			if !prefered {
 | 
			
		||||
				_, err = f.Readdirnames(1)
 | 
			
		||||
				if err != io.EOF {
 | 
			
		||||
					return nil
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			contents = append(contents, &files.Content{
 | 
			
		||||
@@ -599,16 +649,14 @@ func buildContents(vars *types.BuildVars, dirs types.Directories) ([]*files.Cont
 | 
			
		||||
					MTime: fi.ModTime(),
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			return f.Close()
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		// Если файл является символической ссылкой, прорабатываем это
 | 
			
		||||
 | 
			
		||||
		if fi.Mode()&os.ModeSymlink != 0 {
 | 
			
		||||
			link, err := os.Readlink(path)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			// Удаляем pkgdir из пути символической ссылки
 | 
			
		||||
			link = strings.TrimPrefix(link, dirs.PkgDir)
 | 
			
		||||
 | 
			
		||||
			contents = append(contents, &files.Content{
 | 
			
		||||
@@ -620,10 +668,9 @@ func buildContents(vars *types.BuildVars, dirs types.Directories) ([]*files.Cont
 | 
			
		||||
					Mode:  fi.Mode(),
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		// Обрабатываем обычные файлы
 | 
			
		||||
 | 
			
		||||
		fileContent := &files.Content{
 | 
			
		||||
			Source:      path,
 | 
			
		||||
			Destination: trimmed,
 | 
			
		||||
@@ -634,16 +681,35 @@ func buildContents(vars *types.BuildVars, dirs types.Directories) ([]*files.Cont
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Если файл должен быть сохранен, установите его тип как config|noreplace
 | 
			
		||||
		if slices.Contains(vars.Backup, trimmed) {
 | 
			
		||||
			fileContent.Type = "config|noreplace"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		contents = append(contents, fileContent)
 | 
			
		||||
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
	return contents, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if preferedContents != nil {
 | 
			
		||||
		for _, trimmed := range *preferedContents {
 | 
			
		||||
			path := filepath.Join(dirs.PkgDir, trimmed)
 | 
			
		||||
			if err := processPath(path, trimmed, true); err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		err := filepath.Walk(dirs.PkgDir, func(path string, fi os.FileInfo, err error) error {
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			trimmed := strings.TrimPrefix(path, dirs.PkgDir)
 | 
			
		||||
			return processPath(path, trimmed, false)
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return contents, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Функция removeBuildDeps спрашивает у пользователя, хочет ли он удалить зависимости,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user