Compare commits

105 Commits

Author SHA1 Message Date
064ee7f404 testing new features 2025-11-01 16:39:11 -03:00
52ecacc4fe installation system soft implemented 2025-11-01 16:39:01 -03:00
4c88ec3bc2 using CURRENT_ARCH_NORMALIZED 2025-10-31 21:32:51 -03:00
ff5e271195 adding getsourcefunction sha256 check 2025-10-31 21:32:35 -03:00
cbea1dd8b5 normalize arch function 2025-10-31 21:31:58 -03:00
acf00bc5f8 added lua functions from old version of packets 2025-10-31 21:31:12 -03:00
b15d847fd2 function to generate random text 2025-10-31 21:30:48 -03:00
05af0969e9 methods for PacketLua struct 2025-10-31 18:15:42 -03:00
dff912928b removing useless part 2025-10-31 18:15:16 -03:00
0001118bd0 file for test and debuging got in codebase for mistake 2025-10-31 18:08:23 -03:00
43a24a4f36 changing pkg() to install() 2025-10-31 18:04:25 -03:00
d3c4a604c3 New Packet.lua format, test parsing and entire new lua ecossystem 2025-10-31 17:52:40 -03:00
6c5abdf4d4 new Packet.lua format, testing it with bat 2025-10-31 13:32:03 -03:00
1c4ade5db9 removing everything to do final version of packets client 2025-10-31 12:54:42 -03:00
b31630a6c0 Merge pull request #4 from Caio1w/Solved-Issue#3
Solved Issue #3
2025-10-28 21:25:51 -03:00
Caio1w
25eabc92ed Update const.go 2025-10-28 21:23:14 -03:00
a111b060f1 Merge pull request #2 from roboogg133/build-system
A scrap of Packet.lua ecosystem
2025-10-26 21:53:15 -03:00
a62ddf8270 simple checking for remote packets 2025-10-26 21:47:06 -03:00
aa65b28112 Packet.lua with right version, serial and better version constraint 2025-10-26 21:46:46 -03:00
72a5ab7c5d removing debug changes 2025-10-26 18:24:10 -03:00
89b3fdbc84 getting functions from right table now and reading os and arch in package table 2025-10-26 18:23:16 -03:00
0a531488a3 Packet.lua example test 2025-10-26 18:06:08 -03:00
7fbaef7bd4 try to clone Packet.lua 2025-10-26 18:05:57 -03:00
b411eff6f4 systemd managment for daemons 2025-10-26 18:05:34 -03:00
befa4e3ea4 changing home dir for packets user to /etc/packets (configuration folder) 2025-10-26 18:04:07 -03:00
807d9fa784 removing dependencies from table packages in database 2025-10-26 18:03:19 -03:00
9883fd92dc log messages for sockets 2025-10-26 18:02:43 -03:00
51c51b96bf bugfix, trying to read toml in a lua file, now returning Package.lua 2025-10-26 16:39:54 -03:00
a69de7e918 store buildDirs 2025-10-25 22:43:02 -03:00
4178387e2a checking if build or prepare is == nil 2025-10-25 22:42:16 -03:00
b6d7ec8a5f change dir for package dir while removing it 2025-10-25 22:41:59 -03:00
8feaf5d19b change dir for package dir to install it 2025-10-25 22:41:28 -03:00
820ffc299f code maybe confusing, but now using Packet.lua format 2025-10-25 20:17:20 -03:00
ecce74d2e9 changed old manifest.toml to Packet.lua and some improvements for future 100% Packet.lua implementation 2025-10-25 12:44:40 -03:00
5ba30c617a useless file 2025-10-25 11:16:20 -03:00
e3772d0944 some bug fixes, manifest.toml don't exist anyomre and all data for installation will be in one file name Packet.lua 2025-10-25 10:16:33 -03:00
df32178372 with afero functions need, to see more functions to use afero 2025-10-24 17:14:44 -03:00
cc9587821d modifications to build/lua.go 2025-10-24 17:04:02 -03:00
31af4d5389 new go.mod and go.sum 2025-10-24 17:01:23 -03:00
dbd63d371b new values in manifest.toml 2025-10-24 17:01:23 -03:00
52f675ab60 doing io.popen 2025-10-24 11:56:47 -03:00
26f9e20ae8 doing lua functions for build files, to run only in afero.FS 2025-10-24 11:10:43 -03:00
6377de7208 creating new build system 2025-10-23 23:04:35 -03:00
b58173837b bugfix, giving id to dependency resolver 2025-10-11 21:00:22 -03:00
97408da348 bugfix, starting a empty map for dependencies in GetPackage function 2025-10-11 19:39:20 -03:00
be96001d78 bugfix, fix command fixing leaving after remove 1 package 2025-10-11 19:38:50 -03:00
7c4fba5c86 now upgradeCmd is being used, message when downloading, and upgrade need to run as root 2025-10-11 18:50:45 -03:00
4cee062889 bugfix, fix missing wg.Add() and wg and go for upgrade async functions 2025-10-07 19:35:19 -03:00
93093382f4 bugfix, now ResolvDependencies check if depnList map is empty 2025-10-07 16:46:21 -03:00
e4b4d43163 progress doing upgrade all function 2025-10-07 11:56:24 -04:00
b89abb31df now sync needs to run as root 2025-10-06 11:55:51 -03:00
0a965c67c2 creating packets home dir 2025-10-05 18:16:15 -03:00
147fca375e implemented upgrade, and fixed some bugs 2025-10-05 15:47:21 -03:00
afc19b6e4d removing images 2025-10-05 14:31:50 -03:00
690f180687 removing web from this repository 2025-10-05 12:18:48 -03:00
7ef7b60cf5 fixed databaseschema again 2025-10-05 12:17:33 -03:00
4e2d506a01 fixing duplicate column 2025-10-05 11:42:56 -03:00
df4c76bd99 Refactor Manifest struct to change Dependencies from slice to map for better dependency management, and removing somethings from manifest struct too 2025-10-03 18:45:49 -03:00
af24fa84a2 don't need to verify index.db integrity anymore 2025-10-03 17:04:04 -03:00
4b54a9c74b Refactor database schema and update dependency handling in code 2025-10-03 17:03:23 -03:00
f25366d40c Refactor database schema and update dependency handling in code 2025-10-01 22:19:02 -03:00
cadf5fedcb Improving packets with better dependencie resolution, adding a function to auto resolve dependencies. 2025-10-01 18:11:53 -03:00
cfb11cf6e6 New database schema need to change all code files 2025-10-01 17:32:08 -03:00
bb4f221fc9 Adding "-r", to create a system user to not show up on user login screen 2025-09-29 19:21:24 -03:00
9cf5ae61d8 removing the second and useless exec.Command of useradd 2025-09-29 16:37:13 -03:00
ff4c61315e Removing unecessary param and variable on GetSandbox 2025-09-28 21:58:55 -03:00
76450789b0 io can be used, require too, and package 2025-09-28 21:55:50 -03:00
0e8db8b40e Enhance permission handling in package installation and removal commands; add user management functions for improved security. Now for every time packets will execute lua scripts, it will change process euid to an unprivileged user; Now lua scripts can execute more lua default functions 2025-09-28 21:55:13 -03:00
3591460214 Update search command description for clarity 2025-09-28 17:55:52 -03:00
96db4572b4 Add list command to manage installed packages, and search to see all packages avaiable 2025-09-28 17:55:36 -03:00
17e1b4b3ab Refactor logging and variable names for consistency; update log messages for clarity 2025-09-28 17:24:17 -03:00
73171424e4 Update dependencies: remove indirect reference to gin-gonic and add new dependencies for go-cmp, assert, and testify 2025-09-28 17:24:02 -03:00
b4f55ad36f Fixing some huge bugs, and implemented remove function 2025-09-28 16:45:51 -03:00
2c322d4de8 progress doing remove cmd, and removing GetPackage function from the pkg package, now GetPackage function can be found on package utils 2025-09-27 00:39:49 -03:00
2735749b12 Added a function to read manifest from the file manifest.toml and not only from a package file 2025-09-23 19:12:08 -03:00
05fbbde194 Setting data_dir variable to lua scripts to a string with the package data folder 2025-09-23 19:11:11 -03:00
fe81e6bf22 Revert "setting data_dir variable to a string with the package data folder"
This reverts commit 2cfe78721a.
2025-09-23 19:09:50 -03:00
2cfe78721a setting data_dir variable to a string with the package data folder 2025-09-23 19:08:21 -03:00
ff986ef943 now InstallPackage function from packets package don't try to read a config.toml, it get the path to install by a param; added async dependency install process 2025-09-21 22:52:03 -03:00
f34308367e Implement UDP socket server and add package installation check utility 2025-09-21 10:34:49 -03:00
68b394523d Add ed25519 public key and enhance package installation error handling
- Embed ed25519 public key for signature verification when doing sync prcess with servidordomal.fun
- Improve error handling in AddToInstalledDB to rollback on failure
- Update InstallPackage function to accept io.Reader instead of *os.File
2025-09-20 21:55:34 -03:00
b14bd1806a Zipping html files 2025-09-20 20:18:20 -03:00
3929493bfb enhance package database schema and configuration; add dependencies 2025-09-20 19:31:38 -03:00
2620ec00ab implement package synchronization and validation; update database schema and add error handling 2025-09-20 19:12:01 -03:00
0485b8325f new index.db schema, removed likes and reports 2025-09-20 16:05:53 -03:00
33d636b41d go.mod and go.sum with some indirect packages 2025-09-20 16:05:31 -03:00
ac236342b6 added web/ with some html and updated go.mod and go.sum to use gin 2025-09-20 13:04:32 -03:00
910cad2734 deleting old schema 2025-09-20 11:04:08 -03:00
fdb21aacc5 added .Execute to run cobracmds 2025-09-20 11:02:35 -03:00
a22a2a70c0 Database schemas added 2025-09-20 11:02:09 -03:00
f5399a66ba new index.db schema 2025-09-20 08:51:01 -03:00
9e09b1e3a4 renamed DownloadPackageHTTP function to GetFileHTTP 2025-09-19 23:33:12 -03:00
f8bda68a57 Added a const to index.db 2025-09-19 23:32:50 -03:00
b84d43200a index.db schema 2025-09-19 23:32:32 -03:00
35cbc2e47c Created copydir and copyfile functions in utils, now lua os.copy can copy an entire directory 2025-09-19 22:18:34 -03:00
3a068ed90b InstallPackage from pkg running luascript hook 2025-09-18 20:47:08 -03:00
bdbc580c82 GetSandbox aded on package utils_lua, it returns lua.LState with all sandboxfunctions 2025-09-18 20:40:05 -03:00
3c770c469d better file organization 2025-09-18 20:12:07 -03:00
1c00df24a4 Added ask for lan function 2025-09-13 23:11:48 -03:00
f3ccd6d683 Clean Install function and Download function 2025-09-13 22:57:52 -03:00
8de2eaced7 Doing organization improvements 2025-09-13 22:24:04 -03:00
c0057ca053 Deleting all to rewrite better 2025-09-13 20:45:07 -03:00
61149ae711 Added description for GetPackageByMirror function 2025-09-08 22:23:15 -03:00
bf10e39ffc Merge branch 'main' of https://github.com/roboogg133/packets 2025-09-08 22:22:07 -03:00
379f640f33 added Install function description 2025-09-08 22:22:03 -03:00
20 changed files with 1542 additions and 2793 deletions

