// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan. // It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов. // // ALR - Any Linux Repository // Copyright (C) 2025 Евгений Храмов // // 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 . package main import ( "log/slog" "os" "path/filepath" "strings" "github.com/leonelquinteros/gotext" "github.com/urfave/cli/v2" "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils" appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder" "gitea.plemya-x.ru/Plemya-x/ALR/internal/osutils" "gitea.plemya-x.ru/Plemya-x/ALR/internal/types" "gitea.plemya-x.ru/Plemya-x/ALR/internal/utils" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/build" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro" "gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager" ) func BuildCmd() *cli.Command { return &cli.Command{ Name: "build", Usage: gotext.Get("Build a local package"), Flags: []cli.Flag{ &cli.StringFlag{ Name: "script", Aliases: []string{"s"}, Value: "alr.sh", Usage: gotext.Get("Path to the build script"), }, &cli.StringFlag{ Name: "subpackage", Aliases: []string{"sb"}, Usage: gotext.Get("Specify subpackage in script (for multi package script only)"), }, &cli.StringFlag{ Name: "package", Aliases: []string{"p"}, Usage: gotext.Get("Name of the package to build and its repo (example: default/go-bin)"), }, &cli.BoolFlag{ Name: "clean", Aliases: []string{"c"}, Usage: gotext.Get("Build package from scratch even if there's an already built package available"), }, }, Action: func(c *cli.Context) error { if err := utils.EnuseIsPrivilegedGroupMember(); err != nil { return nil } wd, err := os.Getwd() if err != nil { return cliutils.FormatCliExit(gotext.Get("Error getting working directory"), err) } wd, wdCleanup, err := Mount(wd) if err != nil { return err } defer wdCleanup() ctx := c.Context deps, err := appbuilder. New(ctx). WithConfig(). WithDB(). WithReposNoPull(). Build() if err != nil { return cli.Exit(err, 1) } defer deps.Defer() var script string var packages []string // Обнаружение менеджера пакетов mgr := manager.Detect() if mgr == nil { slog.Error(gotext.Get("Unable to detect a supported package manager on the system")) os.Exit(1) } info, err := distro.ParseOSRelease(ctx) if err != nil { return cliutils.FormatCliExit(gotext.Get("Error parsing os release"), err) } var res *build.BuildResult var scriptArgs *build.BuildPackageFromScriptArgs var dbArgs *build.BuildPackageFromDbArgs switch { case c.IsSet("script"): script, err = filepath.Abs(c.String("script")) if err != nil { return cliutils.FormatCliExit(gotext.Get("Cannot get absolute script path"), err) } packages = append(packages, c.String("script-package")) scriptArgs = &build.BuildPackageFromScriptArgs{ Script: script, Packages: packages, BuildArgs: build.BuildArgs{ Opts: &types.BuildOpts{ Clean: c.Bool("clean"), Interactive: c.Bool("interactive"), }, PkgFormat_: build.GetPkgFormat(mgr), Info: info, }, } case c.IsSet("package"): // TODO: handle multiple packages packageInput := c.String("package") arr := strings.Split(packageInput, "/") var packageSearch string if len(arr) == 2 { packageSearch = arr[1] } else { packageSearch = arr[0] } pkgs, _, _ := deps.Repos.FindPkgs(ctx, []string{packageSearch}) pkg, ok := pkgs[packageSearch] if len(pkg) < 1 || !ok { slog.Error(gotext.Get("Package not found")) os.Exit(1) } if pkg[0].BasePkgName != "" { packages = append(packages, pkg[0].Name) } dbArgs = &build.BuildPackageFromDbArgs{ Package: &pkg[0], Packages: packages, BuildArgs: build.BuildArgs{ Opts: &types.BuildOpts{ Clean: c.Bool("clean"), Interactive: c.Bool("interactive"), }, PkgFormat_: build.GetPkgFormat(mgr), Info: info, }, } default: return cliutils.FormatCliExit(gotext.Get("Nothing to build"), nil) } if scriptArgs != nil { scriptFile := filepath.Base(scriptArgs.Script) newScriptDir, scriptDirCleanup, err := Mount(filepath.Dir(scriptArgs.Script)) if err != nil { return err } defer scriptDirCleanup() scriptArgs.Script = filepath.Join(newScriptDir, scriptFile) } if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil { return err } builder, err := build.NewMainBuilder( deps.Cfg, deps.Repos, ) if err != nil { return err } if scriptArgs != nil { res, err = builder.BuildPackageFromScript( ctx, scriptArgs, ) } else if dbArgs != nil { res, err = builder.BuildPackageFromDb( ctx, dbArgs, ) } if err != nil { return cliutils.FormatCliExit(gotext.Get("Error building package"), err) } // Перемещение собранных пакетов в рабочую директорию for _, pkgPath := range res.PackagePaths { name := filepath.Base(pkgPath) err = osutils.Move(pkgPath, filepath.Join(wd, name)) if err != nil { return cliutils.FormatCliExit(gotext.Get("Error moving the package"), err) } } slog.Info(gotext.Get("Done")) return nil }, } }