From 97de746a7d69f88cce7ebe151c8b3cff0494e4c4 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Mon, 7 Apr 2025 15:35:18 +0300 Subject: [PATCH 01/23] Move go code to src/ subdirectory --- Makefile | 2 +- go.mod => src/go.mod | 0 go.sum => src/go.sum | 0 main.go => src/main.go | 0 {utils => src/utils}/config.go | 0 {utils => src/utils}/extract_utils.go | 0 {utils => src/utils}/general_utils.go | 0 {utils => src/utils}/hooks.go | 0 {utils => src/utils}/operations.go | 0 {utils => src/utils}/package_utils.go | 0 {utils => src/utils}/repo_utils.go | 0 11 files changed, 1 insertion(+), 1 deletion(-) rename go.mod => src/go.mod (100%) rename go.sum => src/go.sum (100%) rename main.go => src/main.go (100%) rename {utils => src/utils}/config.go (100%) rename {utils => src/utils}/extract_utils.go (100%) rename {utils => src/utils}/general_utils.go (100%) rename {utils => src/utils}/hooks.go (100%) rename {utils => src/utils}/operations.go (100%) rename {utils => src/utils}/package_utils.go (100%) rename {utils => src/utils}/repo_utils.go (100%) diff --git a/Makefile b/Makefile index ab65f36..c6ef16e 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ endif build: mkdir -p build - $(GO) build -ldflags "-w" -o build/bpm gitlab.com/bubble-package-manager/bpm + cd src; $(GO) build -ldflags "-w" -o ../build/bpm gitlab.com/bubble-package-manager/bpm install: build/bpm config/ mkdir -p $(DESTDIR)$(BINDIR) diff --git a/go.mod b/src/go.mod similarity index 100% rename from go.mod rename to src/go.mod diff --git a/go.sum b/src/go.sum similarity index 100% rename from go.sum rename to src/go.sum diff --git a/main.go b/src/main.go similarity index 100% rename from main.go rename to src/main.go diff --git a/utils/config.go b/src/utils/config.go similarity index 100% rename from utils/config.go rename to src/utils/config.go diff --git a/utils/extract_utils.go b/src/utils/extract_utils.go similarity index 100% rename from utils/extract_utils.go rename to src/utils/extract_utils.go diff --git a/utils/general_utils.go b/src/utils/general_utils.go similarity index 100% rename from utils/general_utils.go rename to src/utils/general_utils.go diff --git a/utils/hooks.go b/src/utils/hooks.go similarity index 100% rename from utils/hooks.go rename to src/utils/hooks.go diff --git a/utils/operations.go b/src/utils/operations.go similarity index 100% rename from utils/operations.go rename to src/utils/operations.go diff --git a/utils/package_utils.go b/src/utils/package_utils.go similarity index 100% rename from utils/package_utils.go rename to src/utils/package_utils.go diff --git a/utils/repo_utils.go b/src/utils/repo_utils.go similarity index 100% rename from utils/repo_utils.go rename to src/utils/repo_utils.go From fcb2ef1515d16187f20f2f190a5f49a5b6375ecb Mon Sep 17 00:00:00 2001 From: EnumDev Date: Mon, 7 Apr 2025 17:06:40 +0300 Subject: [PATCH 02/23] Split project into the BPM frontend (src/bpm) and the BPM backend module (src/bpmlib) --- Makefile | 2 +- src/bpm/go.mod | 14 ++++ src/{ => bpm}/go.sum | 5 +- src/{ => bpm}/main.go | 112 ++++++++++++------------- src/{utils => bpmlib}/config.go | 2 +- src/{utils => bpmlib}/extract_utils.go | 2 +- src/{utils => bpmlib}/general_utils.go | 2 +- src/bpmlib/go.mod | 8 ++ src/bpmlib/go.sum | 6 ++ src/{utils => bpmlib}/hooks.go | 2 +- src/{utils => bpmlib}/operations.go | 2 +- src/{utils => bpmlib}/package_utils.go | 2 +- src/{utils => bpmlib}/repo_utils.go | 2 +- src/go.mod | 9 -- 14 files changed, 93 insertions(+), 77 deletions(-) create mode 100644 src/bpm/go.mod rename src/{ => bpm}/go.sum (57%) rename src/{ => bpm}/main.go (88%) rename src/{utils => bpmlib}/config.go (98%) rename src/{utils => bpmlib}/extract_utils.go (97%) rename src/{utils => bpmlib}/general_utils.go (98%) create mode 100644 src/bpmlib/go.mod create mode 100644 src/bpmlib/go.sum rename src/{utils => bpmlib}/hooks.go (99%) rename src/{utils => bpmlib}/operations.go (99%) rename src/{utils => bpmlib}/package_utils.go (99%) rename src/{utils => bpmlib}/repo_utils.go (99%) delete mode 100644 src/go.mod diff --git a/Makefile b/Makefile index c6ef16e..aae7c6f 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ endif build: mkdir -p build - cd src; $(GO) build -ldflags "-w" -o ../build/bpm gitlab.com/bubble-package-manager/bpm + cd src/bpm; $(GO) build -ldflags "-w" -o ../../build/bpm gitlab.com/bubble-package-manager/bpm install: build/bpm config/ mkdir -p $(DESTDIR)$(BINDIR) diff --git a/src/bpm/go.mod b/src/bpm/go.mod new file mode 100644 index 0000000..5525700 --- /dev/null +++ b/src/bpm/go.mod @@ -0,0 +1,14 @@ +module gitlab.com/bubble-package-manager/bpm + +go 1.23 + +toolchain go1.23.7 + +require git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib v0.5.0 + +replace git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib => ../bpmlib + +require ( + github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/src/go.sum b/src/bpm/go.sum similarity index 57% rename from src/go.sum rename to src/bpm/go.sum index 138d9eb..8a51310 100644 --- a/src/go.sum +++ b/src/bpm/go.sum @@ -1,9 +1,6 @@ -github.com/elliotchance/orderedmap/v2 v2.4.0 h1:6tUmMwD9F998FNpwFxA5E6NQvSpk2PVw7RKsVq3+2Cw= -github.com/elliotchance/orderedmap/v2 v2.4.0/go.mod h1:85lZyVbpGaGvHvnKa7Qhx7zncAdBIBq6u56Hb1PRU5Q= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f h1:xt29M2T6STgldg+WEP51gGePQCsQvklmP2eIhPIBK3g= github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f/go.mod h1:i4sF0l1fFnY1aiw08QQSwVAFxHEm311Me3WsU/X7nL0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/src/main.go b/src/bpm/main.go similarity index 88% rename from src/main.go rename to src/bpm/main.go index 7db4691..58de8d7 100644 --- a/src/main.go +++ b/src/bpm/main.go @@ -4,7 +4,7 @@ import ( "bufio" "flag" "fmt" - "gitlab.com/bubble-package-manager/bpm/utils" + "git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib" "log" "os" "path/filepath" @@ -42,7 +42,7 @@ var doCleanup = false var showRepoInfo = false func main() { - utils.ReadConfig() + bpmlib.ReadConfig() resolveFlags() resolveCommand() } @@ -102,30 +102,30 @@ func resolveCommand() { return } for n, pkg := range packages { - var info *utils.PackageInfo + var info *bpmlib.PackageInfo isFile := false if showRepoInfo { var err error - var entry *utils.RepositoryEntry - entry, _, err = utils.GetRepositoryEntry(pkg) + var entry *bpmlib.RepositoryEntry + entry, _, err = bpmlib.GetRepositoryEntry(pkg) if err != nil { - if entry = utils.ResolveVirtualPackage(pkg); entry == nil { + if entry = bpmlib.ResolveVirtualPackage(pkg); entry == nil { log.Fatalf("Error: could not find package (%s) in any repository\n", pkg) } } info = entry.Info } else if stat, err := os.Stat(pkg); err == nil && !stat.IsDir() { - bpmpkg, err := utils.ReadPackage(pkg) + bpmpkg, err := bpmlib.ReadPackage(pkg) if err != nil { log.Fatalf("Error: could not read package: %s\n", err) } info = bpmpkg.PkgInfo isFile = true } else { - if isVirtual, p := utils.IsVirtualPackage(pkg, rootDir); isVirtual { - info = utils.GetPackageInfo(p, rootDir) + if isVirtual, p := bpmlib.IsVirtualPackage(pkg, rootDir); isVirtual { + info = bpmlib.GetPackageInfo(p, rootDir) } else { - info = utils.GetPackageInfo(pkg, rootDir) + info = bpmlib.GetPackageInfo(pkg, rootDir) } } if info == nil { @@ -141,10 +141,10 @@ func resolveCommand() { } fmt.Println("File: " + abs) } - fmt.Println(utils.CreateReadableInfo(true, true, true, info, rootDir)) + fmt.Println(bpmlib.CreateReadableInfo(true, true, true, info, rootDir)) } case list: - packages, err := utils.GetInstalledPackages(rootDir) + packages, err := bpmlib.GetInstalledPackages(rootDir) if err != nil { log.Fatalf("Error: could not get installed packages: %s", err.Error()) return @@ -161,7 +161,7 @@ func resolveCommand() { return } for n, pkg := range packages { - info := utils.GetPackageInfo(pkg, rootDir) + info := bpmlib.GetPackageInfo(pkg, rootDir) if info == nil { fmt.Printf("Package (%s) could not be found\n", pkg) continue @@ -169,7 +169,7 @@ func resolveCommand() { if n != 0 { fmt.Println() } - fmt.Println(utils.CreateReadableInfo(true, true, true, info, rootDir)) + fmt.Println(bpmlib.CreateReadableInfo(true, true, true, info, rootDir)) } } case search: @@ -178,9 +178,9 @@ func resolveCommand() { log.Fatalf("Error: no search terms given") } for i, term := range searchTerms { - nameResults := make([]*utils.PackageInfo, 0) - descResults := make([]*utils.PackageInfo, 0) - for _, repo := range utils.BPMConfig.Repositories { + nameResults := make([]*bpmlib.PackageInfo, 0) + descResults := make([]*bpmlib.PackageInfo, 0) + for _, repo := range bpmlib.BPMConfig.Repositories { for _, entry := range repo.Entries { if strings.Contains(entry.Info.Name, term) { nameResults = append(nameResults, entry.Info) @@ -212,17 +212,17 @@ func resolveCommand() { } // Check if installationReason argument is valid - ir := utils.Unknown + ir := bpmlib.Unknown if installationReason == "manual" { - ir = utils.Manual + ir = bpmlib.Manual } else if installationReason == "dependency" { - ir = utils.Dependency + ir = bpmlib.Dependency } else if installationReason != "" { log.Fatalf("Error: %s is not a valid installation reason", installationReason) } - operation := utils.BPMOperation{ - Actions: make([]utils.OperationAction, 0), + operation := bpmlib.BPMOperation{ + Actions: make([]bpmlib.OperationAction, 0), UnresolvedDepends: make([]string, 0), Changes: make(map[string]string), RootDir: rootDir, @@ -232,37 +232,37 @@ func resolveCommand() { // Search for packages for _, pkg := range pkgs { if stat, err := os.Stat(pkg); err == nil && !stat.IsDir() { - bpmpkg, err := utils.ReadPackage(pkg) + bpmpkg, err := bpmlib.ReadPackage(pkg) if err != nil { log.Fatalf("Error: could not read package: %s\n", err) } - if !reinstall && utils.IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) && utils.GetPackageInfo(bpmpkg.PkgInfo.Name, rootDir).GetFullVersion() == bpmpkg.PkgInfo.GetFullVersion() { + if !reinstall && bpmlib.IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) && bpmlib.GetPackageInfo(bpmpkg.PkgInfo.Name, rootDir).GetFullVersion() == bpmpkg.PkgInfo.GetFullVersion() { continue } - operation.AppendAction(&utils.InstallPackageAction{ + operation.AppendAction(&bpmlib.InstallPackageAction{ File: pkg, IsDependency: false, BpmPackage: bpmpkg, }) } else { - var entry *utils.RepositoryEntry + var entry *bpmlib.RepositoryEntry - if e, _, err := utils.GetRepositoryEntry(pkg); err == nil { + if e, _, err := bpmlib.GetRepositoryEntry(pkg); err == nil { entry = e - } else if isVirtual, p := utils.IsVirtualPackage(pkg, rootDir); isVirtual { - entry, _, err = utils.GetRepositoryEntry(p) + } else if isVirtual, p := bpmlib.IsVirtualPackage(pkg, rootDir); isVirtual { + entry, _, err = bpmlib.GetRepositoryEntry(p) if err != nil { log.Fatalf("Error: could not find package (%s) in any repository\n", p) } - } else if e := utils.ResolveVirtualPackage(pkg); e != nil { + } else if e := bpmlib.ResolveVirtualPackage(pkg); e != nil { entry = e } else { log.Fatalf("Error: could not find package (%s) in any repository\n", pkg) } - if !reinstall && utils.IsPackageInstalled(entry.Info.Name, rootDir) && utils.GetPackageInfo(entry.Info.Name, rootDir).GetFullVersion() == entry.Info.GetFullVersion() { + if !reinstall && bpmlib.IsPackageInstalled(entry.Info.Name, rootDir) && bpmlib.GetPackageInfo(entry.Info.Name, rootDir).GetFullVersion() == entry.Info.GetFullVersion() { continue } - operation.AppendAction(&utils.FetchPackageAction{ + operation.AppendAction(&bpmlib.FetchPackageAction{ IsDependency: false, RepositoryEntry: entry, }) @@ -342,7 +342,7 @@ func resolveCommand() { // Sync repositories if !nosync { - for _, repo := range utils.BPMConfig.Repositories { + for _, repo := range bpmlib.BPMConfig.Repositories { fmt.Printf("Fetching package database for repository (%s)...\n", repo.Name) err := repo.SyncLocalDatabase() if err != nil { @@ -352,42 +352,42 @@ func resolveCommand() { fmt.Println("All package databases synced successfully!") } - utils.ReadConfig() + bpmlib.ReadConfig() // Get installed packages and check for updates - pkgs, err := utils.GetInstalledPackages(rootDir) + pkgs, err := bpmlib.GetInstalledPackages(rootDir) if err != nil { log.Fatalf("Error: could not get installed packages: %s\n", err) } - operation := utils.BPMOperation{ - Actions: make([]utils.OperationAction, 0), + operation := bpmlib.BPMOperation{ + Actions: make([]bpmlib.OperationAction, 0), UnresolvedDepends: make([]string, 0), Changes: make(map[string]string), RootDir: rootDir, - ForceInstallationReason: utils.Unknown, + ForceInstallationReason: bpmlib.Unknown, } // Search for packages for _, pkg := range pkgs { - if slices.Contains(utils.BPMConfig.IgnorePackages, pkg) { + if slices.Contains(bpmlib.BPMConfig.IgnorePackages, pkg) { continue } - var entry *utils.RepositoryEntry + var entry *bpmlib.RepositoryEntry // Check if installed package can be replaced and install that instead - if e := utils.FindReplacement(pkg); e != nil { + if e := bpmlib.FindReplacement(pkg); e != nil { entry = e - } else if entry, _, err = utils.GetRepositoryEntry(pkg); err != nil { + } else if entry, _, err = bpmlib.GetRepositoryEntry(pkg); err != nil { continue } - installedInfo := utils.GetPackageInfo(pkg, rootDir) + installedInfo := bpmlib.GetPackageInfo(pkg, rootDir) if installedInfo == nil { log.Fatalf("Error: could not get package info for (%s)\n", pkg) } else { - comparison := utils.ComparePackageVersions(*entry.Info, *installedInfo) + comparison := bpmlib.ComparePackageVersions(*entry.Info, *installedInfo) if comparison > 0 || reinstall { - operation.AppendAction(&utils.FetchPackageAction{ + operation.AppendAction(&bpmlib.FetchPackageAction{ IsDependency: false, RepositoryEntry: entry, }) @@ -450,7 +450,7 @@ func resolveCommand() { os.Exit(1) } } - for _, repo := range utils.BPMConfig.Repositories { + for _, repo := range bpmlib.BPMConfig.Repositories { fmt.Printf("Fetching package database for repository (%s)...\n", repo.Name) err := repo.SyncLocalDatabase() if err != nil { @@ -468,8 +468,8 @@ func resolveCommand() { return } - operation := &utils.BPMOperation{ - Actions: make([]utils.OperationAction, 0), + operation := &bpmlib.BPMOperation{ + Actions: make([]bpmlib.OperationAction, 0), UnresolvedDepends: make([]string, 0), Changes: make(map[string]string), RootDir: rootDir, @@ -477,11 +477,11 @@ func resolveCommand() { // Search for packages for _, pkg := range packages { - bpmpkg := utils.GetPackage(pkg, rootDir) + bpmpkg := bpmlib.GetPackage(pkg, rootDir) if bpmpkg == nil { continue } - operation.AppendAction(&utils.RemovePackageAction{BpmPackage: bpmpkg}) + operation.AppendAction(&bpmlib.RemovePackageAction{BpmPackage: bpmpkg}) } // Skip needed packages if the --unused flag is on @@ -531,8 +531,8 @@ func resolveCommand() { log.Fatalf("Error: this subcommand needs to be run with superuser permissions") } - operation := &utils.BPMOperation{ - Actions: make([]utils.OperationAction, 0), + operation := &bpmlib.BPMOperation{ + Actions: make([]bpmlib.OperationAction, 0), UnresolvedDepends: make([]string, 0), Changes: make(map[string]string), RootDir: rootDir, @@ -585,7 +585,7 @@ func resolveCommand() { if os.IsNotExist(err) { log.Fatalf("Error: file (%s) does not exist!\n", absFile) } - pkgs, err := utils.GetInstalledPackages(rootDir) + pkgs, err := bpmlib.GetInstalledPackages(rootDir) if err != nil { log.Fatalf("Error: could not get installed packages: %s\n", err.Error()) } @@ -604,7 +604,7 @@ func resolveCommand() { var pkgList []string for _, pkg := range pkgs { - if slices.ContainsFunc(utils.GetPackageFiles(pkg, rootDir), func(entry *utils.PackageFileEntry) bool { + if slices.ContainsFunc(bpmlib.GetPackageFiles(pkg, rootDir), func(entry *bpmlib.PackageFileEntry) bool { return entry.Path == absFile }) { pkgList = append(pkgList, pkg) @@ -694,8 +694,8 @@ func resolveFlags() { installFlagSet.StringVar(&rootDir, "R", "/", "Set the destination root") installFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing") installFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts") - installFlagSet.StringVar(&utils.BPMConfig.BinaryOutputDir, "o", utils.BPMConfig.BinaryOutputDir, "Set the binary output directory") - installFlagSet.StringVar(&utils.BPMConfig.CompilationDir, "c", utils.BPMConfig.CompilationDir, "Set the compilation directory") + installFlagSet.StringVar(&bpmlib.BPMConfig.BinaryOutputDir, "o", bpmlib.BPMConfig.BinaryOutputDir, "Set the binary output directory") + installFlagSet.StringVar(&bpmlib.BPMConfig.CompilationDir, "c", bpmlib.BPMConfig.CompilationDir, "Set the compilation directory") installFlagSet.BoolVar(&buildSource, "b", false, "Build binary package from source package") installFlagSet.BoolVar(&skipCheck, "s", false, "Skip check function during source compilation") installFlagSet.BoolVar(&keepTempDir, "k", false, "Keep temporary directory after source compilation") diff --git a/src/utils/config.go b/src/bpmlib/config.go similarity index 98% rename from src/utils/config.go rename to src/bpmlib/config.go index e57b03f..18e03c2 100644 --- a/src/utils/config.go +++ b/src/bpmlib/config.go @@ -1,4 +1,4 @@ -package utils +package bpmlib import ( "gopkg.in/yaml.v3" diff --git a/src/utils/extract_utils.go b/src/bpmlib/extract_utils.go similarity index 97% rename from src/utils/extract_utils.go rename to src/bpmlib/extract_utils.go index 6c51928..2f0b3e8 100644 --- a/src/utils/extract_utils.go +++ b/src/bpmlib/extract_utils.go @@ -1,4 +1,4 @@ -package utils +package bpmlib import ( "archive/tar" diff --git a/src/utils/general_utils.go b/src/bpmlib/general_utils.go similarity index 98% rename from src/utils/general_utils.go rename to src/bpmlib/general_utils.go index dd1e812..411a4fe 100644 --- a/src/utils/general_utils.go +++ b/src/bpmlib/general_utils.go @@ -1,4 +1,4 @@ -package utils +package bpmlib import ( "fmt" diff --git a/src/bpmlib/go.mod b/src/bpmlib/go.mod new file mode 100644 index 0000000..d0dabd5 --- /dev/null +++ b/src/bpmlib/go.mod @@ -0,0 +1,8 @@ +module git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib + +go 1.23 + +require ( + github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f + gopkg.in/yaml.v3 v3.0.1 +) diff --git a/src/bpmlib/go.sum b/src/bpmlib/go.sum new file mode 100644 index 0000000..8a51310 --- /dev/null +++ b/src/bpmlib/go.sum @@ -0,0 +1,6 @@ +github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f h1:xt29M2T6STgldg+WEP51gGePQCsQvklmP2eIhPIBK3g= +github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f/go.mod h1:i4sF0l1fFnY1aiw08QQSwVAFxHEm311Me3WsU/X7nL0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/src/utils/hooks.go b/src/bpmlib/hooks.go similarity index 99% rename from src/utils/hooks.go rename to src/bpmlib/hooks.go index 28294f8..e0503d4 100644 --- a/src/utils/hooks.go +++ b/src/bpmlib/hooks.go @@ -1,4 +1,4 @@ -package utils +package bpmlib import ( "errors" diff --git a/src/utils/operations.go b/src/bpmlib/operations.go similarity index 99% rename from src/utils/operations.go rename to src/bpmlib/operations.go index ab3adeb..72d2979 100644 --- a/src/utils/operations.go +++ b/src/bpmlib/operations.go @@ -1,4 +1,4 @@ -package utils +package bpmlib import ( "errors" diff --git a/src/utils/package_utils.go b/src/bpmlib/package_utils.go similarity index 99% rename from src/utils/package_utils.go rename to src/bpmlib/package_utils.go index 443f981..b030cbe 100644 --- a/src/utils/package_utils.go +++ b/src/bpmlib/package_utils.go @@ -1,4 +1,4 @@ -package utils +package bpmlib import ( "archive/tar" diff --git a/src/utils/repo_utils.go b/src/bpmlib/repo_utils.go similarity index 99% rename from src/utils/repo_utils.go rename to src/bpmlib/repo_utils.go index 0cf8c1f..ffe64b2 100644 --- a/src/utils/repo_utils.go +++ b/src/bpmlib/repo_utils.go @@ -1,4 +1,4 @@ -package utils +package bpmlib import ( "errors" diff --git a/src/go.mod b/src/go.mod deleted file mode 100644 index eb5bc0a..0000000 --- a/src/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module gitlab.com/bubble-package-manager/bpm - -go 1.22 - -require ( - github.com/elliotchance/orderedmap/v2 v2.4.0 // indirect - github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) From 05f273d6871c76e5762a7d4b3971dcb5f432b9d9 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Mon, 7 Apr 2025 17:10:19 +0300 Subject: [PATCH 03/23] Update bpm frontend module name --- Makefile | 2 +- src/bpm/go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index aae7c6f..851f832 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ endif build: mkdir -p build - cd src/bpm; $(GO) build -ldflags "-w" -o ../../build/bpm gitlab.com/bubble-package-manager/bpm + cd src/bpm; $(GO) build -ldflags "-w" -o ../../build/bpm git.enumerated.dev/bubble-package-manager/bpm/src/bpm install: build/bpm config/ mkdir -p $(DESTDIR)$(BINDIR) diff --git a/src/bpm/go.mod b/src/bpm/go.mod index 5525700..5129f8b 100644 --- a/src/bpm/go.mod +++ b/src/bpm/go.mod @@ -1,4 +1,4 @@ -module gitlab.com/bubble-package-manager/bpm +module git.enumerated.dev/bubble-package-manager/bpm/src/bpm go 1.23 From 68291e2666676d619905238d473b4d63c26b722a Mon Sep 17 00:00:00 2001 From: EnumDev Date: Mon, 7 Apr 2025 17:14:04 +0300 Subject: [PATCH 04/23] Rename go files --- src/bpmlib/{package_utils.go => packages.go} | 0 src/bpmlib/{repo_utils.go => repositories.go} | 0 src/bpmlib/{extract_utils.go => tarball.go} | 0 src/bpmlib/{general_utils.go => utils.go} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/bpmlib/{package_utils.go => packages.go} (100%) rename src/bpmlib/{repo_utils.go => repositories.go} (100%) rename src/bpmlib/{extract_utils.go => tarball.go} (100%) rename src/bpmlib/{general_utils.go => utils.go} (100%) diff --git a/src/bpmlib/package_utils.go b/src/bpmlib/packages.go similarity index 100% rename from src/bpmlib/package_utils.go rename to src/bpmlib/packages.go diff --git a/src/bpmlib/repo_utils.go b/src/bpmlib/repositories.go similarity index 100% rename from src/bpmlib/repo_utils.go rename to src/bpmlib/repositories.go diff --git a/src/bpmlib/extract_utils.go b/src/bpmlib/tarball.go similarity index 100% rename from src/bpmlib/extract_utils.go rename to src/bpmlib/tarball.go diff --git a/src/bpmlib/general_utils.go b/src/bpmlib/utils.go similarity index 100% rename from src/bpmlib/general_utils.go rename to src/bpmlib/utils.go From 9485248d8ee831cd6065f716d4a13a75324d5b75 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Mon, 7 Apr 2025 17:28:26 +0300 Subject: [PATCH 05/23] Unexport functions --- src/bpmlib/hooks.go | 4 ++-- src/bpmlib/operations.go | 14 +++++++------- src/bpmlib/packages.go | 26 +++++++++++++------------- src/bpmlib/tarball.go | 6 +++--- src/bpmlib/utils.go | 4 ++-- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/bpmlib/hooks.go b/src/bpmlib/hooks.go index e0503d4..a9bbff4 100644 --- a/src/bpmlib/hooks.go +++ b/src/bpmlib/hooks.go @@ -23,8 +23,8 @@ type BPMHook struct { Run string `yaml:"run"` } -// CreateHook returns a BPMHook instance based on the content of the given string -func CreateHook(sourcePath string) (*BPMHook, error) { +// createHook returns a BPMHook instance based on the content of the given string +func createHook(sourcePath string) (*BPMHook, error) { // Read hook from source path bytes, err := os.ReadFile(sourcePath) if err != nil { diff --git a/src/bpmlib/operations.go b/src/bpmlib/operations.go index 72d2979..56efc48 100644 --- a/src/bpmlib/operations.go +++ b/src/bpmlib/operations.go @@ -372,12 +372,12 @@ func (operation *BPMOperation) ShowOperationSummary() { fmt.Println("Warning: Operating in " + operation.RootDir) } if operation.GetTotalDownloadSize() > 0 { - fmt.Printf("%s will be downloaded to complete this operation\n", UnsignedBytesToHumanReadable(operation.GetTotalDownloadSize())) + fmt.Printf("%s will be downloaded to complete this operation\n", unsignedBytesToHumanReadable(operation.GetTotalDownloadSize())) } if operation.GetFinalActionSize(operation.RootDir) > 0 { - fmt.Printf("A total of %s will be installed after the operation finishes\n", BytesToHumanReadable(operation.GetFinalActionSize(operation.RootDir))) + fmt.Printf("A total of %s will be installed after the operation finishes\n", bytesToHumanReadable(operation.GetFinalActionSize(operation.RootDir))) } else if operation.GetFinalActionSize(operation.RootDir) < 0 { - fmt.Printf("A total of %s will be freed after the operation finishes\n", strings.TrimPrefix(BytesToHumanReadable(operation.GetFinalActionSize(operation.RootDir)), "-")) + fmt.Printf("A total of %s will be freed after the operation finishes\n", strings.TrimPrefix(bytesToHumanReadable(operation.GetFinalActionSize(operation.RootDir)), "-")) } } @@ -391,7 +391,7 @@ func (operation *BPMOperation) RunHooks(verbose bool) error { // Find all hooks, validate and execute them for _, entry := range dirEntries { if entry.Type().IsRegular() && strings.HasSuffix(entry.Name(), ".bpmhook") { - hook, err := CreateHook(path.Join(operation.RootDir, "var/lib/bpm/hooks", entry.Name())) + hook, err := createHook(path.Join(operation.RootDir, "var/lib/bpm/hooks", entry.Name())) if err != nil { log.Printf("Error while reading hook (%s): %s", entry.Name(), err) } @@ -458,7 +458,7 @@ func (operation *BPMOperation) Execute(verbose, force bool) error { for _, action := range operation.Actions { if action.GetActionType() == "remove" { pkgInfo := action.(*RemovePackageAction).BpmPackage.PkgInfo - err := RemovePackage(pkgInfo.Name, verbose, operation.RootDir) + err := removePackage(pkgInfo.Name, verbose, operation.RootDir) if err != nil { return errors.New(fmt.Sprintf("could not remove package (%s): %s\n", pkgInfo.Name, err)) } @@ -468,9 +468,9 @@ func (operation *BPMOperation) Execute(verbose, force bool) error { isReinstall := IsPackageInstalled(bpmpkg.PkgInfo.Name, operation.RootDir) var err error if value.IsDependency { - err = InstallPackage(value.File, operation.RootDir, verbose, true, false, false, false) + err = installPackage(value.File, operation.RootDir, verbose, true, false, false, false) } else { - err = InstallPackage(value.File, operation.RootDir, verbose, force, false, false, false) + err = installPackage(value.File, operation.RootDir, verbose, force, false, false, false) } if err != nil { return errors.New(fmt.Sprintf("could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err)) diff --git a/src/bpmlib/packages.go b/src/bpmlib/packages.go index b030cbe..d7008b7 100644 --- a/src/bpmlib/packages.go +++ b/src/bpmlib/packages.go @@ -288,7 +288,7 @@ const ( Remove = 2 ) -func ExecutePackageScripts(filename, rootDir string, operation Operation, postOperation bool) error { +func executePackageScripts(filename, rootDir string, operation Operation, postOperation bool) error { pkgInfo, err := ReadPackage(filename) if err != nil { return err @@ -478,12 +478,12 @@ func CreateReadableInfo(showArchitecture, showType, showPackageRelations bool, p func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) error { if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) { - err := ExecutePackageScripts(filename, rootDir, Install, false) + err := executePackageScripts(filename, rootDir, Install, false) if err != nil { return err } } else { - err := ExecutePackageScripts(filename, rootDir, Update, false) + err := executePackageScripts(filename, rootDir, Update, false) if err != nil { return err } @@ -494,7 +494,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) return err } - tarballFile, err := ReadTarballContent(filename, "files.tar.gz") + tarballFile, err := readTarballContent(filename, "files.tar.gz") if err != nil { return err } @@ -629,12 +629,12 @@ func isSplitPackage(filename string) bool { func compilePackage(bpmpkg *BPMPackage, filename, rootDir string, verbose, binaryPkgFromSrc, skipCheck, keepTempDir bool) (error, []string) { var files []string if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) { - err := ExecutePackageScripts(filename, rootDir, Install, false) + err := executePackageScripts(filename, rootDir, Install, false) if err != nil { return err, nil } } else { - err := ExecutePackageScripts(filename, rootDir, Update, false) + err := executePackageScripts(filename, rootDir, Update, false) if err != nil { return err, nil } @@ -747,12 +747,12 @@ func compilePackage(bpmpkg *BPMPackage, filename, rootDir string, verbose, binar } fmt.Println("Running source.sh file...") if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) { - err = ExecutePackageScripts(filename, rootDir, Install, false) + err = executePackageScripts(filename, rootDir, Install, false) if err != nil { return err, nil } } else { - err = ExecutePackageScripts(filename, rootDir, Update, false) + err = executePackageScripts(filename, rootDir, Update, false) if err != nil { return err, nil } @@ -1051,7 +1051,7 @@ fi return nil, files } -func InstallPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc, skipCheck, keepTempDir bool) error { +func installPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc, skipCheck, keepTempDir bool) error { if _, err := os.Stat(filename); os.IsNotExist(err) { return err } @@ -1198,7 +1198,7 @@ func InstallPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc, return err } - tarballFile, err := ReadTarballContent(filename, "pkg.files") + tarballFile, err := readTarballContent(filename, "pkg.files") if err != nil { return err } @@ -1246,12 +1246,12 @@ func InstallPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc, } if !packageInstalled { - err = ExecutePackageScripts(filename, rootDir, Install, true) + err = executePackageScripts(filename, rootDir, Install, true) if err != nil { return err } } else { - err = ExecutePackageScripts(filename, rootDir, Update, true) + err = executePackageScripts(filename, rootDir, Update, true) if err != nil { return err } @@ -1552,7 +1552,7 @@ func GetAllPackageFiles(rootDir string, excludePackages ...string) (map[string][ return ret, nil } -func RemovePackage(pkg string, verbose bool, rootDir string) error { +func removePackage(pkg string, verbose bool, rootDir string) error { installedDir := path.Join(rootDir, "var/lib/bpm/installed/") pkgDir := path.Join(installedDir, pkg) pkgInfo := GetPackageInfo(pkg, rootDir) diff --git a/src/bpmlib/tarball.go b/src/bpmlib/tarball.go index 2f0b3e8..84a0008 100644 --- a/src/bpmlib/tarball.go +++ b/src/bpmlib/tarball.go @@ -7,12 +7,12 @@ import ( "os" ) -type TarballFileReader struct { +type tarballFileReader struct { tarReader *tar.Reader file *os.File } -func ReadTarballContent(tarballPath, fileToExtract string) (*TarballFileReader, error) { +func readTarballContent(tarballPath, fileToExtract string) (*tarballFileReader, error) { file, err := os.Open(tarballPath) if err != nil { return nil, err @@ -32,7 +32,7 @@ func ReadTarballContent(tarballPath, fileToExtract string) (*TarballFileReader, return nil, errors.New("file to extract must be a regular file") } - return &TarballFileReader{ + return &tarballFileReader{ tarReader: tr, file: file, }, nil diff --git a/src/bpmlib/utils.go b/src/bpmlib/utils.go index 411a4fe..a89dff8 100644 --- a/src/bpmlib/utils.go +++ b/src/bpmlib/utils.go @@ -55,7 +55,7 @@ func stringSliceRemove(s []string, r string) []string { return s } -func UnsignedBytesToHumanReadable(b uint64) string { +func unsignedBytesToHumanReadable(b uint64) string { bf := float64(b) for _, unit := range []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"} { if math.Abs(bf) < 1024.0 { @@ -66,7 +66,7 @@ func UnsignedBytesToHumanReadable(b uint64) string { return fmt.Sprintf("%.1fYiB", bf) } -func BytesToHumanReadable(b int64) string { +func bytesToHumanReadable(b int64) string { bf := float64(b) for _, unit := range []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"} { if math.Abs(bf) < 1024.0 { From 0801612166e261ff1ec7cd7278d15e5296216953 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Mon, 7 Apr 2025 21:03:33 +0300 Subject: [PATCH 06/23] Create functions for basic package management in bpmlib --- src/bpm/main.go | 246 ++++++++--------------------------------- src/bpmlib/general.go | 250 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 293 insertions(+), 203 deletions(-) create mode 100644 src/bpmlib/general.go diff --git a/src/bpm/main.go b/src/bpm/main.go index 58de8d7..f263423 100644 --- a/src/bpm/main.go +++ b/src/bpm/main.go @@ -202,107 +202,41 @@ func resolveCommand() { } } case install: + // Check for required permissions if os.Getuid() != 0 { log.Fatalf("Error: this subcommand needs to be run with superuser permissions") } - pkgs := subcommandArgs - if len(pkgs) == 0 { + + // Return if no packages are specified + if len(subcommandArgs) == 0 { fmt.Println("No packages or files were given to install") return } // Check if installationReason argument is valid ir := bpmlib.Unknown - if installationReason == "manual" { + switch installationReason { + case "manual": ir = bpmlib.Manual - } else if installationReason == "dependency" { + case "dependency": ir = bpmlib.Dependency - } else if installationReason != "" { + case "": + default: log.Fatalf("Error: %s is not a valid installation reason", installationReason) } - operation := bpmlib.BPMOperation{ - Actions: make([]bpmlib.OperationAction, 0), - UnresolvedDepends: make([]string, 0), - Changes: make(map[string]string), - RootDir: rootDir, - ForceInstallationReason: ir, + // Get reinstall method + var reinstallMethod bpmlib.ReinstallMethod + if reinstallAll { + reinstallMethod = bpmlib.ReinstallMethodAll + } else if reinstall { + reinstallMethod = bpmlib.ReinstallMethodSpecified + } else { + reinstallMethod = bpmlib.ReinstallMethodNone } - // Search for packages - for _, pkg := range pkgs { - if stat, err := os.Stat(pkg); err == nil && !stat.IsDir() { - bpmpkg, err := bpmlib.ReadPackage(pkg) - if err != nil { - log.Fatalf("Error: could not read package: %s\n", err) - } - if !reinstall && bpmlib.IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) && bpmlib.GetPackageInfo(bpmpkg.PkgInfo.Name, rootDir).GetFullVersion() == bpmpkg.PkgInfo.GetFullVersion() { - continue - } - operation.AppendAction(&bpmlib.InstallPackageAction{ - File: pkg, - IsDependency: false, - BpmPackage: bpmpkg, - }) - } else { - var entry *bpmlib.RepositoryEntry - - if e, _, err := bpmlib.GetRepositoryEntry(pkg); err == nil { - entry = e - } else if isVirtual, p := bpmlib.IsVirtualPackage(pkg, rootDir); isVirtual { - entry, _, err = bpmlib.GetRepositoryEntry(p) - if err != nil { - log.Fatalf("Error: could not find package (%s) in any repository\n", p) - } - } else if e := bpmlib.ResolveVirtualPackage(pkg); e != nil { - entry = e - } else { - log.Fatalf("Error: could not find package (%s) in any repository\n", pkg) - } - if !reinstall && bpmlib.IsPackageInstalled(entry.Info.Name, rootDir) && bpmlib.GetPackageInfo(entry.Info.Name, rootDir).GetFullVersion() == entry.Info.GetFullVersion() { - continue - } - operation.AppendAction(&bpmlib.FetchPackageAction{ - IsDependency: false, - RepositoryEntry: entry, - }) - } - } - - // Resolve dependencies - err := operation.ResolveDependencies(reinstallAll, !noOptional, verbose) - if err != nil { - log.Fatalf("Error: could not resolve dependencies: %s\n", err) - } - if len(operation.UnresolvedDepends) != 0 { - if !force { - log.Fatalf("Error: the following dependencies could not be found in any repositories: %s\n", strings.Join(operation.UnresolvedDepends, ", ")) - } else { - log.Println("Warning: The following dependencies could not be found in any repositories: " + strings.Join(operation.UnresolvedDepends, ", ")) - } - } - - // Replace obsolete packages - operation.ReplaceObsoletePackages() - - // Check for conflicts - conflicts, err := operation.CheckForConflicts() - if err != nil { - log.Fatalf("Error: could not complete package conflict check: %s\n", err) - } - if len(conflicts) > 0 { - if !force { - log.Println("Error: conflicting packages found") - } else { - log.Fatalf("Warning: conflicting packages found") - } - for pkg, conflict := range conflicts { - fmt.Printf("%s is in conflict with the following packages: %s\n", pkg, strings.Join(conflict, ", ")) - } - if !force { - os.Exit(0) - } - } + // Create Installation Operation + operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallMethod, !noOptional, force, verbose, subcommandArgs...) // Show operation summary operation.ShowOperationSummary() @@ -336,81 +270,17 @@ func resolveCommand() { log.Fatalf("Error: could not run hooks: %s\n", err) } case update: + // Check for required permissions if os.Getuid() != 0 { log.Fatalf("Error: this subcommand needs to be run with superuser permissions") } - // Sync repositories - if !nosync { - for _, repo := range bpmlib.BPMConfig.Repositories { - fmt.Printf("Fetching package database for repository (%s)...\n", repo.Name) - err := repo.SyncLocalDatabase() - if err != nil { - log.Fatalf("Error: could not sync local database for repository (%s): %s\n", repo.Name, err) - } - } - fmt.Println("All package databases synced successfully!") - } - - bpmlib.ReadConfig() - - // Get installed packages and check for updates - pkgs, err := bpmlib.GetInstalledPackages(rootDir) + // Create Update Operation + operation, err := bpmlib.UpdatePackages(rootDir, !nosync, !noOptional, force, verbose) if err != nil { - log.Fatalf("Error: could not get installed packages: %s\n", err) + log.Fatalf("Error: could not update packages: %s\n", err) } - operation := bpmlib.BPMOperation{ - Actions: make([]bpmlib.OperationAction, 0), - UnresolvedDepends: make([]string, 0), - Changes: make(map[string]string), - RootDir: rootDir, - ForceInstallationReason: bpmlib.Unknown, - } - - // Search for packages - for _, pkg := range pkgs { - if slices.Contains(bpmlib.BPMConfig.IgnorePackages, pkg) { - continue - } - var entry *bpmlib.RepositoryEntry - // Check if installed package can be replaced and install that instead - if e := bpmlib.FindReplacement(pkg); e != nil { - entry = e - } else if entry, _, err = bpmlib.GetRepositoryEntry(pkg); err != nil { - continue - } - - installedInfo := bpmlib.GetPackageInfo(pkg, rootDir) - if installedInfo == nil { - log.Fatalf("Error: could not get package info for (%s)\n", pkg) - } else { - comparison := bpmlib.ComparePackageVersions(*entry.Info, *installedInfo) - if comparison > 0 || reinstall { - operation.AppendAction(&bpmlib.FetchPackageAction{ - IsDependency: false, - RepositoryEntry: entry, - }) - } - } - } - - // Check for new dependencies in updated packages - err = operation.ResolveDependencies(reinstallAll, !noOptional, verbose) - if err != nil { - log.Fatalf("Error: could not resolve dependencies: %s\n", err) - } - if len(operation.UnresolvedDepends) != 0 { - if !force { - log.Fatalf("Error: the following dependencies could not be found in any repositories: %s\n", strings.Join(operation.UnresolvedDepends, ", ")) - } else { - log.Println("Warning: The following dependencies could not be found in any repositories: " + strings.Join(operation.UnresolvedDepends, ", ")) - } - } - - // Replace obsolete packages - operation.ReplaceObsoletePackages() - // Show operation summary operation.ShowOperationSummary() @@ -438,9 +308,12 @@ func resolveCommand() { log.Fatalf("Error: could not run hooks: %s\n", err) } case sync: + // Check for required permissions if os.Getuid() != 0 { log.Fatalf("Error: this subcommand needs to be run with superuser permissions") } + + // Confirmation Prompt if !yesAll { fmt.Printf("Are you sure you wish to sync all databases? [y\\N] ") reader := bufio.NewReader(os.Stdin) @@ -450,54 +323,28 @@ func resolveCommand() { os.Exit(1) } } - for _, repo := range bpmlib.BPMConfig.Repositories { - fmt.Printf("Fetching package database for repository (%s)...\n", repo.Name) - err := repo.SyncLocalDatabase() - if err != nil { - log.Fatalf("Error: could not sync local database for repository (%s): %s\n", repo.Name, err) - } + + err := bpmlib.SyncDatabase(verbose) + if err != nil { + log.Fatalf("Error: could not sync local database: %s\n", err) } + fmt.Println("All package databases synced successfully!") case remove: + // Check for required permissions if os.Getuid() != 0 { log.Fatalf("Error: this subcommand needs to be run with superuser permissions") } - packages := subcommandArgs - if len(packages) == 0 { + + if len(subcommandArgs) == 0 { fmt.Println("No packages were given") return } - operation := &bpmlib.BPMOperation{ - Actions: make([]bpmlib.OperationAction, 0), - UnresolvedDepends: make([]string, 0), - Changes: make(map[string]string), - RootDir: rootDir, - } - - // Search for packages - for _, pkg := range packages { - bpmpkg := bpmlib.GetPackage(pkg, rootDir) - if bpmpkg == nil { - continue - } - operation.AppendAction(&bpmlib.RemovePackageAction{BpmPackage: bpmpkg}) - } - - // Skip needed packages if the --unused flag is on - if removeUnused { - err := operation.RemoveNeededPackages() - if err != nil { - log.Fatalf("Error: could not skip needed packages: %s\n", err) - } - } - - // Do package cleanup - if doCleanup { - err := operation.Cleanup(verbose) - if err != nil { - log.Fatalf("Error: could not perform cleanup for operation: %s\n", err) - } + // Remove packages + operation, err := bpmlib.RemovePackages(rootDir, removeUnused, doCleanup, verbose, subcommandArgs...) + if err != nil { + log.Fatalf("Error: could not remove packages: %s\n", err) } // Show operation summary @@ -515,7 +362,7 @@ func resolveCommand() { } // Execute operation - err := operation.Execute(verbose, force) + err = operation.Execute(verbose, force) if err != nil { log.Fatalf("Error: could not complete operation: %s\n", err) } @@ -527,21 +374,15 @@ func resolveCommand() { log.Fatalf("Error: could not run hooks: %s\n", err) } case cleanup: + // Check for required permissions if os.Getuid() != 0 { log.Fatalf("Error: this subcommand needs to be run with superuser permissions") } - operation := &bpmlib.BPMOperation{ - Actions: make([]bpmlib.OperationAction, 0), - UnresolvedDepends: make([]string, 0), - Changes: make(map[string]string), - RootDir: rootDir, - } - - // Do package cleanup - err := operation.Cleanup(verbose) + // Do cleanup + operation, err := bpmlib.CleanupPackages(rootDir, verbose) if err != nil { - log.Fatalf("Error: could not perform cleanup for operation: %s\n", err) + log.Fatalf("Error: could not cleanup packages: %s\n", err) } // Show operation summary @@ -711,7 +552,6 @@ func resolveFlags() { updateFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing") updateFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts") updateFlagSet.BoolVar(&force, "f", false, "Force update by skipping architecture and dependency resolution") - updateFlagSet.BoolVar(&reinstall, "reinstall", false, "Fetches and reinstalls all packages even if they do not have a newer version available") updateFlagSet.BoolVar(&nosync, "no-sync", false, "Skips package database syncing") updateFlagSet.Usage = printHelp // Sync flags diff --git a/src/bpmlib/general.go b/src/bpmlib/general.go new file mode 100644 index 0000000..57d7eb2 --- /dev/null +++ b/src/bpmlib/general.go @@ -0,0 +1,250 @@ +package bpmlib + +import ( + "fmt" + "log" + "os" + "slices" + "strings" +) + +type ReinstallMethod uint8 + +const ( + ReinstallMethodNone ReinstallMethod = iota + ReinstallMethodSpecified ReinstallMethod = iota + ReinstallMethodAll ReinstallMethod = iota +) + +// InstallPackages installs the specified packages into the given root directory by fetching them from repositories or directly from local bpm archives +func InstallPackages(rootDir string, installationReason InstallationReason, reinstallMethod ReinstallMethod, installOptionalDependencies, forceInstallation, verbose bool, packages ...string) (operation *BPMOperation, err error) { + // Setup operation struct + operation = &BPMOperation{ + Actions: make([]OperationAction, 0), + UnresolvedDepends: make([]string, 0), + Changes: make(map[string]string), + RootDir: rootDir, + ForceInstallationReason: installationReason, + } + + // Resolve packages + for _, pkg := range packages { + if stat, err := os.Stat(pkg); err == nil && !stat.IsDir() { + bpmpkg, err := ReadPackage(pkg) + if err != nil { + return nil, fmt.Errorf("could not read package: %s", err) + } + if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) && GetPackageInfo(bpmpkg.PkgInfo.Name, rootDir).GetFullVersion() == bpmpkg.PkgInfo.GetFullVersion() { + continue + } + operation.AppendAction(&InstallPackageAction{ + File: pkg, + IsDependency: false, + BpmPackage: bpmpkg, + }) + } else { + var entry *RepositoryEntry + + if e, _, err := GetRepositoryEntry(pkg); err == nil { + entry = e + } else if isVirtual, p := IsVirtualPackage(pkg, rootDir); isVirtual { + entry, _, err = GetRepositoryEntry(p) + if err != nil { + return nil, fmt.Errorf("could not find package (%s) in any repositor", p) + } + } else if e := ResolveVirtualPackage(pkg); e != nil { + entry = e + } else { + return nil, fmt.Errorf("could not find package (%s) in any repository", pkg) + } + if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(entry.Info.Name, rootDir) && GetPackageInfo(entry.Info.Name, rootDir).GetFullVersion() == entry.Info.GetFullVersion() { + continue + } + operation.AppendAction(&FetchPackageAction{ + IsDependency: false, + RepositoryEntry: entry, + }) + } + } + + // Resolve dependencies + err = operation.ResolveDependencies(reinstallMethod == ReinstallMethodAll, installOptionalDependencies, verbose) + if err != nil { + return nil, fmt.Errorf("could not resolve dependencies: %s", err) + } + if len(operation.UnresolvedDepends) != 0 { + if !forceInstallation { + return nil, fmt.Errorf("dependencies (%s) could not be found in any repositories", strings.Join(operation.UnresolvedDepends, ", ")) + } else if verbose { + log.Println("Warning: The following dependencies could not be found in any repositories: " + strings.Join(operation.UnresolvedDepends, ", ")) + } + } + + // Replace obsolete packages + operation.ReplaceObsoletePackages() + + // Check for conflicts + conflicts, err := operation.CheckForConflicts() + if err != nil { + return nil, fmt.Errorf("could not complete package conflict check: %s", err) + } + if len(conflicts) > 0 { + if verbose { + for pkg, conflict := range conflicts { + fmt.Printf("%s is in conflict with packages (%s)\n", pkg, strings.Join(conflict, ", ")) + } + } + if !forceInstallation { + return nil, fmt.Errorf("conflicting packages found") + } else { + log.Println("Warning: conflicting packages found") + } + } + + return operation, nil +} + +// RemovePackages removes the specified packages from the given root directory +func RemovePackages(rootDir string, removeUnusedPackagesOnly, cleanupDependencies, verbose bool, packages ...string) (operation *BPMOperation, err error) { + operation = &BPMOperation{ + Actions: make([]OperationAction, 0), + UnresolvedDepends: make([]string, 0), + Changes: make(map[string]string), + RootDir: rootDir, + } + + // Search for packages + for _, pkg := range packages { + bpmpkg := GetPackage(pkg, rootDir) + if bpmpkg == nil { + continue + } + operation.AppendAction(&RemovePackageAction{BpmPackage: bpmpkg}) + } + + // Do not remove packages which other packages depend on + if removeUnusedPackagesOnly { + err := operation.RemoveNeededPackages() + if err != nil { + return nil, fmt.Errorf("could not skip needed packages: %s", err) + } + } + + // Do package cleanup + if cleanupDependencies { + err := operation.Cleanup(verbose) + if err != nil { + return nil, fmt.Errorf("could not perform cleanup for operation: %s", err) + } + } + return operation, nil +} + +// CleanupPackages finds packages installed as dependencies which are no longer required by the rest of the system in the given root directory +func CleanupPackages(rootDir string, verbose bool) (operation *BPMOperation, err error) { + operation = &BPMOperation{ + Actions: make([]OperationAction, 0), + UnresolvedDepends: make([]string, 0), + Changes: make(map[string]string), + RootDir: rootDir, + } + + // Do package cleanup + err = operation.Cleanup(verbose) + if err != nil { + return nil, fmt.Errorf("could not perform cleanup for operation: %s", err) + } + + return operation, nil +} + +// UpdatePackages fetches the newest versions of all installed packages from +func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependencies, forceInstallation, verbose bool) (operation *BPMOperation, err error) { + // Sync repositories + if syncDatabase { + err := SyncDatabase(verbose) + if err != nil { + return nil, fmt.Errorf("could not sync local database: %s", err) + } + if verbose { + fmt.Println("All package databases synced successfully!") + } + } + + // Reload config and local databases + ReadConfig() + + // Get installed packages and check for updates + pkgs, err := GetInstalledPackages(rootDir) + if err != nil { + return nil, fmt.Errorf("could not get installed packages: %s", err) + } + + operation = &BPMOperation{ + Actions: make([]OperationAction, 0), + UnresolvedDepends: make([]string, 0), + Changes: make(map[string]string), + RootDir: rootDir, + ForceInstallationReason: Unknown, + } + + // Search for packages + for _, pkg := range pkgs { + if slices.Contains(BPMConfig.IgnorePackages, pkg) { + continue + } + var entry *RepositoryEntry + // Check if installed package can be replaced and install that instead + if e := FindReplacement(pkg); e != nil { + entry = e + } else if entry, _, err = GetRepositoryEntry(pkg); err != nil { + continue + } + + installedInfo := GetPackageInfo(pkg, rootDir) + if installedInfo == nil { + return nil, fmt.Errorf("could not get package info for package (%s)", pkg) + } else { + comparison := ComparePackageVersions(*entry.Info, *installedInfo) + if comparison > 0 { + operation.AppendAction(&FetchPackageAction{ + IsDependency: false, + RepositoryEntry: entry, + }) + } + } + } + + // Check for new dependencies in updated packages + err = operation.ResolveDependencies(false, installOptionalDependencies, verbose) + if err != nil { + return nil, fmt.Errorf("could not resolve dependencies: %s", err) + } + if len(operation.UnresolvedDepends) != 0 { + if !forceInstallation { + return nil, fmt.Errorf("dependencies (%s) could not be found in any repositories", strings.Join(operation.UnresolvedDepends, ", ")) + } else if verbose { + log.Printf("Warning: dependencies (%s) could not be found in any repositories\n", strings.Join(operation.UnresolvedDepends, ", ")) + } + } + + // Replace obsolete packages + operation.ReplaceObsoletePackages() + return operation, nil +} + +// SyncDatabase syncs all databases declared in /etc/bpm.conf +func SyncDatabase(verbose bool) (err error) { + for _, repo := range BPMConfig.Repositories { + if verbose { + fmt.Printf("Fetching package database for repository (%s)...\n", repo.Name) + } + + err := repo.SyncLocalDatabase() + if err != nil { + return err + } + } + + return nil +} From e60381beb1d923177489f952fc619adf179cc163 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Tue, 8 Apr 2025 17:41:14 +0300 Subject: [PATCH 07/23] Rename constants --- src/bpm/main.go | 6 ++--- src/bpmlib/general.go | 2 +- src/bpmlib/operations.go | 6 ++--- src/bpmlib/packages.go | 52 ++++++++++++++++++++-------------------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/bpm/main.go b/src/bpm/main.go index f263423..d38ef09 100644 --- a/src/bpm/main.go +++ b/src/bpm/main.go @@ -214,12 +214,12 @@ func resolveCommand() { } // Check if installationReason argument is valid - ir := bpmlib.Unknown + ir := bpmlib.InstallationReasonUnknown switch installationReason { case "manual": - ir = bpmlib.Manual + ir = bpmlib.InstallationReasonManual case "dependency": - ir = bpmlib.Dependency + ir = bpmlib.InstallationReasonDependency case "": default: log.Fatalf("Error: %s is not a valid installation reason", installationReason) diff --git a/src/bpmlib/general.go b/src/bpmlib/general.go index 57d7eb2..dfe51c9 100644 --- a/src/bpmlib/general.go +++ b/src/bpmlib/general.go @@ -185,7 +185,7 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci UnresolvedDepends: make([]string, 0), Changes: make(map[string]string), RootDir: rootDir, - ForceInstallationReason: Unknown, + ForceInstallationReason: InstallationReasonUnknown, } // Search for packages diff --git a/src/bpmlib/operations.go b/src/bpmlib/operations.go index 56efc48..867b61c 100644 --- a/src/bpmlib/operations.go +++ b/src/bpmlib/operations.go @@ -217,7 +217,7 @@ func (operation *BPMOperation) Cleanup(verbose bool) error { // Get manually installed packages, resolve all their dependencies and add them to the keepPackages slice keepPackages := make([]string, 0) for _, pkg := range slices.Clone(installedPackages) { - if GetInstallationReason(pkg.Name, operation.RootDir) != Manual { + if GetInstallationReason(pkg.Name, operation.RootDir) != InstallationReasonManual { continue } @@ -475,13 +475,13 @@ func (operation *BPMOperation) Execute(verbose, force bool) error { if err != nil { return errors.New(fmt.Sprintf("could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err)) } - if operation.ForceInstallationReason != Unknown && !value.IsDependency { + if operation.ForceInstallationReason != InstallationReasonUnknown && !value.IsDependency { err := SetInstallationReason(bpmpkg.PkgInfo.Name, operation.ForceInstallationReason, operation.RootDir) if err != nil { return errors.New(fmt.Sprintf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err)) } } else if value.IsDependency && !isReinstall { - err := SetInstallationReason(bpmpkg.PkgInfo.Name, Dependency, operation.RootDir) + err := SetInstallationReason(bpmpkg.PkgInfo.Name, InstallationReasonDependency, operation.RootDir) if err != nil { return errors.New(fmt.Sprintf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err)) } diff --git a/src/bpmlib/packages.go b/src/bpmlib/packages.go index d7008b7..abfffcc 100644 --- a/src/bpmlib/packages.go +++ b/src/bpmlib/packages.go @@ -74,9 +74,9 @@ func (pkgInfo *PackageInfo) GetFullVersion() string { type InstallationReason string const ( - Manual InstallationReason = "manual" - Dependency InstallationReason = "dependency" - Unknown InstallationReason = "unknown" + InstallationReasonManual InstallationReason = "manual" + InstallationReasonDependency InstallationReason = "dependency" + InstallationReasonUnknown InstallationReason = "unknown" ) func ComparePackageVersions(info1, info2 PackageInfo) int { @@ -90,19 +90,19 @@ func GetInstallationReason(pkg, rootDir string) InstallationReason { installedDir := path.Join(rootDir, "var/lib/bpm/installed/") pkgDir := path.Join(installedDir, pkg) if stat, err := os.Stat(path.Join(pkgDir, "installation_reason")); err != nil || stat.IsDir() { - return Manual + return InstallationReasonManual } b, err := os.ReadFile(path.Join(pkgDir, "installation_reason")) if err != nil { - return Unknown + return InstallationReasonUnknown } reason := strings.TrimSpace(string(b)) if reason == "manual" { - return Manual + return InstallationReasonManual } else if reason == "dependency" { - return Dependency + return InstallationReasonDependency } - return Unknown + return InstallationReasonUnknown } func SetInstallationReason(pkg string, reason InstallationReason, rootDir string) error { @@ -280,15 +280,15 @@ func ReadPackageScripts(filename string) (map[string]string, error) { return ret, nil } -type Operation uint8 +type packageOperation uint8 const ( - Install Operation = 0 - Update = 1 - Remove = 2 + packageOperationInstall packageOperation = 0 + packageOperationUpdate = 1 + packageOperationRemove = 2 ) -func executePackageScripts(filename, rootDir string, operation Operation, postOperation bool) error { +func executePackageScripts(filename, rootDir string, operation packageOperation, postOperation bool) error { pkgInfo, err := ReadPackage(filename) if err != nil { return err @@ -320,11 +320,11 @@ func executePackageScripts(filename, rootDir string, operation Operation, postOp cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_NAME=%s", pkgInfo.PkgInfo.Name)) cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_DESC=%s", pkgInfo.PkgInfo.Description)) cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_VERSION=%s", pkgInfo.PkgInfo.Version)) - if operation != Install { + if operation != packageOperationInstall { cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_OLD_VERSION=%s", GetPackageInfo(pkgInfo.PkgInfo.Name, rootDir).Version)) } cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_REVISION=%d", pkgInfo.PkgInfo.Revision)) - if operation != Install { + if operation != packageOperationInstall { cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_OLD_REVISION=%d", GetPackageInfo(pkgInfo.PkgInfo.Name, rootDir).Revision)) } cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_URL=%s", pkgInfo.PkgInfo.Url)) @@ -349,7 +349,7 @@ func executePackageScripts(filename, rootDir string, operation Operation, postOp return nil } - if operation == Install { + if operation == packageOperationInstall { if val, ok := scripts["pre_install.sh"]; !postOperation && ok { err := run("pre_install.sh", val) if err != nil { @@ -362,7 +362,7 @@ func executePackageScripts(filename, rootDir string, operation Operation, postOp return err } } - } else if operation == Update { + } else if operation == packageOperationUpdate { if val, ok := scripts["pre_update.sh"]; !postOperation && ok { err := run("pre_update.sh", val) if err != nil { @@ -375,7 +375,7 @@ func executePackageScripts(filename, rootDir string, operation Operation, postOp return err } } - } else if operation == Remove { + } else if operation == packageOperationRemove { if val, ok := scripts["pre_remove.sh"]; !postOperation && ok { err := run("pre_remove.sh", val) if err != nil { @@ -478,12 +478,12 @@ func CreateReadableInfo(showArchitecture, showType, showPackageRelations bool, p func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) error { if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) { - err := executePackageScripts(filename, rootDir, Install, false) + err := executePackageScripts(filename, rootDir, packageOperationInstall, false) if err != nil { return err } } else { - err := executePackageScripts(filename, rootDir, Update, false) + err := executePackageScripts(filename, rootDir, packageOperationUpdate, false) if err != nil { return err } @@ -629,12 +629,12 @@ func isSplitPackage(filename string) bool { func compilePackage(bpmpkg *BPMPackage, filename, rootDir string, verbose, binaryPkgFromSrc, skipCheck, keepTempDir bool) (error, []string) { var files []string if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) { - err := executePackageScripts(filename, rootDir, Install, false) + err := executePackageScripts(filename, rootDir, packageOperationInstall, false) if err != nil { return err, nil } } else { - err := executePackageScripts(filename, rootDir, Update, false) + err := executePackageScripts(filename, rootDir, packageOperationUpdate, false) if err != nil { return err, nil } @@ -747,12 +747,12 @@ func compilePackage(bpmpkg *BPMPackage, filename, rootDir string, verbose, binar } fmt.Println("Running source.sh file...") if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) { - err = executePackageScripts(filename, rootDir, Install, false) + err = executePackageScripts(filename, rootDir, packageOperationInstall, false) if err != nil { return err, nil } } else { - err = executePackageScripts(filename, rootDir, Update, false) + err = executePackageScripts(filename, rootDir, packageOperationUpdate, false) if err != nil { return err, nil } @@ -1246,12 +1246,12 @@ func installPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc, } if !packageInstalled { - err = executePackageScripts(filename, rootDir, Install, true) + err = executePackageScripts(filename, rootDir, packageOperationInstall, true) if err != nil { return err } } else { - err = executePackageScripts(filename, rootDir, Update, true) + err = executePackageScripts(filename, rootDir, packageOperationUpdate, true) if err != nil { return err } From 151de2112ef18da2e7672aab82af0675ee31a229 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Tue, 8 Apr 2025 19:20:49 +0300 Subject: [PATCH 08/23] Fix virtual packages not being accounted for in GetDependants function --- src/bpmlib/packages.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/bpmlib/packages.go b/src/bpmlib/packages.go index abfffcc..dbc137c 100644 --- a/src/bpmlib/packages.go +++ b/src/bpmlib/packages.go @@ -1308,8 +1308,21 @@ func (pkgInfo *PackageInfo) GetDependants(rootDir string) ([]string, error) { if bpmpkg == nil { return nil, errors.New("package not found: " + pkg) } - if bpmpkg.PkgInfo.Name != pkgInfo.Name && slices.Contains(bpmpkg.PkgInfo.GetAllDependencies(false, true), pkgInfo.Name) { + if bpmpkg.PkgInfo.Name == pkgInfo.Name { + continue + } + + dependencies := bpmpkg.PkgInfo.GetAllDependencies(false, true) + + if slices.Contains(dependencies, pkgInfo.Name) { ret = append(ret, pkg) + continue + } + for _, vpkg := range pkgInfo.Provides { + if slices.Contains(dependencies, vpkg) { + ret = append(ret, pkg) + break + } } } From d1a2d28cff6672e46d7722cc9acf85f6a78902ff Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 10 Apr 2025 13:06:18 +0300 Subject: [PATCH 09/23] Fix some error handling and comments --- src/bpm/main.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/bpm/main.go b/src/bpm/main.go index d38ef09..8cb250f 100644 --- a/src/bpm/main.go +++ b/src/bpm/main.go @@ -235,8 +235,11 @@ func resolveCommand() { reinstallMethod = bpmlib.ReinstallMethodNone } - // Create Installation Operation + // Create installation operation operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallMethod, !noOptional, force, verbose, subcommandArgs...) + if err != nil { + log.Fatalf("Error: could not setup operation: %s\n", err) + } // Show operation summary operation.ShowOperationSummary() @@ -275,10 +278,10 @@ func resolveCommand() { log.Fatalf("Error: this subcommand needs to be run with superuser permissions") } - // Create Update Operation + // Create update operation operation, err := bpmlib.UpdatePackages(rootDir, !nosync, !noOptional, force, verbose) if err != nil { - log.Fatalf("Error: could not update packages: %s\n", err) + log.Fatalf("Error: could not setuo operation: %s\n", err) } // Show operation summary @@ -324,6 +327,7 @@ func resolveCommand() { } } + // Sync databases err := bpmlib.SyncDatabase(verbose) if err != nil { log.Fatalf("Error: could not sync local database: %s\n", err) @@ -341,10 +345,10 @@ func resolveCommand() { return } - // Remove packages + // Create remove operation operation, err := bpmlib.RemovePackages(rootDir, removeUnused, doCleanup, verbose, subcommandArgs...) if err != nil { - log.Fatalf("Error: could not remove packages: %s\n", err) + log.Fatalf("Error: could not setup operation: %s\n", err) } // Show operation summary @@ -379,10 +383,10 @@ func resolveCommand() { log.Fatalf("Error: this subcommand needs to be run with superuser permissions") } - // Do cleanup + // Create cleanup operation operation, err := bpmlib.CleanupPackages(rootDir, verbose) if err != nil { - log.Fatalf("Error: could not cleanup packages: %s\n", err) + log.Fatalf("Error: could not setup operation: %s\n", err) } // Show operation summary From 14fe71842efd19d509550b53dd7c5d97aa569020 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 10 Apr 2025 14:38:32 +0300 Subject: [PATCH 10/23] Added custom error types --- src/bpm/main.go | 19 ++++++++++++++----- src/bpmlib/errors.go | 31 +++++++++++++++++++++++++++++++ src/bpmlib/general.go | 33 ++++++++++++++++++++------------- 3 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 src/bpmlib/errors.go diff --git a/src/bpm/main.go b/src/bpm/main.go index 8cb250f..1b6a3d1 100644 --- a/src/bpm/main.go +++ b/src/bpm/main.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "errors" "flag" "fmt" "git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib" @@ -237,7 +238,9 @@ func resolveCommand() { // Create installation operation operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallMethod, !noOptional, force, verbose, subcommandArgs...) - if err != nil { + if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) { + log.Fatalf("Error: %s", err) + } else if err != nil { log.Fatalf("Error: could not setup operation: %s\n", err) } @@ -280,8 +283,10 @@ func resolveCommand() { // Create update operation operation, err := bpmlib.UpdatePackages(rootDir, !nosync, !noOptional, force, verbose) - if err != nil { - log.Fatalf("Error: could not setuo operation: %s\n", err) + if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) { + log.Fatalf("Error: %s", err) + } else if err != nil { + log.Fatalf("Error: could not setup operation: %s\n", err) } // Show operation summary @@ -347,7 +352,9 @@ func resolveCommand() { // Create remove operation operation, err := bpmlib.RemovePackages(rootDir, removeUnused, doCleanup, verbose, subcommandArgs...) - if err != nil { + if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) { + log.Fatalf("Error: %s", err) + } else if err != nil { log.Fatalf("Error: could not setup operation: %s\n", err) } @@ -385,7 +392,9 @@ func resolveCommand() { // Create cleanup operation operation, err := bpmlib.CleanupPackages(rootDir, verbose) - if err != nil { + if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) { + log.Fatalf("Error: %s", err) + } else if err != nil { log.Fatalf("Error: could not setup operation: %s\n", err) } diff --git a/src/bpmlib/errors.go b/src/bpmlib/errors.go new file mode 100644 index 0000000..b9d193e --- /dev/null +++ b/src/bpmlib/errors.go @@ -0,0 +1,31 @@ +package bpmlib + +import ( + "fmt" + "strings" +) + +type PackageNotFoundErr struct { + packages []string +} + +func (e PackageNotFoundErr) Error() string { + return "The following packages were not found in any repositories: " + strings.Join(e.packages, ", ") +} + +type DependencyNotFoundErr struct { + dependencies []string +} + +func (e DependencyNotFoundErr) Error() string { + return "The following dependencies were not found in any repositories: " + strings.Join(e.dependencies, ", ") +} + +type PackageConflictErr struct { + pkg string + conflicts []string +} + +func (e PackageConflictErr) Error() string { + return fmt.Sprintf("Package (%s) is in conflict with the following packages: %s", e.pkg, strings.Join(e.conflicts, ", ")) +} diff --git a/src/bpmlib/general.go b/src/bpmlib/general.go index dfe51c9..1d5ee80 100644 --- a/src/bpmlib/general.go +++ b/src/bpmlib/general.go @@ -1,11 +1,11 @@ package bpmlib import ( + "errors" "fmt" "log" "os" "slices" - "strings" ) type ReinstallMethod uint8 @@ -28,6 +28,7 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein } // Resolve packages + pkgsNotFound := make([]string, 0) for _, pkg := range packages { if stat, err := os.Stat(pkg); err == nil && !stat.IsDir() { bpmpkg, err := ReadPackage(pkg) @@ -50,12 +51,14 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein } else if isVirtual, p := IsVirtualPackage(pkg, rootDir); isVirtual { entry, _, err = GetRepositoryEntry(p) if err != nil { - return nil, fmt.Errorf("could not find package (%s) in any repositor", p) + pkgsNotFound = append(pkgsNotFound, pkg) + continue } } else if e := ResolveVirtualPackage(pkg); e != nil { entry = e } else { - return nil, fmt.Errorf("could not find package (%s) in any repository", pkg) + pkgsNotFound = append(pkgsNotFound, pkg) + continue } if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(entry.Info.Name, rootDir) && GetPackageInfo(entry.Info.Name, rootDir).GetFullVersion() == entry.Info.GetFullVersion() { continue @@ -67,6 +70,11 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein } } + // Return error if not all packages are found + if len(pkgsNotFound) != 0 { + return nil, PackageNotFoundErr{pkgsNotFound} + } + // Resolve dependencies err = operation.ResolveDependencies(reinstallMethod == ReinstallMethodAll, installOptionalDependencies, verbose) if err != nil { @@ -74,9 +82,9 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein } if len(operation.UnresolvedDepends) != 0 { if !forceInstallation { - return nil, fmt.Errorf("dependencies (%s) could not be found in any repositories", strings.Join(operation.UnresolvedDepends, ", ")) + return nil, DependencyNotFoundErr{operation.UnresolvedDepends} } else if verbose { - log.Println("Warning: The following dependencies could not be found in any repositories: " + strings.Join(operation.UnresolvedDepends, ", ")) + log.Printf("Warning: %s", DependencyNotFoundErr{operation.UnresolvedDepends}) } } @@ -89,15 +97,14 @@ func InstallPackages(rootDir string, installationReason InstallationReason, rein return nil, fmt.Errorf("could not complete package conflict check: %s", err) } if len(conflicts) > 0 { - if verbose { - for pkg, conflict := range conflicts { - fmt.Printf("%s is in conflict with packages (%s)\n", pkg, strings.Join(conflict, ", ")) - } + err = nil + for pkg, conflict := range conflicts { + err = errors.Join(err, PackageConflictErr{pkg, conflict}) } if !forceInstallation { - return nil, fmt.Errorf("conflicting packages found") + return nil, err } else { - log.Println("Warning: conflicting packages found") + log.Printf("Warning: %s", err) } } @@ -222,9 +229,9 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci } if len(operation.UnresolvedDepends) != 0 { if !forceInstallation { - return nil, fmt.Errorf("dependencies (%s) could not be found in any repositories", strings.Join(operation.UnresolvedDepends, ", ")) + return nil, DependencyNotFoundErr{operation.UnresolvedDepends} } else if verbose { - log.Printf("Warning: dependencies (%s) could not be found in any repositories\n", strings.Join(operation.UnresolvedDepends, ", ")) + log.Printf("Warning: %s", DependencyNotFoundErr{operation.UnresolvedDepends}) } } From 3f2d5cf7a15582d90b5b20e6c7f536b111ca0df6 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 10 Apr 2025 14:54:41 +0300 Subject: [PATCH 11/23] Remove all log.Fatal and os.Exit calls from bpmlib --- src/bpm/main.go | 29 ++++++++++++++++++++++++++++- src/bpmlib/config.go | 19 ++++++++++++------- src/bpmlib/general.go | 5 ++++- src/bpmlib/operations.go | 9 +++------ 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/bpm/main.go b/src/bpm/main.go index 1b6a3d1..702e950 100644 --- a/src/bpm/main.go +++ b/src/bpm/main.go @@ -43,7 +43,10 @@ var doCleanup = false var showRepoInfo = false func main() { - bpmlib.ReadConfig() + err := bpmlib.ReadConfig() + if err != nil { + log.Fatalf("Error: could not read BPM config: %s", err) + } resolveFlags() resolveCommand() } @@ -244,6 +247,12 @@ func resolveCommand() { log.Fatalf("Error: could not setup operation: %s\n", err) } + // Exit if operation contains no actions + if len(operation.Actions) == 0 { + fmt.Println("No action needs to be taken") + return + } + // Show operation summary operation.ShowOperationSummary() @@ -289,6 +298,12 @@ func resolveCommand() { log.Fatalf("Error: could not setup operation: %s\n", err) } + // Exit if operation contains no actions + if len(operation.Actions) == 0 { + fmt.Println("No action needs to be taken") + return + } + // Show operation summary operation.ShowOperationSummary() @@ -358,6 +373,12 @@ func resolveCommand() { log.Fatalf("Error: could not setup operation: %s\n", err) } + // Exit if operation contains no actions + if len(operation.Actions) == 0 { + fmt.Println("No action needs to be taken") + return + } + // Show operation summary operation.ShowOperationSummary() @@ -398,6 +419,12 @@ func resolveCommand() { log.Fatalf("Error: could not setup operation: %s\n", err) } + // Exit if operation contains no actions + if len(operation.Actions) == 0 { + fmt.Println("No action needs to be taken") + return + } + // Show operation summary operation.ShowOperationSummary() diff --git a/src/bpmlib/config.go b/src/bpmlib/config.go index 18e03c2..8c3e50a 100644 --- a/src/bpmlib/config.go +++ b/src/bpmlib/config.go @@ -2,7 +2,6 @@ package bpmlib import ( "gopkg.in/yaml.v3" - "log" "os" ) @@ -17,14 +16,16 @@ type BPMConfigStruct struct { var BPMConfig BPMConfigStruct -func ReadConfig() { - if _, err := os.Stat("/etc/bpm.conf"); os.IsNotExist(err) { - log.Fatal(err) +func ReadConfig() (err error) { + if _, err = os.Stat("/etc/bpm.conf"); os.IsNotExist(err) { + return err } + bytes, err := os.ReadFile("/etc/bpm.conf") if err != nil { - log.Fatal(err) + return err } + BPMConfig = BPMConfigStruct{ CompilationEnv: make([]string, 0), SilentCompilation: false, @@ -33,19 +34,23 @@ func ReadConfig() { } err = yaml.Unmarshal(bytes, &BPMConfig) if err != nil { - log.Fatal(err) + return err } + for i := len(BPMConfig.Repositories) - 1; i >= 0; i-- { if BPMConfig.Repositories[i].Disabled != nil && *BPMConfig.Repositories[i].Disabled { BPMConfig.Repositories = append(BPMConfig.Repositories[:i], BPMConfig.Repositories[i+1:]...) } } + for _, repo := range BPMConfig.Repositories { repo.Entries = make(map[string]*RepositoryEntry) repo.VirtualPackages = make(map[string][]string) err := repo.ReadLocalDatabase() if err != nil { - log.Fatal(err) + return err } } + + return nil } diff --git a/src/bpmlib/general.go b/src/bpmlib/general.go index 1d5ee80..c88ac32 100644 --- a/src/bpmlib/general.go +++ b/src/bpmlib/general.go @@ -179,7 +179,10 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci } // Reload config and local databases - ReadConfig() + err = ReadConfig() + if err != nil { + return nil, fmt.Errorf("could not read BPM config: %s", err) + } // Get installed packages and check for updates pkgs, err := GetInstalledPackages(rootDir) diff --git a/src/bpmlib/operations.go b/src/bpmlib/operations.go index 867b61c..a23acae 100644 --- a/src/bpmlib/operations.go +++ b/src/bpmlib/operations.go @@ -195,7 +195,7 @@ func (operation *BPMOperation) Cleanup(verbose bool) error { // Get all installed packages installedPackageNames, err := GetInstalledPackages(operation.RootDir) if err != nil { - log.Fatalf("Error: could not get installed packages: %s\n", err) + return fmt.Errorf("could not get installed packages: %s", err) } installedPackages := make([]*PackageInfo, len(installedPackageNames)) for i, value := range installedPackageNames { @@ -329,8 +329,8 @@ func (operation *BPMOperation) CheckForConflicts() (map[string][]string, error) func (operation *BPMOperation) ShowOperationSummary() { if len(operation.Actions) == 0 { - fmt.Println("All packages are up to date!") - os.Exit(0) + fmt.Println("No action needs to be taken") + return } for _, value := range operation.Actions { @@ -348,9 +348,6 @@ func (operation *BPMOperation) ShowOperationSummary() { installedInfo := GetPackageInfo(pkgInfo.Name, operation.RootDir) sourceInfo := "" if pkgInfo.Type == "source" { - if operation.RootDir != "/" { - log.Fatalf("cannot compile and install source packages to a different root directory") - } sourceInfo = "(From Source)" } From c767f269375cc98422ba23516a987a4ba5c4a5ce Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 10 Apr 2025 14:59:41 +0300 Subject: [PATCH 12/23] Remove direct source compilation (To be reworked) --- src/bpm/main.go | 11 - src/bpmlib/config.go | 15 +- src/bpmlib/operations.go | 4 +- src/bpmlib/packages.go | 471 +-------------------------------------- 4 files changed, 7 insertions(+), 494 deletions(-) diff --git a/src/bpm/main.go b/src/bpm/main.go index 702e950..45349f3 100644 --- a/src/bpm/main.go +++ b/src/bpm/main.go @@ -27,9 +27,6 @@ var subcommandArgs []string var rootDir = "/" var verbose = false var yesAll = false -var buildSource = false -var skipCheck = false -var keepTempDir = false var force = false var pkgListNumbers = false var pkgListNames = false @@ -524,9 +521,6 @@ func printHelp() { fmt.Println(" -v Show additional information about what BPM is doing") fmt.Println(" -y skips the confirmation prompt") fmt.Println(" -f skips dependency, conflict and architecture checking") - fmt.Println(" -o= set the binary package output directory (defaults to /var/lib/bpm/compiled)") - fmt.Println(" -c= set the compilation directory (defaults to /var/tmp)") - fmt.Println(" -b creates a binary package from a source package after compilation and saves it in the binary package output directory") fmt.Println(" -k keeps the compilation directory created by BPM after source package installation") fmt.Println(" --reinstall Reinstalls packages even if they do not have a newer version available") fmt.Println(" --reinstall-all Same as --reinstall but also reinstalls dependencies") @@ -575,11 +569,6 @@ func resolveFlags() { installFlagSet.StringVar(&rootDir, "R", "/", "Set the destination root") installFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing") installFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts") - installFlagSet.StringVar(&bpmlib.BPMConfig.BinaryOutputDir, "o", bpmlib.BPMConfig.BinaryOutputDir, "Set the binary output directory") - installFlagSet.StringVar(&bpmlib.BPMConfig.CompilationDir, "c", bpmlib.BPMConfig.CompilationDir, "Set the compilation directory") - installFlagSet.BoolVar(&buildSource, "b", false, "Build binary package from source package") - installFlagSet.BoolVar(&skipCheck, "s", false, "Skip check function during source compilation") - installFlagSet.BoolVar(&keepTempDir, "k", false, "Keep temporary directory after source compilation") installFlagSet.BoolVar(&force, "f", false, "Force installation by skipping architecture and dependency resolution") installFlagSet.BoolVar(&reinstall, "reinstall", false, "Reinstalls packages even if they do not have a newer version available") installFlagSet.BoolVar(&reinstallAll, "reinstall-all", false, "Same as --reinstall but also reinstalls dependencies") diff --git a/src/bpmlib/config.go b/src/bpmlib/config.go index 8c3e50a..fdbf246 100644 --- a/src/bpmlib/config.go +++ b/src/bpmlib/config.go @@ -6,12 +6,8 @@ import ( ) type BPMConfigStruct struct { - CompilationEnv []string `yaml:"compilation_env"` - SilentCompilation bool `yaml:"silent_compilation"` - BinaryOutputDir string `yaml:"binary_output_dir"` - CompilationDir string `yaml:"compilation_dir"` - IgnorePackages []string `yaml:"ignore_packages"` - Repositories []*Repository `yaml:"repositories"` + IgnorePackages []string `yaml:"ignore_packages"` + Repositories []*Repository `yaml:"repositories"` } var BPMConfig BPMConfigStruct @@ -26,12 +22,7 @@ func ReadConfig() (err error) { return err } - BPMConfig = BPMConfigStruct{ - CompilationEnv: make([]string, 0), - SilentCompilation: false, - BinaryOutputDir: "/var/lib/bpm/compiled/", - CompilationDir: "/var/tmp/", - } + BPMConfig = BPMConfigStruct{} err = yaml.Unmarshal(bytes, &BPMConfig) if err != nil { return err diff --git a/src/bpmlib/operations.go b/src/bpmlib/operations.go index a23acae..cb56419 100644 --- a/src/bpmlib/operations.go +++ b/src/bpmlib/operations.go @@ -465,9 +465,9 @@ func (operation *BPMOperation) Execute(verbose, force bool) error { isReinstall := IsPackageInstalled(bpmpkg.PkgInfo.Name, operation.RootDir) var err error if value.IsDependency { - err = installPackage(value.File, operation.RootDir, verbose, true, false, false, false) + err = installPackage(value.File, operation.RootDir, verbose, true) } else { - err = installPackage(value.File, operation.RootDir, verbose, force, false, false, false) + err = installPackage(value.File, operation.RootDir, verbose, force) } if err != nil { return errors.New(fmt.Sprintf("could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err)) diff --git a/src/bpmlib/packages.go b/src/bpmlib/packages.go index dbc137c..91ebf5a 100644 --- a/src/bpmlib/packages.go +++ b/src/bpmlib/packages.go @@ -8,16 +8,13 @@ import ( version "github.com/knqyf263/go-rpm-version" "gopkg.in/yaml.v3" "io" - "io/fs" "os" "os/exec" "path" - "path/filepath" "slices" "sort" "strconv" "strings" - "syscall" ) type BPMPackage struct { @@ -309,11 +306,6 @@ func executePackageScripts(filename, rootDir string, operation packageOperation, } cmd := exec.Command("/bin/bash", temp.Name()) - if !BPMConfig.SilentCompilation { - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } cmd.Dir = rootDir cmd.Env = os.Environ() cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_ROOT=%s", rootDir)) @@ -433,14 +425,6 @@ func ReadPackageInfo(contents string) (*PackageInfo, error) { return &pkgInfo, nil } -func CreateInfoFile(pkgInfo *PackageInfo) string { - b, err := yaml.Marshal(&pkgInfo) - if err != nil { - return "" - } - return string(b) -} - func CreateReadableInfo(showArchitecture, showType, showPackageRelations bool, pkgInfo *PackageInfo, rootDir string) string { ret := make([]string, 0) appendArray := func(label string, array []string) { @@ -611,447 +595,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) return nil } -func isSplitPackage(filename string) bool { - pkgInfo, err := ReadPackage(filename) - if err != nil { - return false - } - if pkgInfo.PkgInfo.Type != "source" { - return false - } - cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("test $(tar -tf %s | grep '^pkg.info' | wc -l) -eq 1", filename)) - if err := cmd.Run(); err == nil { - return false - } - return true -} - -func compilePackage(bpmpkg *BPMPackage, filename, rootDir string, verbose, binaryPkgFromSrc, skipCheck, keepTempDir bool) (error, []string) { - var files []string - if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) { - err := executePackageScripts(filename, rootDir, packageOperationInstall, false) - if err != nil { - return err, nil - } - } else { - err := executePackageScripts(filename, rootDir, packageOperationUpdate, false) - if err != nil { - return err, nil - } - } - //seenHardlinks := make(map[string]string) - file, err := os.Open(filename) - if err != nil { - return err, nil - } - - tr := tar.NewReader(file) - - temp := path.Join(BPMConfig.CompilationDir, "bpm_source-"+bpmpkg.PkgInfo.Name) - err = os.RemoveAll(temp) - if err != nil { - return err, nil - } - if verbose { - fmt.Println("Creating temp directory at: " + temp) - } - err = os.Mkdir(temp, 0755) - if err != nil { - return err, nil - } - err = os.Chown(temp, 65534, 65534) - if err != nil { - return err, nil - } - - for { - header, err := tr.Next() - if err == io.EOF { - break - } - if err != nil { - return err, nil - } - if strings.HasPrefix(header.Name, "source-files/") && header.Name != "source-files/" { - extractFilename := path.Join(temp, strings.TrimPrefix(header.Name, "source-files/")) - switch header.Typeflag { - case tar.TypeDir: - if err := os.Mkdir(extractFilename, 0755); err != nil { - if !os.IsExist(err) { - return err, nil - } - } else { - if verbose { - fmt.Println("Creating Directory: " + extractFilename) - } - err = os.Chown(extractFilename, 65534, 65534) - if err != nil { - return err, nil - } - } - case tar.TypeReg: - err := os.Remove(extractFilename) - if err != nil && !os.IsNotExist(err) { - return err, nil - } - outFile, err := os.Create(extractFilename) - if verbose { - fmt.Println("Creating File: " + extractFilename) - } - if err != nil { - return err, nil - } - err = os.Chown(extractFilename, 65534, 65534) - if err != nil { - return err, nil - } - if _, err := io.Copy(outFile, tr); err != nil { - return err, nil - } - if err := os.Chmod(extractFilename, header.FileInfo().Mode()); err != nil { - return err, nil - } - err = outFile.Close() - if err != nil { - return err, nil - } - case tar.TypeSymlink: - if verbose { - fmt.Println("Skipping symlink (Bundling symlinks in source packages is not supported)") - } - case tar.TypeLink: - if verbose { - fmt.Println("Skipping hard link (Bundling hard links in source packages is not supported)") - } - default: - return errors.New("unknown type (" + strconv.Itoa(int(header.Typeflag)) + ") in " + extractFilename), nil - } - } - if header.Name == "source.sh" { - bs, err := io.ReadAll(tr) - if err != nil { - return err, nil - } - err = os.WriteFile(path.Join(temp, "source.sh"), bs, 0644) - if err != nil { - return err, nil - } - err = os.Chown(path.Join(temp, "source.sh"), 65534, 65534) - if err != nil { - return err, nil - } - } - } - if _, err := os.Stat(path.Join(temp, "source.sh")); os.IsNotExist(err) { - return errors.New("source.sh file could not be found in the temporary build directory"), nil - } - fmt.Println("Running source.sh file...") - if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) { - err = executePackageScripts(filename, rootDir, packageOperationInstall, false) - if err != nil { - return err, nil - } - } else { - err = executePackageScripts(filename, rootDir, packageOperationUpdate, false) - if err != nil { - return err, nil - } - } - bs, err := os.ReadFile(path.Join(temp, "source.sh")) - if err != nil { - return err, nil - } - - if !strings.Contains(string(bs), "package()") { - fmt.Print("This package does not seem to have the required 'package' function\nThe source.sh file may have been created for an older BPM version\nPlease update the source.sh file") - return errors.New("invalid source.sh format"), nil - } - - runScript := ` -cd "$BPM_WORKDIR" - -set -a -source "source.sh" -set +a - -if [[ $(type -t prepare) == function ]]; then - echo "Running prepare() function..." - bash -e -c prepare - if [ $? -ne 0 ]; then - echo "Failed to run prepare() function in source.sh" - exit 1 - fi -fi - -cd "$BPM_SOURCE" -if [[ $(type -t build) == function ]]; then - echo "Running build() function..." - bash -e -c build - if [ $? -ne 0 ]; then - echo "Failed to run build() function in source.sh" - exit 1 - fi -fi - -cd "$BPM_SOURCE" -if [[ $(type -t check) == function ]] && [ -z "$SKIPCHECK" ]; then - echo "Running check() function..." - bash -e -c check - if [ $? -ne 0 ]; then - echo "Failed to run check() function in source.sh" - exit 1 - fi -fi - - -cd "$BPM_SOURCE" -if ! [[ $(type -t package) == function ]]; then - echo "Failed to locate package() function in source.sh" - exit 1 -fi -echo "Running package() function..." -touch "$BPM_WORKDIR"/fakeroot_file -fakeroot -s "$BPM_WORKDIR"/fakeroot_file bash -e -c package -bash -e -c package -if [ $? -ne 0 ]; then - echo "Failed to run package() function in source.sh" -fi -` - err = os.WriteFile(path.Join(temp, "run.sh"), []byte(runScript), 0644) - if err != nil { - return err, nil - } - err = os.Chown(path.Join(temp, "run.sh"), 65534, 65534) - if err != nil { - return err, nil - } - - cmd := exec.Command("/bin/bash", "-e", "run.sh") - cmd.SysProcAttr = &syscall.SysProcAttr{} - cmd.SysProcAttr.Credential = &syscall.Credential{Uid: 65534, Gid: 65534} - cmd.Dir = temp - cmd.Env = os.Environ() - cmd.Env = append(cmd.Env, "USER=nobody") - cmd.Env = append(cmd.Env, "HOME="+temp) - - err = os.Mkdir(path.Join(temp, "source"), 0755) - if err != nil { - return err, nil - } - err = os.Chown(path.Join(temp, "source"), 65534, 65534) - if err != nil { - return err, nil - } - err = os.Mkdir(path.Join(temp, "output"), 0755) - if err != nil { - return err, nil - } - err = os.Chown(path.Join(temp, "output"), 65534, 65534) - if err != nil { - return err, nil - } - cmd.Env = append(cmd.Env, "BPM_WORKDIR="+temp) - cmd.Env = append(cmd.Env, "BPM_SOURCE="+path.Join(temp, "source")) - cmd.Env = append(cmd.Env, "BPM_OUTPUT="+path.Join(temp, "output")) - cmd.Env = append(cmd.Env, "SKIPCHECK="+strconv.FormatBool(skipCheck)) - - cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_ROOT=%s", rootDir)) - cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_NAME=%s", bpmpkg.PkgInfo.Name)) - cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_DESC=%s", bpmpkg.PkgInfo.Description)) - cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_VERSION=%s", bpmpkg.PkgInfo.Version)) - cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_REVISION=%d", bpmpkg.PkgInfo.Revision)) - cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_URL=%s", bpmpkg.PkgInfo.Url)) - cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_ARCH=%s", bpmpkg.PkgInfo.Arch)) - depends := make([]string, len(bpmpkg.PkgInfo.Depends)) - copy(depends, bpmpkg.PkgInfo.Depends) - for i := 0; i < len(depends); i++ { - depends[i] = fmt.Sprintf("\"%s\"", depends[i]) - } - makeDepends := make([]string, len(bpmpkg.PkgInfo.MakeDepends)) - copy(makeDepends, bpmpkg.PkgInfo.MakeDepends) - for i := 0; i < len(makeDepends); i++ { - makeDepends[i] = fmt.Sprintf("\"%s\"", makeDepends[i]) - } - cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_DEPENDS=(%s)", strings.Join(depends, " "))) - cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_MAKE_DEPENDS=(%s)", strings.Join(makeDepends, " "))) - for _, value := range BPMConfig.CompilationEnv { - cmd.Env = append(cmd.Env, value) - } - cmd.Env = append(cmd.Env, "BPM_PKG_TYPE=source") - - if !BPMConfig.SilentCompilation { - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } - err = cmd.Run() - if err != nil { - return err, nil - } - if _, err := os.Stat(path.Join(temp, "output/")); err != nil { - if os.IsNotExist(err) { - return errors.New("output directory not be found at " + path.Join(temp, "output/")), nil - } - return err, nil - } - if dir, _ := os.ReadDir(path.Join(temp, "output/")); len(dir) == 0 { - return errors.New("output directory is empty"), nil - } - fmt.Println("Copying all files...") - err = filepath.WalkDir(path.Join(temp, "/output/"), func(fullpath string, d fs.DirEntry, err error) error { - relFilename, err := filepath.Rel(path.Join(temp, "/output/"), fullpath) - if relFilename == "." { - return nil - } - extractFilename := path.Join(rootDir, relFilename) - if err != nil { - return err - } - if d.Type() == os.ModeDir { - files = append(files, relFilename+"/") - if err := os.Mkdir(extractFilename, 0755); err != nil { - if !os.IsExist(err) { - return err - } - } else { - if verbose { - fmt.Println("Creating Directory: " + extractFilename) - } - } - } else if d.Type().IsRegular() { - if _, err := os.Stat(extractFilename); err == nil { - if slices.Contains(bpmpkg.PkgInfo.Keep, relFilename) { - if verbose { - fmt.Println("Skipping File: " + extractFilename + "(File is configured to be kept during installs/updates)") - } - files = append(files, relFilename) - return nil - } - } - err := os.Remove(extractFilename) - if err != nil && !os.IsNotExist(err) { - return err - } - outFile, err := os.Create(extractFilename) - if verbose { - fmt.Println("Creating File: " + extractFilename) - } - files = append(files, relFilename) - if err != nil { - return err - } - f, err := os.Open(fullpath) - if err != nil { - return err - } - if _, err := io.Copy(outFile, f); err != nil { - return err - } - info, err := os.Stat(fullpath) - if err != nil { - return err - } - if err := os.Chmod(extractFilename, info.Mode()); err != nil { - return err - } - err = outFile.Close() - if err != nil { - return err - } - err = f.Close() - if err != nil { - return err - } - } else if d.Type() == os.ModeSymlink { - link, err := os.Readlink(fullpath) - if err != nil { - return err - } - err = os.Remove(extractFilename) - if err != nil && !os.IsNotExist(err) { - return err - } - if verbose { - fmt.Println("Creating Symlink: "+extractFilename, " -> "+link) - } - files = append(files, relFilename) - err = os.Symlink(link, extractFilename) - if err != nil { - return err - } - } - return nil - }) - if err != nil { - return err, nil - } - if binaryPkgFromSrc { - compiledDir := path.Join(BPMConfig.BinaryOutputDir) - err = os.MkdirAll(compiledDir, 0755) - compiledInfo := PackageInfo{} - compiledInfo = *bpmpkg.PkgInfo - compiledInfo.Type = "binary" - compiledInfo.Arch = GetArch() - err = os.WriteFile(path.Join(temp, "pkg.info"), []byte(CreateInfoFile(&compiledInfo)), 0644) - if err != nil { - return err, nil - } - err = os.Chown(path.Join(temp, "pkg.info"), 65534, 65534) - if err != nil { - return err, nil - } - scripts, err := ReadPackageScripts(filename) - for key, val := range scripts { - err = os.WriteFile(path.Join(temp, key), []byte(val), 0644) - if err != nil { - return err, nil - } - err = os.Chown(path.Join(temp, key), 65534, 65534) - if err != nil { - return err, nil - } - } - sed := fmt.Sprintf("s/output/files/") - fileName := compiledInfo.Name + "-" + compiledInfo.GetFullVersion() + "-" + compiledInfo.Arch + ".bpm" - cmd := exec.Command("/usr/bin/fakeroot", "-i fakeroot_file", "tar", "-czvpf", fileName, "pkg.info", "output/", "--transform", sed) - if !BPMConfig.SilentCompilation { - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } - cmd.SysProcAttr = &syscall.SysProcAttr{} - cmd.SysProcAttr.Credential = &syscall.Credential{Uid: 65534, Gid: 65534} - cmd.Dir = temp - cmd.Env = os.Environ() - fmt.Printf("running command: %s\n", strings.Join(cmd.Args, " ")) - err = cmd.Run() - if err != nil { - return err, nil - } - err = copyFileContents(path.Join(temp, fileName), path.Join(compiledDir, fileName)) - if err != nil { - return err, nil - } - err = os.Chown(path.Join(compiledDir, fileName), 0, 0) - if err != nil { - return err, nil - } - } - if !keepTempDir { - err := os.RemoveAll(temp) - if err != nil { - return err, nil - } - } - if len(files) == 0 { - return errors.New("no output files for source package. Cancelling package installation"), nil - } - - defer file.Close() - return nil, files -} - -func installPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc, skipCheck, keepTempDir bool) error { +func installPackage(filename, rootDir string, verbose, force bool) error { if _, err := os.Stat(filename); os.IsNotExist(err) { return err } @@ -1170,13 +714,7 @@ func installPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc, return err } } else if bpmpkg.PkgInfo.Type == "source" { - if isSplitPackage(filename) { - return errors.New("BPM is unable to install split source packages") - } - err, _ := compilePackage(bpmpkg, filename, rootDir, verbose, binaryPkgFromSrc, skipCheck, keepTempDir) - if err != nil { - return err - } + return errors.New("direct source package compilation in BPM has been temporarily removed and is being reworked on") } else { return errors.New("unknown package type: " + bpmpkg.PkgInfo.Type) } @@ -1649,11 +1187,6 @@ func removePackage(pkg string, verbose bool, rootDir string) error { // Executing post_remove script if _, err := os.Stat(path.Join(pkgDir, "post_remove.sh")); err == nil { cmd := exec.Command("/bin/bash", path.Join(pkgDir, "post_remove.sh")) - if !BPMConfig.SilentCompilation { - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } cmd.Dir = rootDir cmd.Env = os.Environ() cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_ROOT=%s", rootDir)) From 2f8d6a7ea9e2230cfbd5e73e7719eb827b484c4a Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 10 Apr 2025 15:08:27 +0300 Subject: [PATCH 13/23] Add missing dashes in the printHelp function --- src/bpm/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bpm/main.go b/src/bpm/main.go index 45349f3..7265eb9 100644 --- a/src/bpm/main.go +++ b/src/bpm/main.go @@ -541,8 +541,8 @@ func printHelp() { fmt.Println(" -v Show additional information about what BPM is doing") fmt.Println(" -R= lets you define the root path which will be used") fmt.Println(" -y skips the confirmation prompt") - fmt.Println(" -unused removes only packages that aren't required as dependencies by other packages") - fmt.Println(" -cleanup performs a dependency cleanup") + fmt.Println(" --unused removes only packages that aren't required as dependencies by other packages") + fmt.Println(" --cleanup performs a dependency cleanup") fmt.Println("-> bpm cleanup [-R, -v, -y] | remove all unused dependency packages") fmt.Println(" -v Show additional information about what BPM is doing") fmt.Println(" -R= lets you define the root path which will be used") From 46f7d96acf2d90e9fc7aa7e3d3228a778238ae03 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 10 Apr 2025 15:29:44 +0300 Subject: [PATCH 14/23] Update README.md --- README.md | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 637e170..a15ab6c 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,10 @@ BPM is a simple package manager for Linux systems ## Features - Simple to use subcommands -- Can install binary and source packages -- Can be easily installed on practically any system -- No bloat +- Can install binary packages (and source packages in the future) ## Information - -BPM is still in very early development. It should not be installed on any system you use seriously. I recommend trying this out in a VM or container. In addition to this, this is one of the first projects I have made using the go programming language so code quality may not be the best. This project was made to help me learn go and how linux systems work better. It is not meant to replace the big package managers in any way +BPM is still in very early development. Do not install it without knowing what you are doing. I would only recommend using it in a Virtual Machine for testing ## Build from source @@ -21,7 +18,7 @@ BPM is still in very early development. It should not be installed on any system ``` make ``` -- Run the following command to install stormfetch into your system. You may also append a DESTDIR variable at the end of this line if you wish to install in a different location +- Run the following command to install BPM into your system. You may also append a DESTDIR variable at the end of this line if you wish to install in a different location ``` make install PREFIX=/usr SYSCONFDIR=/etc ``` @@ -32,17 +29,30 @@ You are able to install bpm packages by typing the following: ```sh bpm install /path/to/package.bpm ``` -You may also use the -y flag as shown below to bypass the installation confirmation prompt +You can also use the package name directly if using repositories +```sh +bpm install package_name +``` +The -y flag may be used as shown below to bypass the confirmation prompt ```sh bpm install -y /path/to/package.bpm ``` -Flags must strictly be typed before the first package path otherwise they'll be read as package locations themselves +Flags must strictly be typed before the first package path or name, otherwise they'll be read as package locations themselves You can remove an installed package by typing the following ```sh bpm remove package_name ``` -The -y flag applies here as well if you wish to skip the removal confirmation prompt + +To remove all unused dependencies try using the cleanup command +```sh +bpm cleanup +``` + +If using repositories, all packages can be updated using this simple command +```sh +bpm update +``` For information on the rest of the commands simply use the help command or pass in no arguments at all ``` @@ -51,5 +61,6 @@ bpm help ## Package Creation -Package creation is simplified using the bpm-utils package which contains helper scripts for creating and archiving packages. \ -Learn more here: https://gitlab.com/bubble-package-manager/bpm-utils \ No newline at end of file +Package creation is simplified using the bpm-utils package which contains helper scripts for creating and archiving packages + +Learn more here: https://git.enumerated.dev/bubble-package-manager/bpm-utils \ No newline at end of file From fa3f59d8ba9b923bc447f811dde3bbdd4f3c4996 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 10 Apr 2025 15:31:36 +0300 Subject: [PATCH 15/23] Update bpm.conf --- config/bpm.conf | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config/bpm.conf b/config/bpm.conf index 6b92f57..1ca6fb9 100644 --- a/config/bpm.conf +++ b/config/bpm.conf @@ -1,7 +1,3 @@ -compilation_env: [] -silent_compilation: false -compilation_dir: "/var/tmp/" -binary_output_dir: "/var/lib/bpm/compiled/" repositories: - name: example-repository source: https://my-repo.xyz/ From dd41369e057c38fca299ef3e12fb41c326a6564e Mon Sep 17 00:00:00 2001 From: EnumDev Date: Wed, 16 Apr 2025 18:49:54 +0300 Subject: [PATCH 16/23] Fix error when hooks directory does not exist --- src/bpmlib/operations.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bpmlib/operations.go b/src/bpmlib/operations.go index cb56419..f072759 100644 --- a/src/bpmlib/operations.go +++ b/src/bpmlib/operations.go @@ -379,6 +379,11 @@ func (operation *BPMOperation) ShowOperationSummary() { } func (operation *BPMOperation) RunHooks(verbose bool) error { + // Return if hooks directory does not exist + if stat, err := os.Stat(path.Join(operation.RootDir, "var/lib/bpm/hooks")); err != nil || !stat.IsDir() { + return nil + } + // Get directory entries in hooks directory dirEntries, err := os.ReadDir(path.Join(operation.RootDir, "var/lib/bpm/hooks")) if err != nil { From f74372f13b50a80e1b0218f2272fc192df43d20f Mon Sep 17 00:00:00 2001 From: EnumDev Date: Wed, 16 Apr 2025 19:02:55 +0300 Subject: [PATCH 17/23] Add 'ignore_packages' field to default config --- config/bpm.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/config/bpm.conf b/config/bpm.conf index 1ca6fb9..3e8e4ae 100644 --- a/config/bpm.conf +++ b/config/bpm.conf @@ -1,3 +1,4 @@ +ignore_packages: [] repositories: - name: example-repository source: https://my-repo.xyz/ From 78dce34b6424115e6c5f2ba15f43b760d1b5a678 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Wed, 16 Apr 2025 20:08:24 +0300 Subject: [PATCH 18/23] Hide make dependencies when reading info of binary packages --- src/bpmlib/packages.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bpmlib/packages.go b/src/bpmlib/packages.go index 91ebf5a..da57201 100644 --- a/src/bpmlib/packages.go +++ b/src/bpmlib/packages.go @@ -446,7 +446,9 @@ func CreateReadableInfo(showArchitecture, showType, showPackageRelations bool, p } if showPackageRelations { appendArray("Dependencies", pkgInfo.Depends) - appendArray("Make Dependencies", pkgInfo.MakeDepends) + if pkgInfo.Type == "source" { + appendArray("Make Dependencies", pkgInfo.MakeDepends) + } appendArray("Optional dependencies", pkgInfo.OptionalDepends) dependants, err := pkgInfo.GetDependants(rootDir) if err == nil { From b27137da29a63e2c7c062d4dec1fe83da8323342 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Wed, 16 Apr 2025 20:13:22 +0300 Subject: [PATCH 19/23] Allow sync and update subcommands when local database files are corrupt --- src/bpm/main.go | 46 ++++++++++++++++++++++++++++++++++++++ src/bpmlib/config.go | 9 -------- src/bpmlib/repositories.go | 41 ++++++++++++++++++++++++++++----- 3 files changed, 82 insertions(+), 14 deletions(-) diff --git a/src/bpm/main.go b/src/bpm/main.go index 7265eb9..9ff4a10 100644 --- a/src/bpm/main.go +++ b/src/bpm/main.go @@ -102,6 +102,13 @@ func resolveCommand() { fmt.Println("No packages were given") return } + + // Read local databases + err := bpmlib.ReadLocalDatabases() + if err != nil { + log.Fatalf("Error: could not read local databases: %s", err) + } + for n, pkg := range packages { var info *bpmlib.PackageInfo isFile := false @@ -145,6 +152,12 @@ func resolveCommand() { fmt.Println(bpmlib.CreateReadableInfo(true, true, true, info, rootDir)) } case list: + // Read local databases + err := bpmlib.ReadLocalDatabases() + if err != nil { + log.Fatalf("Error: could not read local databases: %s", err) + } + packages, err := bpmlib.GetInstalledPackages(rootDir) if err != nil { log.Fatalf("Error: could not get installed packages: %s", err.Error()) @@ -178,6 +191,13 @@ func resolveCommand() { if len(searchTerms) == 0 { log.Fatalf("Error: no search terms given") } + + // Read local databases + err := bpmlib.ReadLocalDatabases() + if err != nil { + log.Fatalf("Error: could not read local databases: %s", err) + } + for i, term := range searchTerms { nameResults := make([]*bpmlib.PackageInfo, 0) descResults := make([]*bpmlib.PackageInfo, 0) @@ -236,6 +256,12 @@ func resolveCommand() { reinstallMethod = bpmlib.ReinstallMethodNone } + // Read local databases + err := bpmlib.ReadLocalDatabases() + if err != nil { + log.Fatalf("Error: could not read local databases: %s", err) + } + // Create installation operation operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallMethod, !noOptional, force, verbose, subcommandArgs...) if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) { @@ -287,6 +313,14 @@ func resolveCommand() { log.Fatalf("Error: this subcommand needs to be run with superuser permissions") } + // Read local databases if no sync + if nosync { + err := bpmlib.ReadLocalDatabases() + if err != nil { + log.Fatalf("Error: could not read local databases: %s", err) + } + } + // Create update operation operation, err := bpmlib.UpdatePackages(rootDir, !nosync, !noOptional, force, verbose) if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) { @@ -362,6 +396,12 @@ func resolveCommand() { return } + // Read local databases + err := bpmlib.ReadLocalDatabases() + if err != nil { + log.Fatalf("Error: could not read local databases: %s", err) + } + // Create remove operation operation, err := bpmlib.RemovePackages(rootDir, removeUnused, doCleanup, verbose, subcommandArgs...) if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) { @@ -408,6 +448,12 @@ func resolveCommand() { log.Fatalf("Error: this subcommand needs to be run with superuser permissions") } + // Read local databases + err := bpmlib.ReadLocalDatabases() + if err != nil { + log.Fatalf("Error: could not read local databases: %s", err) + } + // Create cleanup operation operation, err := bpmlib.CleanupPackages(rootDir, verbose) if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) { diff --git a/src/bpmlib/config.go b/src/bpmlib/config.go index fdbf246..eee5d57 100644 --- a/src/bpmlib/config.go +++ b/src/bpmlib/config.go @@ -34,14 +34,5 @@ func ReadConfig() (err error) { } } - for _, repo := range BPMConfig.Repositories { - repo.Entries = make(map[string]*RepositoryEntry) - repo.VirtualPackages = make(map[string][]string) - err := repo.ReadLocalDatabase() - if err != nil { - return err - } - } - return nil } diff --git a/src/bpmlib/repositories.go b/src/bpmlib/repositories.go index ffe64b2..c74e440 100644 --- a/src/bpmlib/repositories.go +++ b/src/bpmlib/repositories.go @@ -2,6 +2,7 @@ package bpmlib import ( "errors" + "fmt" "gopkg.in/yaml.v3" "io" "net/http" @@ -83,29 +84,59 @@ func (repo *Repository) ReadLocalDatabase() error { func (repo *Repository) SyncLocalDatabase() error { repoFile := "/var/lib/bpm/repositories/" + repo.Name + ".bpmdb" - err := os.MkdirAll(path.Dir(repoFile), 0755) - if err != nil { - return err - } + // Get URL to database u, err := url.JoinPath(repo.Source, "database.bpmdb") if err != nil { return err } + // Retrieve data from URL resp, err := http.Get(u) if err != nil { return err } defer resp.Body.Close() + // Load data into byte buffer + buffer, err := io.ReadAll(resp.Body) + + // Unmarshal data to ensure it is a valid BPM repository + err = yaml.Unmarshal(buffer, &Repository{}) + if err != nil { + return fmt.Errorf("could not decode repository: %s", err) + } + + // Create parent directories to repository file + err = os.MkdirAll(path.Dir(repoFile), 0755) + if err != nil { + return err + } + + // Create file and save repository data out, err := os.Create(repoFile) if err != nil { return err } defer out.Close() - _, err = io.Copy(out, resp.Body) + _, err = out.Write(buffer) + + return nil +} + +func ReadLocalDatabases() (err error) { + for _, repo := range BPMConfig.Repositories { + // Initialize struct values + repo.Entries = make(map[string]*RepositoryEntry) + repo.VirtualPackages = make(map[string][]string) + + // Read database + err = repo.ReadLocalDatabase() + if err != nil { + return err + } + } return nil } From 0858a4963634206dff95674db9876fb2f4d358ae Mon Sep 17 00:00:00 2001 From: EnumDev Date: Wed, 16 Apr 2025 20:15:46 +0300 Subject: [PATCH 20/23] Add .gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6bbca8c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# IDE Directories +.idea + +# Build directory +build From 877fba8767e1e4f8a582d274b432a6a0ce3368d5 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 17 Apr 2025 13:49:41 +0300 Subject: [PATCH 21/23] Use install command in Makefile, remove compress and run target and add uninstall target --- Makefile | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 851f832..d757063 100644 --- a/Makefile +++ b/Makefile @@ -18,21 +18,16 @@ build: cd src/bpm; $(GO) build -ldflags "-w" -o ../../build/bpm git.enumerated.dev/bubble-package-manager/bpm/src/bpm install: build/bpm config/ - mkdir -p $(DESTDIR)$(BINDIR) - mkdir -p $(DESTDIR)$(SYSCONFDIR) - cp build/bpm $(DESTDIR)$(BINDIR)/bpm - cp config/bpm.conf $(DESTDIR)$(SYSCONFDIR)/bpm.conf + # Create directories + install -dm755 $(DESTDIR)$(BINDIR) + install -dm755 $(DESTDIR)$(SYSCONFDIR) + # Install files + install -Dm755 build/bpm $(DESTDIR)$(BINDIR)/bpm + install -Dm644 config/bpm.conf $(DESTDIR)$(SYSCONFDIR)/bpm.conf -compress: build/bpm config/ - mkdir -p bpm/$(BINDIR) - mkdir -p bpm/$(SYSCONFDIR) - cp build/bpm bpm/$(BINDIR)/bpm - cp config/bpm.conf bpm/$(SYSCONFDIR)/bpm.conf - tar --owner=root --group=root -czf bpm.tar.gz bpm - rm -r bpm - -run: build/bpm - build/bpm +uninstall: + rm $(DESTDIR)$(BINDIR)/bpm + rm $(DESTDIR)$(SYSCONFDIR)/bpm.conf clean: rm -r build/ From d9d85b49435f83ad045f4f0b749bfb2ce882a698 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 17 Apr 2025 13:58:49 +0300 Subject: [PATCH 22/23] Simplify Makefile and make it posix compliant --- Makefile | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index d757063..1b4a678 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,10 @@ -SHELL = /bin/bash +# Installation paths +PREFIX ?= /usr/local +BINDIR ?= $(PREFIX)/bin +SYSCONFDIR := $(PREFIX)/etc -ifeq ($(PREFIX),) - PREFIX := /usr/local -endif -ifeq ($(BINDIR),) - BINDIR := $(PREFIX)/bin -endif -ifeq ($(SYSCONFDIR),) - SYSCONFDIR := $(PREFIX)/etc -endif -ifeq ($(GO),) - GO := $(shell type -a -P go | head -n 1) -endif +# Compilers and tools +GO ?= $(shell which go) build: mkdir -p build From 3a62f23db5b780596afe341d7244687a021498d8 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 17 Apr 2025 14:04:11 +0300 Subject: [PATCH 23/23] Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a15ab6c..231a717 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,13 @@ BPM is still in very early development. Do not install it without knowing what y - Download `go` from your package manager or from the go website - Download `make` from your package manager -- Run the following command to compile the project -``` +- Download `which` from your package manager +- Run the following command to compile the project. You may need to set the `GO` environment variable if your Go installation is not in your PATH +```sh make ``` - Run the following command to install BPM into your system. You may also append a DESTDIR variable at the end of this line if you wish to install in a different location -``` +```sh make install PREFIX=/usr SYSCONFDIR=/etc ``` @@ -55,7 +56,7 @@ bpm update ``` For information on the rest of the commands simply use the help command or pass in no arguments at all -``` +```sh bpm help ```