From e3772d0944707eae0541fd8009836814298037e0 Mon Sep 17 00:00:00 2001 From: robogg133 Date: Sat, 25 Oct 2025 10:16:33 -0300 Subject: [PATCH] some bug fixes, manifest.toml don't exist anyomre and all data for installation will be in one file name Packet.lua --- cmd/packets/main.go | 2 - configs/structs.go | 6 ++ internal/build/install.go | 165 ++++++++++++++++++++++++++++++++++++++ internal/build/lua.go | 62 +++++++++++++- internal/build/main.go | 86 +++++++++++++++++--- internal/build/manager.go | 44 ++++++++++ internal/build/specs.go | 2 + internal/consts/consts.go | 1 + internal/packet/main.go | 18 +++++ internal/utils/lua/git.go | 28 +++++++ pkg/main.go | 13 ++- 11 files changed, 405 insertions(+), 22 deletions(-) create mode 100644 internal/build/install.go create mode 100644 internal/build/manager.go create mode 100644 internal/packet/main.go create mode 100644 internal/utils/lua/git.go diff --git a/cmd/packets/main.go b/cmd/packets/main.go index 51c4ff4..bda76ba 100644 --- a/cmd/packets/main.go +++ b/cmd/packets/main.go @@ -2,7 +2,6 @@ package main import ( "database/sql" - _ "embed" "fmt" "log" "os" @@ -258,7 +257,6 @@ var installCmd = &cobra.Command{ var wg sync.WaitGroup wg.Add(1) go AsyncFullyUpgrade(inputName, cfg.Config.StorePackages, filepath.Join(cfg.Config.Data_d, id), &wg, db) - wg.Done() continue } diff --git a/configs/structs.go b/configs/structs.go index 28734da..5650059 100644 --- a/configs/structs.go +++ b/configs/structs.go @@ -1,5 +1,6 @@ package configs +/* type Manifest struct { Package struct { Name string `toml:"name"` @@ -11,16 +12,21 @@ type Manifest struct { Architeture string `toml:"architeture"` Os string `toml:"os"` PacakgeType string `toml:"type"` + + GitUrl string `toml:"giturl,omitempty"` + Branch string `toml:"gitbranch,omitempty"` } `toml:"Package"` Build struct { BuildDependencies map[string]string `toml:"dependencies"` } Hooks struct { + Fetch string `toml:"fetch,omitempty"` Install string `toml:"install"` Remove string `toml:"remove"` Build string `toml:"build"` } `toml:"Hooks"` } +*/ type ConfigTOML struct { Config struct { diff --git a/internal/build/install.go b/internal/build/install.go new file mode 100644 index 0000000..7dcb95e --- /dev/null +++ b/internal/build/install.go @@ -0,0 +1,165 @@ +package build + +import ( + "archive/tar" + "bytes" + "fmt" + "io" + "log" + "os" + "packets/internal/utils" + utils_lua "packets/internal/utils/lua" + "path/filepath" + "strings" + "sync" + + "github.com/klauspost/compress/zstd" + lua "github.com/yuin/gopher-lua" +) + +func (container Container) installPackage(file []byte, destDir string) error { + manifest, err := utils.ReadManifest(bytes.NewReader(file)) + if err != nil { + return err + } + + zstdReader, err := zstd.NewReader(bytes.NewReader(file)) + if err != nil { + return err + } + defer zstdReader.Close() + + tarReader := tar.NewReader(zstdReader) + + uid, err := utils.GetPacketsUID() + if err != nil { + return err + } + + for { + hdr, err := tarReader.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + + rel := filepath.Clean(hdr.Name) + + if rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { + continue + } + + if err := os.MkdirAll(filepath.Join(container.Root, destDir), 0775); err != nil { + return err + } + + if err := os.Chown(filepath.Join(container.Root, destDir), uid, 0); err != nil { + return err + } + + absPath := filepath.Join(filepath.Join(container.Root, destDir), rel) + + switch hdr.Typeflag { + + case tar.TypeDir: + err = os.MkdirAll(absPath, os.FileMode(hdr.Mode)) + if err != nil { + return err + } + if err := os.Chown(absPath, uid, 0); err != nil { + return err + } + + case tar.TypeReg: + + err = os.MkdirAll(filepath.Dir(absPath), 0775) + if err != nil { + return err + } + + out, err := os.Create(absPath) + if err != nil { + return err + } + + _, err = io.Copy(out, tarReader) + out.Close() + if err != nil { + return err + } + + err = os.Chmod(absPath, os.FileMode(0775)) + if err != nil { + return err + } + + if filepath.Base(hdr.Name) == "manifest.toml" || filepath.Base(hdr.Name) == manifest.Hooks.Install || filepath.Base(hdr.Name) == manifest.Hooks.Remove { + err = os.Chmod(absPath, os.FileMode(0755)) + if err != nil { + return err + } + } else { + if err := os.Chown(absPath, uid, 0); err != nil { + return err + } + } + } + } + + L, err := utils_lua.GetSandBox() + if err != nil { + return err + } + + L.SetGlobal("DATA_DIR", lua.LString(filepath.Join(destDir, "data"))) + L.SetGlobal("script", lua.LString(manifest.Hooks.Build)) + + bootstrapcontainer, err := NewContainer(filepath.Join(container.Root, destDir, "data"), manifest) + if err != nil { + return err + } + + bootstrapcontainer.LuaState.DoFile(manifest.Hooks.Build) + + L.SetGlobal("DATA_DIR", lua.LString(filepath.Join(destDir, "data"))) + L.SetGlobal("script", lua.LString(manifest.Hooks.Install)) + + if err := utils.ChangeToNoPermission(); err != nil { + return err + } + if err := L.DoFile(filepath.Join(destDir, manifest.Hooks.Install)); err != nil { + return err + } + + if err := utils.ElevatePermission(); err != nil { + return err + } + + return nil +} + +func (container Container) asyncFullInstallDependencie(dep string, storePackages bool, installPath string, wg *sync.WaitGroup, mu *sync.Mutex) { + defer wg.Done() + + fmt.Printf(" downloading %s \n", dep) + p, err := utils.GetPackage(dep) + if err != nil { + log.Fatal(err) + } + + fmt.Printf(" installing %s \n", dep) + + if err := container.installPackage(p.PackageF, installPath); err != nil { + log.Fatal(err) + } + + if storePackages { + _, err := p.Write() + if err != nil { + log.Fatal(err) + return + } + } +} diff --git a/internal/build/lua.go b/internal/build/lua.go index f598127..f454fad 100644 --- a/internal/build/lua.go +++ b/internal/build/lua.go @@ -2,6 +2,7 @@ package build import ( "fmt" + "io" "os" "os/exec" "strings" @@ -195,18 +196,71 @@ func (container Container) lpopen(L *lua.LState) int { return 2 } -func (container Container) GetLuaState() error { +func (container Container) lGet(L *lua.LState) int { + src := L.CheckString(1) + dest := L.CheckString(2) + + file, err := container.FS.Open(src) + if err != nil { + L.Push(lua.LFalse) + L.Push(lua.LString(err.Error())) + return 2 + } + defer file.Close() + + info, err := file.Stat() + if err != nil { + L.Push(lua.LFalse) + L.Push(lua.LString(err.Error())) + return 2 + } + + fileBlob, err := io.ReadAll(file) + if err != nil { + L.Push(lua.LFalse) + L.Push(lua.LString(err.Error())) + return 2 + } + + if err := os.WriteFile(dest, fileBlob, info.Mode()); err != nil { + L.Push(lua.LFalse) + L.Push(lua.LString(err.Error())) + return 2 + } + + L.Push(lua.LTrue) + L.Push(lua.LNil) + return 2 +} + +func (container Container) lCopyToContainer(L *lua.LState) int { + + if err := container.CopyHostToContainer(L.CheckString(1), L.CheckString(2)); err != nil { + L.Push(lua.LFalse) + L.Push(lua.LString(err.Error())) + return 2 + } + L.Push(lua.LTrue) + L.Push(lua.LNil) + return 2 +} + +func (container Container) GetLuaState() { + L := lua.NewState() osObject := L.GetGlobal("os").(*lua.LTable) + ioObject := L.GetGlobal("io").(*lua.LTable) L.SetGlobal("path_join", L.NewFunction(utils_lua.Ljoin)) - // Packets build functions - osObject.RawSetString("remove", L.NewFunction(container.lRemove)) osObject.RawSetString("rename", L.NewFunction(container.lRename)) osObject.RawSetString("copy", L.NewFunction(container.lCopy)) osObject.RawSetString("mkdir", L.NewFunction(container.lMkdir)) - return nil + + ioObject.RawSetString("popen", L.NewFunction(container.lpopen)) + ioObject.RawSetString("open", L.NewFunction(container.lOpen)) + + container.LuaState = *L } diff --git a/internal/build/main.go b/internal/build/main.go index 11ebaa7..87c8523 100644 --- a/internal/build/main.go +++ b/internal/build/main.go @@ -1,30 +1,70 @@ package build import ( + "database/sql" + "encoding/base64" + "encoding/json" "io" "os" "packets/configs" - utils_lua "packets/internal/utils/lua" + "packets/internal/consts" "path/filepath" + _ "modernc.org/sqlite" + "github.com/spf13/afero" lua "github.com/yuin/gopher-lua" ) type Container struct { - Root string - FS afero.Fs - DataDir string - Manifest configs.Manifest + BuildID BuildID + Root string + FS afero.Fs + DataDir string + LuaState lua.LState + Manifest configs.Manifest + uses int + DeleteAfter bool } -func NewContainer(Root string, dataDir string, manifest configs.Manifest) (Container, error) { +func NewContainer(dataDir string, manifest configs.Manifest) (Container, error) { var container Container + var err error + container.BuildID, err = getBuildId(manifest.Build.BuildDependencies) + if err != nil { + return Container{}, err + } baseFs := afero.NewOsFs() - fileSystem := afero.NewBasePathFs(baseFs, Root) - container.Root = Root + db, err := sql.Open("sqlite", consts.InstalledDB) + if err != nil { + return Container{}, err + } + if err := db.QueryRow("SELECT uses, dir FROM build_dependencies WHERE id = ? ", container.BuildID).Scan(&container.uses, container.Root); err != nil { + db.Close() + return Container{}, err + } + db.Close() + + if container.Root != "/dev/null" { + if _, err := os.Stat(container.Root); err != nil { + if os.IsNotExist(err) { + if err := container.createNew(); err != nil { + return Container{}, err + } + } + } + } else { + container.DeleteAfter = true + if err := container.createNew(); err != nil { + return Container{}, err + } + } + + container.GetLuaState() + fileSystem := afero.NewBasePathFs(baseFs, container.Root) + container.Manifest = manifest container.DataDir = dataDir container.FS = fileSystem @@ -37,6 +77,10 @@ func NewContainer(Root string, dataDir string, manifest configs.Manifest) (Conta return Container{}, err } + if err := container.FS.MkdirAll("/etc/packets", 0777); err != nil { + return Container{}, err + } + if err := afero.Symlinker.SymlinkIfPossible(container.FS.(afero.Symlinker), BinDir, SymLinkBinDir); err != nil { return Container{}, err } @@ -115,15 +159,31 @@ func (container Container) copySingleFile(source string, destination string) err return nil } -func (container Container) RunBuild() error { +func getBuildId(buildDependencies map[string]string) (BuildID, error) { + blobs, err := json.Marshal(buildDependencies) + if err != nil { + return "", err + } + return BuildID(base64.StdEncoding.EncodeToString(blobs)), nil +} - L, err := utils_lua.GetSandBox() +func (container Container) saveBuild() error { + db, err := sql.Open("sqlite", consts.InstalledDB) if err != nil { return err } + defer db.Close() - L.SetGlobal("data_dir", lua.LString(container.DataDir)) - L.SetGlobal("script", lua.LString(container.Manifest.Hooks.Build)) + buildID := container.BuildID + var exists bool + if err := db.QueryRow("SELECT EXISTS(SELECT 1 FROM build_dependencies WHERE id = ?)", buildID).Scan(exists); err != nil { + return err + } + if exists { + _, err := db.Exec("UPDATE FROM build_dependencies WHERE id = ? SET uses = uses + 1", buildID) + return err + } - return nil + _, err = db.Exec("INSERT INTO build_dependencies (id) VALUES (?)", buildID) + return err } diff --git a/internal/build/manager.go b/internal/build/manager.go new file mode 100644 index 0000000..b76ed2d --- /dev/null +++ b/internal/build/manager.go @@ -0,0 +1,44 @@ +package build + +import ( + "os" + "packets/configs" + "packets/internal/consts" + "packets/internal/utils" + "path/filepath" + "sync" + + _ "modernc.org/sqlite" +) + +func (container Container) createNew() error { + if err := os.MkdirAll(filepath.Join(consts.BuildImagesDir, string(container.BuildID)), 0775); err != nil { + return err + } + packetsuid, err := utils.GetPacketsUID() + if err != nil { + return err + } + if err := os.Chown(filepath.Join(consts.BuildImagesDir, string(container.BuildID)), packetsuid, 0); err != nil { + return err + } + dependencies, err := utils.ResolvDependencies(container.Manifest.Build.BuildDependencies) + if err != nil { + return err + } + + cfg, err := configs.GetConfigTOML() + if err != nil { + return err + } + var wg sync.WaitGroup + var mu sync.Mutex + for _, depn := range dependencies { + wg.Add(1) + go container.asyncFullInstallDependencie(depn, cfg.Config.StorePackages, depn, &wg, &mu) + } + wg.Wait() + + container.saveBuild() + return nil +} diff --git a/internal/build/specs.go b/internal/build/specs.go index 6bcdf98..be62122 100644 --- a/internal/build/specs.go +++ b/internal/build/specs.go @@ -4,3 +4,5 @@ const ( BinDir = "/usr/bin" SymLinkBinDir = "/bin" ) + +type BuildID string // Json dependencies encoded to base64 stdEncoding diff --git a/internal/consts/consts.go b/internal/consts/consts.go index 182078a..054f8ae 100644 --- a/internal/consts/consts.go +++ b/internal/consts/consts.go @@ -11,6 +11,7 @@ const ( LANDeadline = 2 * time.Second IndexDB = "/etc/packets/index.db" InstalledDB = "/etc/packets/installed.db" + BuildImagesDir = "/etc/packets/temp" DefaultSyncUrl = "https://servidordomal.fun/index.db" ) diff --git a/internal/packet/main.go b/internal/packet/main.go new file mode 100644 index 0000000..15fbea2 --- /dev/null +++ b/internal/packet/main.go @@ -0,0 +1,18 @@ +package packet + +type PacketLua struct { + Name string + Id string + Version string + Description string + Dependencies map[string]string + Author string + Architetures []string + Os []string + + PkgType string + GitUrl string + GitBranch string + + BuildDependencies string +} diff --git a/internal/utils/lua/git.go b/internal/utils/lua/git.go new file mode 100644 index 0000000..30782ef --- /dev/null +++ b/internal/utils/lua/git.go @@ -0,0 +1,28 @@ +package utils_lua + +import ( + "os" + + "github.com/go-git/go-git" + lua "github.com/yuin/gopher-lua" +) + +func LGitClone(L *lua.LState) int { + uri := L.CheckString(1) + output := L.CheckString(2) + + _, err := git.PlainClone(output, false, &git.CloneOptions{ + URL: uri, + Progress: os.Stdout, + }) + if err != nil { + L.Push(lua.LFalse) + L.Push(lua.LString(err.Error())) + return 2 + } + L.Push(lua.LTrue) + L.Push(lua.LNil) + return 2 +} + +func LGitCheckout(L) diff --git a/pkg/main.go b/pkg/main.go index ce1909f..a0d76e8 100644 --- a/pkg/main.go +++ b/pkg/main.go @@ -5,6 +5,7 @@ import ( "bytes" "io" "os" + "packets/internal/build" "packets/internal/utils" "runtime" @@ -114,9 +115,16 @@ func InstallPackage(file []byte, destDir string) error { return err } - L.SetGlobal("data_dir", lua.LString(filepath.Join(destDir, "data"))) + L.SetGlobal("DATA_DIR", lua.LString(filepath.Join(destDir, "data"))) L.SetGlobal("script", lua.LString(manifest.Hooks.Build)) + container, err := build.NewContainer(filepath.Join(destDir, "data"), manifest) + if err != nil { + return err + } + + container.GetLuaState() + L.SetGlobal("data_dir", lua.LString(filepath.Join(destDir, "data"))) L.SetGlobal("script", lua.LString(manifest.Hooks.Install)) @@ -145,9 +153,8 @@ func ExecuteRemoveScript(path string) error { return err } - L.SetGlobal("data_dir", lua.LFalse) + L.SetGlobal("DATA_DIR", lua.LFalse) L.SetGlobal("script", lua.LString(path)) - L.SetGlobal("build", lua.LNil) runtime.LockOSThread() defer runtime.UnlockOSThread()