163
README.md
View File

@@ -1,163 +0,0 @@
# 📦 Packets Custom Package Manager for Linux
> A fast and minimal package manager written in Go with Lua hooks, local network discovery, and SQLite-based indexing.
---
## 📘 Overview
**Packets** is a lightweight package manager for Linux, written in Go. It supports:
- Installation and removal of packages
- Dependency resolution and upgrading
- `.tar.zst` compressed packages with `manifest.toml` metadata
- Lua-based install/remove hooks
- Local cache with SHA-256 validation
- Peer-to-peer discovery over LAN
- Remote package syncing via HTTP
- SQLite-based local database
---
## 📁 Directory Structure
| Path | Description |
|-----------------------|----------------------------------|
| `/etc/packets/` | Configuration files |
| `/opt/packets/` | Installed package data |
| `/var/cache/packets/` | Cached `.tar.zst` package files |
(This can be changed in `/etc/packets/config.toml`)
---
# Available Commands
| Command | Description |
|---------------------------|----------------------------------------------------------------------------|
|`packets install <name>` | Install a package (resolves dependencies, executes Lua install hook) |
|`packets remove <name>` | Remove a package (executes Lua remove hook) |
|`packets upgrade <name>` | Upgrade a package by checking family and serial in the manifest |
|`packets sync [url]` | Synchronize index.db from remote HTTP source |
|`packets serve init/stop` | Starts and stop the LAN service daemon |
|`packets list` | List all installed packages |
|`packets info` | Get technical package information |
|`packets search` | List all packages in index.db |
# 📦 Package Format
Packages must be compressed as .tar.zst and include:
- ├── manifest.toml # Package metadata
- ├── data/ # Files to install
- ├── install.lua # Lua install hook
- └── remove.lua # Lua remove hook
## Example manifest.toml
[Info]
name = "packets"
version = "1.0.0"
description = "offline and online packetmanager"
dependencies = []
author = "robo"
family = "1f84ca15-5077-4f1d-a370-0ec860766eb2"
serial = 0
[Hooks]
install = "install.lua"
remove = "remove.lua"
--
# 🔄 Installation Process
- Check if package is already cached and validated via SHA-256.
- If not, search the package:
Via LAN: Sends UDP broadcast (Q:filename) to peers.
Via HTTP: Downloads from configured mirrors.
Decompress .tar.zst, install files.
Execute Lua install hook.
# 🧩 Core Features
✅ Dependency Resolution
Installs required dependencies listed in the manifest.
## 🌐 LAN Discovery
Broadcasts package request to devices in the same network via UDP.
## 📡 Remote Download
Downloads package via HTTP if not found on LAN.
## 🔒 Security
SHA-256 checksum validation
Path validation to avoid exploits (..)
Safe, sandboxed Lua runtime with limited API
# 🌍 Global Variables Available in Lua Scripts
During the execution of install.lua and remove.lua hooks, some global variables are automatically provided to the Lua environment. These help simplify file path handling and access to package-specific directories.
## Available variables:
|Name |Type | Description
|--------------------|--------|--------------------------------------------------------------------------|
|packets_package_dir | string| Absolute path to the package's data directory (e.g., /opt/packets/...) |
| packets_bin_dir | string| Path where executables should be installed (e.g., /usr/bin) |
|script | string| Path to the currently executing script (e.g., "install.lua") |
|data_dir | string| Path to the /data folder of the current package |
### Example usage in Lua:
print("Installing into: " .. packets_bin_dir)
print("Package data in: " .. data_dir)
-- Copy a binary to /usr/bin
os.copy(path_join(data_dir, "htop"), path_join(packets_bin_dir, "htop"))
These variables are preloaded in the Lua environment—no need to manually declare or initialize them.
## 🛠️ Allowed Lua API (install/remove hooks)
To ensure security, only a limited set of safe functions are exposed in Lua hooks:
os.remove(path)
os.rename(old, new)
os.copy(source, target)
os.symlink(source, target)
io.open(path, mode)
os.mkdir(path, filemode)
path_join(...)
### Note: Dangerous functions like os.execute, os.getenv, etc. are removed.
## 🗃️ Databases
index.db: Available packages (after sync)
installed.db: Packages currently installed
# ⚠️ Restrictions & Notes
Linux only (//go:build linux)
Root permissions required for most commands
Changing dataDir triggers prompt to migrate installed packages
Binaries in binDir are not automatically moved if path changes
Do not manually edit lastDataDir
# TODO
- Auto-compile packages
- An web page to upload packages

View File

@@ -1,37 +0,0 @@
package main
import (
"fmt"
"log"
"net/http"
"os"
"path/filepath"
"packets/internal"
"github.com/BurntSushi/toml"
)
type ConfigTOML struct {
Config struct {
DefaultHttpPort int `toml:"httpPort"`
DefaultCacheDir string `toml:"cacheDir"`
} `toml:"Config"`
}
func main() {
internal.PacketsPackageDir()
var cfg ConfigTOML
toml.Decode(filepath.Join(internal.PacketsPackageDir(), "config.toml"), &cfg)
pid := os.Getpid()
if err := os.WriteFile(filepath.Join(internal.PacketsPackageDir(), "http.pid"), []byte(fmt.Sprint(pid)), 0644); err != nil {
fmt.Println("error saving subprocess pid", err)
}
fs := http.FileServer(http.Dir(cfg.Config.DefaultCacheDir))
http.Handle("/", fs)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", cfg.Config.DefaultHttpPort), nil))
}

154
cmd/main.go Normal file
View File

@@ -0,0 +1,154 @@
package main
import (
"log"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"github.com/go-git/go-git/v6"
"github.com/roboogg133/packets/pkg/install"
"github.com/roboogg133/packets/pkg/packet.lua.d"
)
const bipath = "/usr/bin"
func main() {
log.SetFlags(log.Llongfile)
switch os.Args[1] {
case "install":
f, err := os.ReadFile(os.Args[2])
if err != nil {
log.Fatal(err)
}
options := &packet.Config{
BinDir: bipath,
}
pkg, err := packet.ReadPacket(f, options)
if err != nil {
log.Fatal(err)
}
pkgId := pkg.Name + "@" + pkg.Version
if err := os.MkdirAll("_pkgtest/"+pkgId, 0777); err != nil {
log.Fatal(err)
}
os.MkdirAll("_pkgtest/"+pkgId+"/src", 0777)
os.MkdirAll("_pkgtest/"+pkgId+"/packet", 0777)
if pkg.Plataforms != nil {
tmp := *pkg.Plataforms
plataform := tmp[packet.OperationalSystem(runtime.GOOS)]
for _, v := range *plataform.Sources {
src, err := packet.GetSource(v.Url, v.Method, v.Specs, 5)
if err != nil {
log.Fatal(err)
}
if v.Method == "GET" || v.Method == "POST" {
f := src.([]byte)
if err := os.WriteFile("_pkgtest/"+pkgId+"/"+path.Base(v.Url), f, 0777); err != nil {
log.Fatal(err)
}
if err := packet.Dearchive("_pkgtest/"+pkgId+"/"+path.Base(v.Url), "_pkgtest/"+pkgId+"/src"); err != nil {
log.Fatal(err)
}
os.Remove("_pkgtest/" + pkgId + "/" + path.Base(v.Url))
} else {
result, err := packet.GetSource(v.Url, v.Method, v.Specs, -213123)
if err != nil {
log.Fatal(err)
}
reponame, _ := strings.CutSuffix(path.Base(v.Url), ".git")
_, err = git.PlainClone("_pkgtest/"+pkgId+"/src/"+reponame, result.(*git.CloneOptions))
if err != nil {
log.Fatal(err)
}
}
}
}
if pkg.GlobalSources != nil {
for _, v := range *pkg.GlobalSources {
src, err := packet.GetSource(v.Url, v.Method, v.Specs, 5)
if err != nil {
log.Fatal(err)
}
if v.Method == "GET" || v.Method == "POST" {
f := src.([]byte)
if err := os.WriteFile("_pkgtest/"+pkgId+"/"+path.Base(v.Url), f, 0777); err != nil {
log.Fatal(err)
}
if err := packet.Dearchive("_pkgtest/"+pkgId+"/"+path.Base(v.Url), "_pkgtest/"+pkgId+"/src"); err != nil {
log.Fatal(err)
}
os.Remove("_pkgtest/" + pkgId + "/" + path.Base(v.Url))
} else {
result, err := packet.GetSource(v.Url, v.Method, v.Specs, -213123)
if err != nil {
log.Fatal(err)
}
reponame, _ := strings.CutSuffix(path.Base(v.Url), ".git")
_, err = git.PlainClone("_pkgtest/"+pkgId+"/src/"+reponame, result.(*git.CloneOptions))
if err != nil {
log.Fatal(err)
}
}
}
}
packetdir, err := filepath.Abs("_pkgtest/" + pkgId + "/packet")
if err != nil {
log.Fatal(err)
}
srcdir, err := filepath.Abs("_pkgtest/" + pkgId + "/src")
if err != nil {
log.Fatal(err)
}
rootdir, err := filepath.Abs("_pkgtest/" + pkgId)
if err != nil {
log.Fatal(err)
}
pkg.ExecuteBuild(&packet.Config{
BinDir: bipath,
PacketDir: packetdir,
SourcesDir: srcdir,
RootDir: rootdir,
})
pkg.ExecuteInstall(&packet.Config{
BinDir: bipath,
PacketDir: packetdir,
SourcesDir: srcdir,
RootDir: rootdir,
})
files, err := install.GetPackageFiles(packetdir)
if err != nil {
log.Fatal(err)
}
if err := install.InstallFiles(files, packetdir); err != nil {
log.Fatal(err)
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,65 +0,0 @@
package main
import (
"fmt"
"log"
"net"
"os"
"packets/internal"
"path/filepath"
"strings"
"github.com/BurntSushi/toml"
)
type ConfigTOML struct {
Config struct {
HttpPort int `toml:"httpPort"`
CacheDir string `toml:"cacheDir"`
} `toml:"Config"`
}
var cfg ConfigTOML
func CheckDownloaded(filename string) bool {
_, err := os.Stat(filepath.Join(cfg.Config.CacheDir))
if os.IsNotExist(err) {
return false
} else {
return true
}
}
func main() {
pid := os.Getpid()
if err := os.WriteFile(filepath.Join(internal.PacketsPackageDir(), "udp.pid"), []byte(fmt.Sprint(pid)), 0644); err != nil {
fmt.Println("error saving subprocess pid", err)
}
toml.Decode(filepath.Join(internal.PacketsPackageDir(), "config.toml"), &cfg)
addr := net.UDPAddr{IP: net.IPv4zero, Port: 1333}
conn, err := net.ListenUDP("udp", &addr)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
buf := make([]byte, 1500)
for {
n, remote, err := conn.ReadFromUDP(buf)
if err != nil {
log.Println("error creating udp socket", err)
}
msg := string(buf[:n])
if !strings.HasPrefix(msg, "Q:") {
continue
}
filename := strings.TrimPrefix(msg, "Q:")
if CheckDownloaded(filename) {
reply := fmt.Sprintf("H:%s:%d", filename, cfg.Config.HttpPort)
conn.WriteToUDP([]byte(reply), remote)
}
}
}

View File

@@ -1 +0,0 @@
-- PACKETS SCRIPTS EXAMPLES

45
go.mod
View File

@@ -1,31 +1,28 @@
module packets
module github.com/roboogg133/packets
go 1.24.4
go 1.25.3
require github.com/yuin/gopher-lua v1.1.1
require (
github.com/BurntSushi/toml v1.5.0
github.com/klauspost/compress v1.18.0
github.com/schollz/progressbar/v3 v3.18.0
github.com/spf13/cobra v1.9.1
github.com/yuin/gopher-lua v1.1.1
golang.org/x/net v0.41.0
modernc.org/sqlite v1.38.0
github.com/go-git/go-git/v6 v6.0.0-20251029213217-0bbfc0875edd
github.com/klauspost/compress v1.18.1
)
require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/spf13/pflag v1.0.7 // indirect
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/term v0.32.0 // indirect
modernc.org/libc v1.65.10 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/cyphar/filepath-securejoin v0.5.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/go-git/gcfg/v2 v2.0.2 // indirect
github.com/go-git/go-billy/v6 v6.0.0-20251022185412-61e52df296a5 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/kevinburke/ssh_config v1.4.0 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/pjbgf/sha1cd v0.5.0 // indirect
github.com/sergi/go-diff v1.4.0 // indirect
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/net v0.46.0 // indirect
golang.org/x/sys v0.37.0 // indirect
)

135
go.sum
View File

@@ -1,85 +1,68 @@
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cyphar/filepath-securejoin v0.5.0 h1:hIAhkRBMQ8nIeuVwcAoymp7MY4oherZdAxD+m0u9zaw=
github.com/cyphar/filepath-securejoin v0.5.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/go-git/gcfg/v2 v2.0.2 h1:MY5SIIfTGGEMhdA7d7JePuVVxtKL7Hp+ApGDJAJ7dpo=
github.com/go-git/gcfg/v2 v2.0.2/go.mod h1:/lv2NsxvhepuMrldsFilrgct6pxzpGdSRC13ydTLSLs=
github.com/go-git/go-billy/v6 v6.0.0-20251022185412-61e52df296a5 h1:9nXOQ3HupDEerUXxiPrw3olFy/jHGZ3O3DyM/o6ejdc=
github.com/go-git/go-billy/v6 v6.0.0-20251022185412-61e52df296a5/go.mod h1:TpCYxdQ0tWZkrnAkd7yqK+z1C8RKcyjcaYAJNAcnUnM=
github.com/go-git/go-git-fixtures/v5 v5.1.1 h1:OH8i1ojV9bWfr0ZfasfpgtUXQHQyVS8HXik/V1C099w=
github.com/go-git/go-git-fixtures/v5 v5.1.1/go.mod h1:Altk43lx3b1ks+dVoAG2300o5WWUnktvfY3VI6bcaXU=
github.com/go-git/go-git/v6 v6.0.0-20251029213217-0bbfc0875edd h1:pn6+tR4O8McyqEr2MbQwqcySovpG8jDd11F/jQ6aAfA=
github.com/go-git/go-git/v6 v6.0.0-20251029213217-0bbfc0875edd/go.mod h1:z9pQiXCfyOZIs/8qa5zmozzbcsDPtGN91UD7+qeX3hk=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ=
github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA=
github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.3.3 h1:3qaU+7f7xxTUmvU1pJTZiDLAIoJVdUSSauJNHg9yXoA=
modernc.org/fileutil v1.3.3/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/libc v1.65.10 h1:ZwEk8+jhW7qBjHIT+wd0d9VjitRyQef9BnzlzGwMODc=
modernc.org/libc v1.65.10/go.mod h1:StFvYpx7i/mXtBAfVOjaU0PWZOvIRoZSgXhrwXzr8Po=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.38.0 h1:+4OrfPQ8pxHKuWG4md1JpR/EYAh3Md7TdejuuzE7EUI=
modernc.org/sqlite v1.38.0/go.mod h1:1Bj+yES4SVvBZ4cBOpVZ6QgesMCKpJZDq0nxYzOpmNE=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=

View File

@@ -1,557 +0,0 @@
package internal
import (
"archive/tar"
"fmt"
"io"
"io/fs"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/BurntSushi/toml"
"github.com/klauspost/compress/zstd"
lua "github.com/yuin/gopher-lua"
)
var AllowedCmds = map[string]string{
"go": "go", // "Go code compiler"
"gcc": "gcc", // "C"
"g++": "g++", // "C++"
"rustc": "rustc", // "Rust"
"javac": "javac", // "Java"
"luac": "luac", // "Lua"
"pyinstaller": "pyinstaller", // "Python"
"kotlinc": "kotlinc", // "Kotlin"
"mcs": "mcs", // "C# compiler"
"swiftc": "swiftc", // "Swift compiler"
"ts": "tsc", // "TypeScript compiler"
"ruby": "rubyc", // "Ruby compiler"
}
type ConfigTOML struct {
Config struct {
HttpPort int `toml:"httpPort"`
CacheDir string `toml:"cacheDir"`
AutoDeleteCacheDir bool `toml:"dayToDeleteCacheDir"`
DaysToDelete int `toml:"daysToDelete"`
DataDir string `toml:"dataDir"`
BinDir string `toml:"binDir"`
LastDataDir string `toml:"lastDataDir"`
} `toml:"Config"`
}
type Manifest struct {
Info struct {
Name string `toml:"name"`
Version string `toml:"version"`
Description string `toml:"description"`
Dependencies []string `toml:"dependencies"`
Author string `toml:"author"`
Family string `toml:"family"`
Serial uint `toml:"serial"`
} `toml:"Info"`
Hooks struct {
Install string `toml:"install"`
Remove string `toml:"remove"`
} `toml:"Hooks"`
}
var SandboxDir string
func PacketsPackageDir() string {
out, _ := exec.Command("uname", "-s").Output()
if uname := strings.TrimSpace(string(out)); uname == "J2ME" {
_, err := os.Stat("packets.help")
if os.IsNotExist(err) {
err = nil
var thedirectory string
err := filepath.WalkDir("/mnt", func(path string, d fs.DirEntry, err error) error {
if d.IsDir() {
thedirectory = filepath.Join(path, "packets")
if err := os.Mkdir(thedirectory, 0644); err != nil {
return err
}
if err := os.WriteFile("packets.help", []byte(thedirectory), 0644); err != nil {
return err
}
if err := os.Mkdir(filepath.Join(filepath.Join(thedirectory, "cache")), 0644); err != nil {
return err
}
if err := os.Mkdir(filepath.Join(filepath.Join(thedirectory, "packages")), 0644); err != nil {
return err
}
if err := os.Mkdir(filepath.Join(filepath.Join(thedirectory, "bin")), 0644); err != nil {
return err
}
return nil
}
return nil
})
if err != nil {
log.Fatal(err)
}
return thedirectory
}
byt, err := os.ReadFile("packets.help")
if err != nil {
log.Fatal(err)
}
return string(byt)
} else {
return "/etc/packets"
}
}
func ManifestReadXZ(path string) (*Manifest, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
zr, err := zstd.NewReader(f)
if err != nil {
return nil, err
}
defer zr.Close()
tarReader := tar.NewReader(zr)
for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
if filepath.Base(header.Name) == "manifest.toml" {
decoder := toml.NewDecoder(tarReader)
var manifest Manifest
if _, err := decoder.Decode(&manifest); err != nil {
log.Fatal(err)
}
return &manifest, nil
}
}
return nil, fmt.Errorf("can't find manifest.toml")
}
func DefaultConfigTOML() *ConfigTOML {
var cfg ConfigTOML
out, _ := exec.Command("uname", "-s").Output()
if uname := strings.TrimSpace(string(out)); uname == "J2ME" {
cfg.Config.HttpPort = 9123
cfg.Config.AutoDeleteCacheDir = false
cfg.Config.CacheDir = filepath.Join(PacketsPackageDir(), "cache")
cfg.Config.DataDir = filepath.Join(PacketsPackageDir(), "data")
cfg.Config.DaysToDelete = -1
cfg.Config.BinDir = filepath.Join(PacketsPackageDir(), "bin")
cfg.Config.LastDataDir = filepath.Join(PacketsPackageDir(), "data")
return &cfg
} else {
cfg.Config.HttpPort = 9123
cfg.Config.AutoDeleteCacheDir = false
cfg.Config.CacheDir = "/var/cache/packets"
cfg.Config.DataDir = "/opt/packets"
cfg.Config.DaysToDelete = -1
cfg.Config.BinDir = "/usr/bin"
cfg.Config.LastDataDir = "/opt/packets"
return &cfg
}
}
func IsSafe(str string) bool {
s, err := filepath.EvalSymlinks(filepath.Clean(str))
if err != nil {
s = filepath.Clean(str)
}
var cfg ConfigTOML
toml.DecodeFile(filepath.Join(PacketsPackageDir(), "config.toml"), &cfg)
if strings.HasPrefix(s, cfg.Config.DataDir) || strings.HasPrefix(s, cfg.Config.BinDir) {
return true
} else if strings.Contains(s, ".ssh") {
return false
} else if strings.HasPrefix(s, "/etc") {
return false
} else if strings.HasPrefix(s, "/usr") || strings.HasPrefix(s, "/bin") {
fmt.Println(s, "está dentro de usr")
return strings.HasPrefix(s, "/usr/share")
} else if strings.HasPrefix(s, "/var/mail") {
return false
} else if strings.HasPrefix(s, "/proc") {
return false
} else if strings.HasPrefix(s, "/sys") {
return false
} else if strings.HasPrefix(s, "/var/run") || strings.HasPrefix(s, "/run") {
return false
} else if strings.HasPrefix(s, "/tmp") {
return false
} else if strings.HasPrefix(s, "/dev") {
return false
} else if strings.HasPrefix(s, "/boot") {
return false
} else if strings.HasPrefix(s, "/home") {
if strings.Contains(s, "/Pictures") || strings.Contains(s, "/Videos") || strings.Contains(s, "/Documents") || strings.Contains(s, "/Downloads") {
return false
}
} else if strings.HasPrefix(s, "/lib") || strings.HasPrefix(s, "/lib64") || strings.HasPrefix(s, "/var/lib64") || strings.HasPrefix(s, "/lib") {
return false
} else if strings.HasPrefix(s, "/sbin") {
return false
} else if strings.HasPrefix(s, "/srv") {
return false
} else if strings.HasPrefix(s, "/mnt") {
return false
} else if strings.HasPrefix(s, "/media") {
return false
} else if strings.HasPrefix(s, "/snap") {
return false
}
return true
}
func SafeRemove(L *lua.LState) int {
filename := L.CheckString(1)
if !IsSafe(filename) {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] unsafe filepath"))
return 2
}
err := os.RemoveAll(filename)
if err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] remove failed\n" + err.Error()))
return 2
}
L.Push(lua.LTrue)
L.Push(lua.LNil)
return 2
}
func SafeRename(L *lua.LState) int {
oldname := L.CheckString(1)
newname := L.CheckString(2)
if !IsSafe(oldname) || !IsSafe(newname) {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] unsafe filepath"))
return 2
}
if err := os.Rename(oldname, newname); err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] rename failed\n" + err.Error()))
return 2
}
L.Push(lua.LTrue)
return 1
}
func SafeCopy(L *lua.LState) int {
oldname := L.CheckString(1)
newname := L.CheckString(2)
if !IsSafe(oldname) || !IsSafe(newname) {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] unsafe filepath"))
return 2
}
src, err := os.Open(oldname)
if err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] copy failed\n" + err.Error()))
return 2
}
defer src.Close()
status, err := src.Stat()
if err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] copy failed\n" + err.Error()))
return 2
}
err = os.MkdirAll(filepath.Dir(newname), 0755)
if err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] copy failed\n" + err.Error()))
return 2
}
dst, err := os.Create(newname)
if err != nil {
if !os.IsExist(err) {
dst, err = os.Open(newname)
if err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] copy failed\n" + err.Error()))
return 2
}
} else {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] copy failed\n" + err.Error()))
return 2
}
}
defer dst.Close()
if err := dst.Chmod(status.Mode()); err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] copy failed\n" + err.Error()))
return 2
}
_, err = io.Copy(dst, src)
if err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] copy failed\n" + err.Error()))
return 2
}
L.Push(lua.LTrue)
L.Push(lua.LNil)
return 2
}
func SymbolicLua(L *lua.LState) int {
fileName := L.CheckString(1)
destination := L.CheckString(2)
if !IsSafe(fileName) || !IsSafe(destination) {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] unsafe filepath"))
return 2
}
_ = os.RemoveAll(destination)
if err := os.Symlink(fileName, destination); err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] symlink failed\n" + err.Error()))
return 2
}
L.Push(lua.LTrue)
L.Push(lua.LNil)
return 2
}
func modeFlags(mode string) int {
switch mode {
case "r", "rb":
return os.O_RDONLY
case "w", "wb":
return os.O_CREATE | os.O_WRONLY | os.O_TRUNC
case "a", "ab":
return os.O_CREATE | os.O_WRONLY | os.O_APPEND
case "r+", "r+b", "rb+", "br+":
return os.O_RDWR
case "w+", "w+b", "wb+", "bw+":
return os.O_CREATE | os.O_RDWR | os.O_TRUNC
case "a+", "a+b", "ab+", "ba+":
return os.O_CREATE | os.O_RDWR | os.O_APPEND
default:
return os.O_RDONLY
}
}
func SafeOpen(L *lua.LState) int {
path := L.CheckString(1)
mode := L.OptString(2, "r")
if !IsSafe(path) {
L.Push(lua.LNil)
L.Push(lua.LString("[packets] unsafe filepath"))
return 2
}
file, err := os.OpenFile(path, modeFlags(mode), 0644)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString("[packets] open failed\n" + err.Error()))
return 2
}
ud := L.NewUserData()
ud.Value = file
L.SetMetatable(ud, L.GetTypeMetatable("file"))
L.Push(ud)
L.Push(lua.LNil)
return 2
}
func Ljoin(L *lua.LState) int {
n := L.GetTop()
parts := make([]string, 0, n)
for i := 1; i <= n; i++ {
val := L.Get(i)
parts = append(parts, val.String())
}
result := filepath.Join(parts...)
L.Push(lua.LString(result))
return 1
}
func LMkdir(L *lua.LState) int {
path := L.CheckString(1)
perm := L.CheckInt(2)
if !IsSafe(path) {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] unsafe filepath\n"))
return 2
}
if err := os.MkdirAll(path, os.FileMode(perm)); err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] mkdir failed\n" + err.Error()))
return 2
}
L.Push(lua.LTrue)
L.Push(lua.LNil)
return 2
}
func LuaCompile(L *lua.LState) int {
lang := L.CheckString(1)
args := []string{}
for i := 2; i <= L.GetTop(); i++ {
if strings.Contains(L.CheckString(i), "/") {
tryintoacess, err := filepath.Abs(filepath.Clean(filepath.Join(SandboxDir, L.CheckString(i))))
if err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] invalid filepath\n" + err.Error()))
return 2
}
fmt.Printf("sandboxdir: (%s) acessto: (%s)\n", SandboxDir, tryintoacess)
rel, err := filepath.Rel(SandboxDir, tryintoacess)
if err != nil || strings.HasPrefix(rel, "..") {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] unsafe filepath"))
return 2
}
}
args = append(args, L.CheckString(i))
}
bin, suc := AllowedCmds[lang]
if !suc {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] unsupported language"))
return 2
}
cmd := exec.Command(bin, args...)
cmd.Dir = SandboxDir
out, err := cmd.CombinedOutput()
if err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] compile failed\n" + err.Error() + "\n" + string(out)))
return 2
}
if err := cmd.Run(); err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] compile failed\n" + err.Error()))
return 2
}
L.Push(lua.LTrue)
L.Push(lua.LString(string(out)))
return 2
}
func CompileRequirements(L *lua.LState) int {
cmdLang := L.CheckString(1)
if strings.Contains(L.CheckString(2), "/") {
tryintoacess, err := filepath.Abs(filepath.Clean(L.CheckString(2)))
if err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] invalid filepath\n" + err.Error()))
return 2
}
if !strings.HasPrefix(tryintoacess, SandboxDir) {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] unsafe filepath"))
return 2
}
}
var err error
switch cmdLang {
case "python":
cmd := exec.Command("pip", "install", "--target", filepath.Join(SandboxDir, "tmp/build"), "-r", L.CheckString(2))
cmd.Dir = filepath.Join(SandboxDir, "data")
err = cmd.Run()
case "java":
cmd := exec.Command("mvn", "dependency:copy-dependencies", "-DoutputDirectory="+filepath.Join(SandboxDir, "tmp/build"))
cmd.Dir = L.CheckString(2)
err = cmd.Run()
case "ruby":
cmd := exec.Command("bundle", "install", "--path", filepath.Join(SandboxDir, "tmp/build"))
cmd.Dir = L.CheckString(2)
err = cmd.Run()
}
if err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString("[packets] requirements install failed\n" + err.Error()))
return 2
}
L.Push(lua.LTrue)
L.Push(lua.LNil)
return 2
}

View File

@@ -0,0 +1,150 @@
package lua
import (
"log"
"os"
"path/filepath"
lua "github.com/yuin/gopher-lua"
)
func LRemove(L *lua.LState) int {
filename := L.CheckString(1)
err := os.RemoveAll(filename)
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 LRename(L *lua.LState) int {
oldname := L.CheckString(1)
newname := L.CheckString(2)
if err := os.Rename(oldname, newname); err != nil {
L.Push(lua.LFalse)
L.Push(lua.LString(err.Error()))
return 2
}
L.Push(lua.LTrue)
return 1
}
func LCopy(L *lua.LState) int {
oldname := L.CheckString(1)
newname := L.CheckString(2)
os.MkdirAll(filepath.Dir(newname), 0755)
if err := copyDir(oldname, newname); 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 LSymlink(L *lua.LState) int {
fileName := L.CheckString(1)
destination := L.CheckString(2)
_ = os.RemoveAll(destination)
if err := os.Symlink(fileName, destination); 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 Ljoin(L *lua.LState) int {
n := L.GetTop()
parts := make([]string, 0, n)
for i := 1; i <= n; i++ {
val := L.Get(i)
parts = append(parts, val.String())
}
result := filepath.Join(parts...)
L.Push(lua.LString(result))
return 1
}
func LMkdir(L *lua.LState) int {
path := L.CheckString(1)
perm := L.CheckInt(2)
if err := os.MkdirAll(path, os.FileMode(perm)); 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 LError(L *lua.LState) int {
n := L.GetTop()
parts := make([]any, 0, n)
for i := 1; i <= n; i++ {
val := L.Get(i)
parts = append(parts, val.String())
}
llogger().Panic(parts...)
return 0
}
func LSetEnv(L *lua.LState) int {
env := L.CheckString(1)
value := L.CheckString(2)
os.Setenv(env, value)
return 0
}
func LCD(L *lua.LState) int {
dir := L.CheckString(1)
if err := os.Chdir(dir); 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 LChmod(L *lua.LState) int {
f := L.CheckString(1)
mode := L.CheckInt(2)
if err := os.Chmod(f, os.FileMode(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 llogger() *log.Logger { return log.New(os.Stderr, "script error: ", 0) }

95
internal/lua/utils.go Normal file
View File

@@ -0,0 +1,95 @@
package lua
import (
"io"
"os"
"path/filepath"
)
func copyDir(src string, dest string) error {
if stats, err := os.Stat(src); err != nil {
return err
} else {
if stats.IsDir() {
files, err := os.ReadDir(src)
if err != nil {
return err
}
if err := os.MkdirAll(dest, 0755); err != nil {
return err
}
for _, file := range files {
if file.IsDir() {
copyDir(filepath.Join(src, file.Name()), filepath.Join(dest, file.Name()))
continue
}
srcFile := filepath.Join(src, file.Name())
f, err := os.Create(filepath.Join(dest, file.Name()))
if err != nil {
return err
}
defer f.Close()
opennedSrcFile, err := os.Open(srcFile)
if err != nil {
return err
}
defer opennedSrcFile.Close()
if _, err := io.Copy(f, opennedSrcFile); err != nil {
return err
}
}
} else {
if err := copyFile(src, dest); err != nil {
return err
}
}
}
return nil
}
func copyFile(source string, destination string) error {
src, err := os.Open(source)
if err != nil {
return err
}
defer src.Close()
status, err := src.Stat()
if err != nil {
return err
}
err = os.MkdirAll(filepath.Dir(destination), 0o755)
if err != nil {
return err
}
dst, err := os.Create(destination)
if err != nil {
if !os.IsExist(err) {
dst, err = os.Open(destination)
if err != nil {
return err
}
} else {
return err
}
}
defer dst.Close()
if err := dst.Chmod(status.Mode()); err != nil {
return err
}
_, err = io.Copy(dst, src)
if err != nil {
return err
}
return nil
}

10
main.go Normal file
View File

@@ -0,0 +1,10 @@
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println(runtime.GOARCH)
}

98
pkg/install/main.go Normal file
View File

@@ -0,0 +1,98 @@
package install
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
type BasicFileStatus struct {
Filepath string
PermMode os.FileMode
IsDir bool
}
func GetPackageFiles(packetDir string) ([]BasicFileStatus, error) {
return walkAll(packetDir)
}
func walkAll(dirToWalk string) ([]BasicFileStatus, error) {
var filesSlice []BasicFileStatus
files, err := os.ReadDir(dirToWalk)
if err != nil {
return []BasicFileStatus{}, err
}
for _, v := range files {
basicStat := &BasicFileStatus{
Filepath: filepath.Join(dirToWalk, v.Name()),
PermMode: v.Type().Perm(),
IsDir: v.IsDir(),
}
filesSlice = append(filesSlice, *basicStat)
if v.IsDir() {
filesSlice, err = walkAll(filepath.Join(dirToWalk, v.Name()))
if err != nil {
return []BasicFileStatus{}, err
}
}
}
return filesSlice, nil
}
func InstallFiles(files []BasicFileStatus, packetDir string) error {
for i, v := range files {
sysPath, _ := strings.CutPrefix(v.Filepath, packetDir)
fmt.Printf("[%d] Installing file %s\n", i, v.Filepath)
fmt.Printf("[%d] NEED tro track file %s\n", i, sysPath)
if err := copyFile(v.Filepath, sysPath); err != nil {
return err
}
}
return nil
}
func copyFile(source string, destination string) error {
src, err := os.Open(source)
if err != nil {
return err
}
defer src.Close()
status, err := src.Stat()
if err != nil {
return err
}
err = os.MkdirAll(filepath.Dir(destination), 0o755)
if err != nil {
return err
}
dst, err := os.Create(destination)
if err != nil {
if !os.IsExist(err) {
dst, err = os.Open(destination)
if err != nil {
return err
}
} else {
return err
}
}
defer dst.Close()
if err := dst.Chmod(status.Mode()); err != nil {
return err
}
_, err = io.Copy(dst, src)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,344 @@
package packet
import (
"strings"
lua "github.com/yuin/gopher-lua"
)
func getStringFromTable(table *lua.LTable, key string) string {
value := table.RawGetString(key)
if value.Type() == lua.LTString {
return value.String()
}
return ""
}
func getIntFromTable(table *lua.LTable, key string) int {
value := table.RawGetString(key)
if value.Type() == lua.LTNumber {
if num, ok := value.(lua.LNumber); ok {
return int(num)
}
}
return -133
}
func getStringArrayFromTable(table *lua.LTable, key string) []string {
value := table.RawGetString(key)
if value.Type() != lua.LTTable {
return []string{}
}
arrayTable := value.(*lua.LTable)
var result []string
arrayTable.ForEach(func(_, value lua.LValue) {
if value.Type() == lua.LTString {
result = append(result, value.String())
}
})
return result
}
func getFunctionFromTable(table *lua.LTable, key string) *lua.LFunction {
value := table.RawGetString(key)
if value.Type() == lua.LTFunction {
return value.(*lua.LFunction)
}
return nil
}
type version struct {
Name string
Constraint VersionConstraint
}
func getDependenciesFromTable(table *lua.LTable, key string) *PkgDependencies {
value := table.RawGetString(key)
if value.Type() != lua.LTTable {
return &PkgDependencies{}
}
var pkgDeps PkgDependencies
depnTable := value.(*lua.LTable)
pkgDeps.RuntimeDependencies = depsParse(depnTable, "runtime")
pkgDeps.BuildDependencies = depsParse(depnTable, "build")
pkgDeps.Conflicts = depsParse(depnTable, "conflicts")
return &pkgDeps
}
func getSourcesFromTable(table *lua.LTable, key string) *[]Source {
value := table.RawGetString(key)
if value.Type() != lua.LTTable {
return nil
}
var srcList []Source
srcTable := value.(*lua.LTable)
srcTable.ForEach(func(_, value lua.LValue) {
if value.Type() == lua.LTTable {
src := value.(*lua.LTable)
var srcInfo Source
method := src.RawGetString("method")
if method.Type() == lua.LTString {
srcInfo.Method = method.String()
}
url := src.RawGetString("url")
if url.Type() == lua.LTString {
srcInfo.Url = url.String()
}
switchlabel:
switch srcInfo.Method {
case "GET":
var getSpecs GETSpecs
getSpecs.SHA256 = new(string)
sha256sumL := src.RawGetString("sha256")
if sha256sumL.Type() == lua.LTString {
*getSpecs.SHA256 = sha256sumL.String()
}
headersLT := src.RawGetString("headers")
if headersLT.Type() == lua.LTTable {
headers := headersLT.(*lua.LTable)
tmpMap := make(map[string]string)
headers.ForEach(func(headerKey, value lua.LValue) {
if value.Type() == lua.LTString {
tmpMap[headerKey.String()] = value.String()
}
})
getSpecs.Headers = &tmpMap
}
srcInfo.Specs = getSpecs
break switchlabel
case "git":
var gitSpecs GitSpecs
branchL := src.RawGetString("branch")
if branchL.Type() == lua.LTString {
gitSpecs.Branch = branchL.String()
}
tagL := src.RawGetString("tag")
if tagL.Type() == lua.LTString {
*gitSpecs.Tag = tagL.String()
}
srcInfo.Specs = gitSpecs
break switchlabel
case "POST":
var postSpecs POSTSpecs
sha256sumL := src.RawGetString("sha256")
if sha256sumL.Type() == lua.LTString {
*postSpecs.SHA256 = sha256sumL.String()
}
headersLT := src.RawGetString("headers")
if headersLT.Type() == lua.LTTable {
headers := headersLT.(*lua.LTable)
tmpMap := make(map[string]string)
headers.ForEach(func(headerKey, value lua.LValue) {
if value.Type() == lua.LTString {
tmpMap[headerKey.String()] = value.String()
}
})
postSpecs.Headers = &tmpMap
}
bodyLt := src.RawGetString("body")
if bodyLt.Type() == lua.LTString {
*postSpecs.Body = bodyLt.String()
}
srcInfo.Specs = postSpecs
break switchlabel
}
srcList = append(srcList, srcInfo)
}
})
return &srcList
}
func getPlataformsFromTable(table *lua.LTable, key string) *map[OperationalSystem]Plataform {
value := table.RawGetString(key)
if value.Type() != lua.LTTable {
return nil
}
tmpMap := make(map[OperationalSystem]Plataform)
plataform := value.(*lua.LTable)
plataform.ForEach(func(osString, value lua.LValue) {
if value.Type() != lua.LTTable {
return
}
var plat Plataform
plat.Architetures = getStringArrayFromTable(value.(*lua.LTable), "arch")
plat.Name = osString.String()
plat.Sources = getSourcesFromTable(value.(*lua.LTable), "sources")
plat.Dependencies = getDependenciesFromTable(value.(*lua.LTable), "dependencies")
tmpMap[OperationalSystem(osString.String())] = plat
})
if len(tmpMap) == 0 {
return nil
}
return &tmpMap
}
func depsParse(depnTable *lua.LTable, key string) *map[string]*VersionConstraint {
if runLTable := depnTable.RawGetString(key); runLTable.Type() == lua.LTTable {
runtimeTable := runLTable.(*lua.LTable)
mapTemp := make(map[string]*VersionConstraint)
var found bool
runtimeTable.ForEach(func(_, value lua.LValue) {
if value.Type() == lua.LTString {
version := parseVersionString(value.String())
mapTemp[version.Name] = &version.Constraint
found = true
}
})
if !found {
return nil
} else {
return &mapTemp
}
}
return nil
}
func parseVersionString(s string) version {
// >=go@1.25.3 | <=go@1.25.3 | go | >go@1.25.3 | <go@1.25.3 | go@1.25.3
if strings.ContainsAny(s, "@") {
slice := strings.Split(s, "@")
switch {
case !strings.ContainsAny(s, "<=>"):
return version{
Name: slice[0],
Constraint: VersionConstraint(slice[1]),
}
case s[0] == '>' && s[1] == '=':
return version{
Name: slice[0][2:],
Constraint: VersionConstraint(">=" + slice[1]),
}
case s[0] == '<' && s[1] == '=':
return version{
Name: slice[0][2:],
Constraint: VersionConstraint("<=" + slice[1]),
}
case s[0] == '>' && s[1] != '=':
return version{
Name: slice[0][1:],
Constraint: VersionConstraint(">" + slice[1]),
}
case s[0] == '<' && s[1] != '=':
return version{
Name: slice[0][1:],
Constraint: VersionConstraint("<" + slice[1]),
}
}
} else if !strings.ContainsAny(s, "@=<>") {
return version{
Name: s,
Constraint: VersionConstraint(0x000),
}
}
return version{}
}
func normalizeArch(arch string) string {
switch arch {
case "386":
return "i686"
case "amd64":
return "x86_64"
case "amd64p32":
return "x86_64"
case "arm":
return "arm"
case "arm64":
return "aarch64"
case "arm64be":
return "aarch64_be"
case "armbe":
return "armbe"
case "loong64":
return "loongarch64"
case "mips":
return "mips"
case "mips64":
return "mips64"
case "mips64le":
return "mips64el"
case "mips64p32":
return "mips64"
case "mips64p32le":
return "mips64el"
case "mipsle":
return "mipsel"
case "ppc":
return "powerpc"
case "ppc64":
return "ppc64"
case "ppc64le":
return "ppc64le"
case "riscv":
return "riscv"
case "riscv64":
return "riscv64"
case "s390":
return "s390"
case "s390x":
return "s390x"
case "sparc":
return "sparc"
case "sparc64":
return "sparc64"
case "wasm":
return "wasm"
default:
return arch
}
}

View File

@@ -0,0 +1,33 @@
package packet
import "path/filepath"
type Config struct {
BinDir string
PacketDir string
SourcesDir string
RootDir string
}
const defaultBinDir = "/usr/bin"
func checkConfig(cfg *Config) *Config {
if cfg == nil {
bin := defaultBinDir
return &Config{
BinDir: bin,
}
}
switch {
case cfg.BinDir == "":
return &Config{
BinDir: defaultBinDir,
}
case cfg.PacketDir == "":
cfg.PacketDir = filepath.Join("/tmp", randStringBytes(12))
}
return cfg
}

374
pkg/packet.lua.d/main.go Normal file
View File

@@ -0,0 +1,374 @@
package packet
import (
"archive/tar"
"bytes"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"runtime"
"time"
"github.com/go-git/go-git/v6"
"github.com/go-git/go-git/v6/plumbing"
"github.com/klauspost/compress/zstd"
lua_utils "github.com/roboogg133/packets/internal/lua"
lua "github.com/yuin/gopher-lua"
)
type OperationalSystem string
type PacketLua struct {
Name string
Version string
Maintaner string
Description string
Serial int
Plataforms *map[OperationalSystem]Plataform
GlobalSources *[]Source
GlobalDependencies *PkgDependencies
Build *lua.LFunction
Install *lua.LFunction
PreRemove *lua.LFunction
LuaState *lua.LState
}
type Source struct {
Method string
Url string
Specs any
}
type VersionConstraint string
type PkgDependencies struct {
RuntimeDependencies *map[string]*VersionConstraint
BuildDependencies *map[string]*VersionConstraint
Conflicts *map[string]*VersionConstraint
}
type Plataform struct {
Name string
Architetures []string
Sources *[]Source
Dependencies *PkgDependencies
}
type GitSpecs struct {
Branch string
Tag *string
}
type POSTSpecs struct {
SHA256 *string
Body *string
Headers *map[string]string
}
type GETSpecs struct {
SHA256 *string
Headers *map[string]string
}
var ErrCantFindPacketDotLua = errors.New("can't find Packet.lua in .tar.zst file")
var ErrFileDontReturnTable = errors.New("invalid Packet.lua format: the file do not return a table")
var ErrCannotFindPackageTable = errors.New("invalid Packet.lua format: can't find package table")
var ErrInstallFunctionDoesNotExist = errors.New("can not find instal()")
var ErrSha256Sum = errors.New("false checksum")
// ReadPacket read a Packet.lua and alredy set global vars
func ReadPacket(f []byte, cfg *Config) (PacketLua, error) {
cfg = checkConfig(cfg)
L := lua.NewState()
L.SetGlobal("error", L.NewFunction(lua_utils.LError))
osObject := L.GetGlobal("os").(*lua.LTable)
ioObject := L.GetGlobal("io").(*lua.LTable)
L.SetGlobal("os", lua.LNil)
L.SetGlobal("io", lua.LNil)
L.SetGlobal("BIN_DIR", lua.LString(cfg.BinDir))
L.SetGlobal("CURRENT_ARCH", lua.LString(runtime.GOARCH))
L.SetGlobal("CURRENT_ARCH_NORMALIZED", lua.LString(normalizeArch(runtime.GOARCH)))
L.SetGlobal("CURRENT_PLATAFORM", lua.LString(runtime.GOOS))
L.SetGlobal("pathjoin", L.NewFunction(lua_utils.Ljoin))
if err := L.DoString(string(f)); err != nil {
return PacketLua{}, err
}
L.SetGlobal("os", osObject)
L.SetGlobal("io", ioObject)
tableLua := L.Get(-1)
if tableLua.Type() != lua.LTTable {
return PacketLua{}, ErrFileDontReturnTable
}
table := tableLua.(*lua.LTable)
pkgTableLua := table.RawGetString("package")
if pkgTableLua.Type() != lua.LTTable {
return PacketLua{}, ErrCannotFindPackageTable
}
pkgTable := pkgTableLua.(*lua.LTable)
packetLua := &PacketLua{
Name: getStringFromTable(pkgTable, "name"),
Version: getStringFromTable(pkgTable, "version"),
Maintaner: getStringFromTable(pkgTable, "maintainer"),
Description: getStringFromTable(pkgTable, "description"),
Serial: getIntFromTable(pkgTable, "serial"),
Plataforms: getPlataformsFromTable(pkgTable, "plataforms"),
GlobalDependencies: getDependenciesFromTable(pkgTable, "build_dependencies"),
GlobalSources: getSourcesFromTable(pkgTable, "sources"),
Build: getFunctionFromTable(table, "build"),
Install: getFunctionFromTable(table, "install"),
PreRemove: getFunctionFromTable(table, "pre_remove"),
}
packetLua.LuaState = L
if packetLua.Install == nil {
return PacketLua{}, ErrInstallFunctionDoesNotExist
}
return *packetLua, nil
}
func ReadPacketFromZSTDF(file io.Reader, cfg *Config) (PacketLua, error) {
cfg = checkConfig(cfg)
zstdReader, err := zstd.NewReader(file)
if err != nil {
return PacketLua{}, err
}
defer zstdReader.Close()
tarReader := tar.NewReader(zstdReader)
for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return PacketLua{}, err
}
if filepath.Base(header.Name) == "Packet.lua" {
packageLuaBlob, err := io.ReadAll(tarReader)
if err != nil {
return PacketLua{}, err
}
return ReadPacket(packageLuaBlob, cfg)
}
}
return PacketLua{}, ErrCantFindPacketDotLua
}
// GetSource returns file []byte if method is "GET" or "POST", if is "git" returns *git.CloneOptions{}
func GetSource(url, method string, info any, tryAttempts int) (any, error) {
switch method {
case "GET":
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
specs := info.(GETSpecs)
if specs.Headers != nil {
for k, v := range *specs.Headers {
req.Header.Set(k, v)
}
}
client := http.Client{Timeout: 5 * time.Minute}
var resp *http.Response
for i := 0; i < tryAttempts; i++ {
resp, err = client.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
break
}
resp.Body.Close()
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if !verifySHA256(*specs.SHA256, data) {
return nil, ErrSha256Sum
}
return data, nil
case "POST":
specs := info.(POSTSpecs)
var body *bytes.Reader
if specs.Body != nil {
body = bytes.NewReader([]byte(*specs.Body))
} else {
body = nil
}
req, err := http.NewRequest("POST", url, body)
if err != nil {
return nil, err
}
if specs.Headers != nil {
for k, v := range *specs.Headers {
req.Header.Set(k, v)
}
}
client := http.Client{Timeout: 5 * time.Minute}
var resp *http.Response
for i := 0; i < tryAttempts; i++ {
resp, err = client.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
break
}
resp.Body.Close()
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if !verifySHA256(*specs.SHA256, data) {
return nil, ErrSha256Sum
}
return data, nil
case "git":
specs := info.(GitSpecs)
if specs.Tag == nil {
return &git.CloneOptions{
URL: url,
SingleBranch: true,
ReferenceName: plumbing.NewBranchReferenceName(specs.Branch),
Depth: 1,
}, nil
} else {
return &git.CloneOptions{
URL: url,
SingleBranch: true,
ReferenceName: plumbing.NewTagReferenceName(*specs.Tag),
Depth: 1,
}, nil
}
}
return nil, fmt.Errorf("invalid method")
}
func verifySHA256(checksum string, src []byte) bool {
check := sha256.Sum256(src)
return hex.EncodeToString(check[:]) == checksum
}
func (pkg PacketLua) ExecuteBuild(cfg *Config) error {
L := pkg.LuaState
L.SetGlobal("error", L.NewFunction(lua_utils.LError))
osObject := L.GetGlobal("os").(*lua.LTable)
osObject.RawSetString("chdir", L.NewFunction(lua_utils.LCD))
osObject.RawSetString("setenv", L.NewFunction(lua_utils.LSetEnv))
osObject.RawSetString("copy", L.NewFunction(lua_utils.LCopy))
osObject.RawSetString("mkdir", L.NewFunction(lua_utils.LMkdir))
osObject.RawSetString("remove", L.NewFunction(lua_utils.LRemove))
osObject.RawSetString("rename", L.NewFunction(lua_utils.LRename))
osObject.RawSetString("symlink", L.NewFunction(lua_utils.LSymlink))
osObject.RawSetString("chmod", L.NewFunction(lua_utils.LChmod))
L.SetGlobal("BIN_DIR", lua.LString(cfg.BinDir))
L.SetGlobal("CURRENT_ARCH", lua.LString(runtime.GOARCH))
L.SetGlobal("CURRENT_ARCH_NORMALIZED", lua.LString(normalizeArch(runtime.GOARCH)))
L.SetGlobal("CURRENT_PLATAFORM", lua.LString(runtime.GOOS))
L.SetGlobal("SOURCESDIR", lua.LString(cfg.SourcesDir))
L.SetGlobal("PACKETDIR", lua.LString(cfg.PacketDir))
L.SetGlobal("pathjoin", L.NewFunction(lua_utils.Ljoin))
os.Chdir(cfg.RootDir)
os.Setenv("PATH", os.Getenv("PATH")+":"+cfg.BinDir)
L.Push(pkg.Build)
return L.PCall(0, 0, nil)
}
func (pkg PacketLua) ExecuteInstall(cfg *Config) error {
L := pkg.LuaState
defer L.Close()
L.SetGlobal("error", L.NewFunction(lua_utils.LError))
osObject := L.GetGlobal("os").(*lua.LTable)
osObject.RawSetString("chdir", L.NewFunction(lua_utils.LCD))
osObject.RawSetString("setenv", L.NewFunction(lua_utils.LSetEnv))
osObject.RawSetString("copy", L.NewFunction(lua_utils.LCopy))
osObject.RawSetString("mkdir", L.NewFunction(lua_utils.LMkdir))
osObject.RawSetString("remove", L.NewFunction(lua_utils.LRemove))
osObject.RawSetString("rename", L.NewFunction(lua_utils.LRename))
osObject.RawSetString("symlink", L.NewFunction(lua_utils.LSymlink))
osObject.RawSetString("chmod", L.NewFunction(lua_utils.LChmod))
L.SetGlobal("BIN_DIR", lua.LString(cfg.BinDir))
L.SetGlobal("CURRENT_ARCH", lua.LString(runtime.GOARCH))
L.SetGlobal("CURRENT_ARCH_NORMALIZED", lua.LString(normalizeArch(runtime.GOARCH)))
L.SetGlobal("CURRENT_PLATAFORM", lua.LString(runtime.GOOS))
L.SetGlobal("SOURCESDIR", lua.LString(cfg.SourcesDir))
L.SetGlobal("PACKETDIR", lua.LString(cfg.PacketDir))
L.SetGlobal("pathjoin", L.NewFunction(lua_utils.Ljoin))
os.Chdir(cfg.RootDir)
os.Setenv("PATH", os.Getenv("PATH")+":"+cfg.BinDir)
L.Push(pkg.Install)
L.Call(0, 0)
return nil
}

View File

@@ -0,0 +1,25 @@
package packet
func (pkg PacketLua) IsValid() bool {
var a, b int
for _, v := range *pkg.Plataforms {
a += len(*v.Sources)
b += len(v.Architetures)
}
a += len(*pkg.GlobalSources)
if a < 1 || len(*pkg.Plataforms) > b {
return false
}
switch {
case pkg.Serial == -133:
return false
case pkg.Description == "" || pkg.Maintaner == "" || pkg.Name == "" || pkg.Version == "":
return false
}
return true
}

81
pkg/packet.lua.d/utils.go Normal file
View File

@@ -0,0 +1,81 @@
package packet
import (
"archive/tar"
"compress/gzip"
"fmt"
"io"
"log"
"math/rand"
"os"
"path/filepath"
"strings"
)
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$%!@%&*()-=+[]{}:;.,1234567890"
func randStringBytes(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand.Intn(len(letterBytes))]
}
return string(b)
}
func Dearchive(archive, outdir string) error {
switch {
case strings.HasSuffix(archive, ".tar.gz"):
f, err := os.Open(archive)
if err != nil {
return err
}
gzReader, err := gzip.NewReader(f)
if err != nil {
return err
}
tarReader := tar.NewReader(gzReader)
for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
destination := filepath.Join(outdir, header.Name)
fmt.Println(destination)
switch header.Typeflag {
case tar.TypeDir:
if err := os.Mkdir(destination, header.FileInfo().Mode()); err != nil {
return err
}
case tar.TypeReg:
if err := os.MkdirAll(filepath.Dir(destination), 0777); err != nil {
return err
}
outFile, err := os.Create(destination)
if err != nil {
return err
}
if _, err := io.Copy(outFile, tarReader); err != nil {
return err
}
outFile.Close()
default:
return fmt.Errorf("unknow filetype")
}
}
}
return nil
}

60
test/bat/Packet.lua Normal file
View File

@@ -0,0 +1,60 @@
return {
package = {
name = "bat-bin", -- required
version = "0.26.0", -- required
maintainer = "robogg133", -- required
description = "A cat(1) clone with syntax highlighting and Git integration.", -- required
serial = 0,-- required
plataforms = {
windows = {
arch = {"amd64"},
sources = {
{
url = "https://github.com/sharkdp/bat/releases/download/v0.26.0/bat-v0.26.0-" ..CURRENT_ARCH_NORMALIZED.."-pc-windows-msvc.zip",
method = "GET",
sha256="a8a6862f14698b45e101b0932c69bc47a007f4c0456f3a129fdcef54d443d501"
}
},
dependencies = {
build = {},
runtime = {},
conflicts = {}
}
},
linux = {
arch = {"amd64"},
sources = {
{
url = "https://github.com/sharkdp/bat/releases/download/v0.26.0/bat-v0.26.0-".. CURRENT_ARCH_NORMALIZED .."-unknown-linux-gnu.tar.gz",
method = "GET",
sha256 = "7efed0c768fae36f18ddbbb4a38f5c4b64db7c55a170dfc89fd380805809a44b"
}
},
dependencies = {
build = {},
runtime = {},
conflicts = {}
}
}
},
sources = {}
},
build = function()
end,
install = function()
local suc, errmsg = os.copy(pathjoin(SOURCESDIR,"bat-v0.26.0-".. CURRENT_ARCH_NORMALIZED .."-unknown-linux-gnu", "bat"), pathjoin(PACKETDIR, BIN_DIR, "bat"))
if not suc then
error(errmsg)
end
end,
}

View File

@@ -0,0 +1,38 @@
return {
package = {
name = "utctimerightnow", -- required
version = "0.1.0", -- required
maintainer = "robogg133", -- required
description = "shows utc time", -- required
serial = 0,-- required
dependencies = {
build = {"go"},
runtime = {},
conflicts = {}
},
sources = { --optional
{
url = "https://git.opentty.xyz/robogg133/utctimerightnow.git", -- required
method = "git", -- required
branch = "main" -- required
-- tag = ""
}
}
},
build = function()
-- os.setenv("GOPATH", pathjoin(SOURCESDIR, "gopath"))
os.chdir(pathjoin(SOURCESDIR, "utctimerightnow"))
os.execute('go build -trimpath -ldflags="-s -w" -o utctimerightnow main.go')
os.chmod(utctimerightnow, 0777)
end,
install = function() -- required
os.copy(pathjoin(SOURCESDIR, "utctimerightnow", "utctimerightnow"), pathjoin(PACKETDIR, BIN_DIR, "utctimerightnow"))
os.copy(pathjoin(SOURCESDIR, "utctimerightnow", "LICENSE"), pathjoin(PACKETDIR, "/usr/share/licenses/utctimerightnow/LICENSE"))
end,
}