mirror of
https://github.com/EnumeratedDev/bpm.git
synced 2026-09-25 06:56:12 +00:00
Compare commits
22
Commits
dfdf38bad8
..
0.6.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f23537ba7d
|
||
|
|
6e9f16837c
|
||
|
|
271e87cb77
|
||
|
|
25ccc208d7
|
||
|
|
9c7e20d27d
|
||
|
|
6206fdbf43
|
||
|
|
9e48d97dc8
|
||
|
|
08a4e24889
|
||
|
|
4a32df6335
|
||
|
|
548b2476bd
|
||
|
|
a660039be1
|
||
|
|
44c2678ef9
|
||
|
|
2a7c6ce5d9
|
||
|
|
f98760d1dd
|
||
|
|
2ba78f16db
|
||
|
|
04a71b573b
|
||
|
|
aa229af8df
|
||
|
|
9912b173ff
|
||
|
|
879c832f60
|
||
|
|
2c91a9332b
|
||
|
|
1895fabfb0
|
||
|
|
0dfb66c6c0
|
@@ -7,12 +7,13 @@ SYSCONFDIR := $(PREFIX)/etc
|
|||||||
GO ?= go
|
GO ?= go
|
||||||
|
|
||||||
# Build-time variables
|
# Build-time variables
|
||||||
|
VERSION ?= $(shell git describe --tags --dirty)
|
||||||
ROOT_COMPILATION_UID ?= 65534
|
ROOT_COMPILATION_UID ?= 65534
|
||||||
ROOT_COMPILATION_GID ?= 65534
|
ROOT_COMPILATION_GID ?= 65534
|
||||||
|
|
||||||
build:
|
build:
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd src/bpm; $(GO) build $(GOFLAGS) -ldflags "-w -X 'git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib.rootCompilationUID=$(ROOT_COMPILATION_UID)' -X 'git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib.rootCompilationGID=$(ROOT_COMPILATION_GID)'" -o ../../build/bpm git.enumerated.dev/bubble-package-manager/bpm/src/bpm
|
cd src/bpm; $(GO) build $(GOFLAGS) -ldflags "-w -X 'main.BpmVersion=$(VERSION)' -X 'github.com/EnumeratedDev/bpm/src/bpmlib.rootCompilationUID=$(ROOT_COMPILATION_UID)' -X 'github.com/EnumeratedDev/bpm/src/bpmlib.rootCompilationGID=$(ROOT_COMPILATION_GID)'" -o ../../build/bpm bpm
|
||||||
|
|
||||||
install: build/bpm config/
|
install: build/bpm config/
|
||||||
# Create directory
|
# Create directory
|
||||||
|
|||||||
+3
-3
@@ -1,14 +1,14 @@
|
|||||||
module git.enumerated.dev/bubble-package-manager/bpm/src/bpm
|
module bpm
|
||||||
|
|
||||||
go 1.24.0
|
go 1.24.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib v0.5.0
|
github.com/EnumeratedDev/bpm/src/bpmlib v0.0.0
|
||||||
github.com/lithammer/fuzzysearch v1.1.8
|
github.com/lithammer/fuzzysearch v1.1.8
|
||||||
github.com/spf13/pflag v1.0.10
|
github.com/spf13/pflag v1.0.10
|
||||||
)
|
)
|
||||||
|
|
||||||
replace git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib => ../bpmlib
|
replace github.com/EnumeratedDev/bpm/src/bpmlib => ../bpmlib
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/drone/envsubst v1.0.3 // indirect
|
github.com/drone/envsubst v1.0.3 // indirect
|
||||||
|
|||||||
+117
-25
@@ -14,7 +14,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib"
|
"github.com/EnumeratedDev/bpm/src/bpmlib"
|
||||||
|
|
||||||
"github.com/lithammer/fuzzysearch/fuzzy"
|
"github.com/lithammer/fuzzysearch/fuzzy"
|
||||||
flag "github.com/spf13/pflag"
|
flag "github.com/spf13/pflag"
|
||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
/* A simple-to-use package manager */
|
/* A simple-to-use package manager */
|
||||||
/* ------------------------------------------------------- */
|
/* ------------------------------------------------------- */
|
||||||
|
|
||||||
var bpmVer = "0.6.1"
|
var BpmVersion = "dev"
|
||||||
|
|
||||||
var currentFlagSet *flag.FlagSet
|
var currentFlagSet *flag.FlagSet
|
||||||
|
|
||||||
@@ -37,16 +37,18 @@ func main() {
|
|||||||
log.Fatalf("Error: could not read BPM config: %s", err)
|
log.Fatalf("Error: could not read BPM config: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute subcommand
|
// Show usage if no arguments specified
|
||||||
subcommand := "help"
|
if len(os.Args) == 1 {
|
||||||
if len(os.Args) >= 2 {
|
printUsage()
|
||||||
subcommand = os.Args[1]
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subcommand := os.Args[1]
|
||||||
|
|
||||||
switch subcommand {
|
switch subcommand {
|
||||||
case "v", "version":
|
case "v", "version":
|
||||||
fmt.Println("Bubble Package Manager (BPM)")
|
fmt.Println("Bubble Package Manager (BPM)")
|
||||||
fmt.Println("Version: " + bpmVer)
|
fmt.Println("Version: " + BpmVersion)
|
||||||
case "q", "query":
|
case "q", "query":
|
||||||
// Setup flags and help
|
// Setup flags and help
|
||||||
currentFlagSet = flag.NewFlagSet("query", flag.ExitOnError)
|
currentFlagSet = flag.NewFlagSet("query", flag.ExitOnError)
|
||||||
@@ -136,6 +138,7 @@ func main() {
|
|||||||
currentFlagSet.BoolP("force", "f", false, "Bypass warnings during package update")
|
currentFlagSet.BoolP("force", "f", false, "Bypass warnings during package update")
|
||||||
currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts")
|
currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts")
|
||||||
currentFlagSet.BoolP("no-sync", "n", false, "Do not sync databases")
|
currentFlagSet.BoolP("no-sync", "n", false, "Do not sync databases")
|
||||||
|
currentFlagSet.Bool("allow-downgrades", false, "Allow package downgrades")
|
||||||
currentFlagSet.BoolP("optional", "o", false, "Install all optional dependencies")
|
currentFlagSet.BoolP("optional", "o", false, "Install all optional dependencies")
|
||||||
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Update installed packages", os.Args[2:])
|
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Update installed packages", os.Args[2:])
|
||||||
|
|
||||||
@@ -162,8 +165,14 @@ func main() {
|
|||||||
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Compile source packages and convert them to binary ones", os.Args[2:])
|
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Compile source packages and convert them to binary ones", os.Args[2:])
|
||||||
|
|
||||||
compilePackage()
|
compilePackage()
|
||||||
|
case "p", "vercmp":
|
||||||
|
currentFlagSet = flag.NewFlagSet("compile", flag.ExitOnError)
|
||||||
|
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Compare two version numbers", os.Args[2:])
|
||||||
|
|
||||||
|
compareVersions()
|
||||||
default:
|
default:
|
||||||
listSubcommands()
|
printUsage()
|
||||||
|
exitCode = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if exitCode != 0 {
|
if exitCode != 0 {
|
||||||
@@ -247,7 +256,14 @@ func showPackageInfo() {
|
|||||||
}
|
}
|
||||||
fmt.Println("File: " + abs)
|
fmt.Println("File: " + abs)
|
||||||
}
|
}
|
||||||
fmt.Println(bpmpkg.CreateReadableInfo(rootDir, showHumanReadableSize))
|
fmt.Println(bpmpkg.PkgInfo.CreateReadableInfo(rootDir))
|
||||||
|
if bpmpkg.PkgInfo.Type == "binary" {
|
||||||
|
if !showHumanReadableSize {
|
||||||
|
fmt.Printf("Installed size: %d\n", bpmpkg.GetInstalledSize())
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Installed size: %s\n", bpmlib.BytesToHumanReadable(bpmpkg.GetInstalledSize()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,9 +301,21 @@ func showPackageList() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
installedPackages := make([]*bpmlib.BPMPackage, len(installedPackageNames))
|
installedPackages := make([]struct {
|
||||||
|
pkgInfo bpmlib.PackageInfo
|
||||||
|
installedSize int64
|
||||||
|
}, len(installedPackageNames))
|
||||||
for i, pkgName := range installedPackageNames {
|
for i, pkgName := range installedPackageNames {
|
||||||
installedPackages[i] = bpmlib.GetPackage(pkgName, rootDir)
|
pkgInfo := *bpmlib.GetPackageInfo(pkgName, rootDir)
|
||||||
|
installedSize := bpmlib.GetPackage(pkgName, rootDir).GetInstalledSize()
|
||||||
|
|
||||||
|
installedPackages[i] = struct {
|
||||||
|
pkgInfo bpmlib.PackageInfo
|
||||||
|
installedSize int64
|
||||||
|
}{
|
||||||
|
pkgInfo: pkgInfo,
|
||||||
|
installedSize: installedSize,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
databaseEntries := make([]*bpmlib.BPMDatabaseEntry, 0)
|
databaseEntries := make([]*bpmlib.BPMDatabaseEntry, 0)
|
||||||
@@ -298,8 +326,11 @@ func showPackageList() {
|
|||||||
switch sortPackages {
|
switch sortPackages {
|
||||||
case "", "name":
|
case "", "name":
|
||||||
case "size":
|
case "size":
|
||||||
slices.SortFunc(installedPackages, func(a, b *bpmlib.BPMPackage) int {
|
slices.SortFunc(installedPackages, func(a, b struct {
|
||||||
return int(b.GetInstalledSize() - a.GetInstalledSize())
|
pkgInfo bpmlib.PackageInfo
|
||||||
|
installedSize int64
|
||||||
|
}) int {
|
||||||
|
return int(b.installedSize - a.installedSize)
|
||||||
})
|
})
|
||||||
slices.SortFunc(databaseEntries, func(a, b *bpmlib.BPMDatabaseEntry) int {
|
slices.SortFunc(databaseEntries, func(a, b *bpmlib.BPMDatabaseEntry) int {
|
||||||
return int(b.InstalledSize - a.InstalledSize)
|
return int(b.InstalledSize - a.InstalledSize)
|
||||||
@@ -328,7 +359,7 @@ func showPackageList() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, pkg := range installedPackages {
|
for _, pkg := range installedPackages {
|
||||||
installationReason := bpmlib.GetInstallationReason(pkg.PkgInfo.Name, rootDir)
|
installationReason := bpmlib.GetInstallationReason(pkg.pkgInfo.Name, rootDir)
|
||||||
if installationReason == bpmlib.InstallationReasonManual && !showManual {
|
if installationReason == bpmlib.InstallationReasonManual && !showManual {
|
||||||
continue
|
continue
|
||||||
} else if installationReason == bpmlib.InstallationReasonDependency && !showDepends {
|
} else if installationReason == bpmlib.InstallationReasonDependency && !showDepends {
|
||||||
@@ -339,7 +370,7 @@ func showPackageList() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(pkg.PkgInfo.Name)
|
fmt.Println(pkg.pkgInfo.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -359,13 +390,8 @@ func showPackageList() {
|
|||||||
fmt.Println("No packages have been installed")
|
fmt.Println("No packages have been installed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for n, bpmpkg := range installedPackages {
|
for n, pkg := range installedPackages {
|
||||||
if bpmpkg == nil {
|
installationReason := bpmlib.GetInstallationReason(pkg.pkgInfo.Name, rootDir)
|
||||||
fmt.Printf("Package (%s) could not be found\n", installedPackageNames[n])
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
installationReason := bpmlib.GetInstallationReason(bpmpkg.PkgInfo.Name, rootDir)
|
|
||||||
if installationReason == bpmlib.InstallationReasonManual && !showManual {
|
if installationReason == bpmlib.InstallationReasonManual && !showManual {
|
||||||
continue
|
continue
|
||||||
} else if installationReason == bpmlib.InstallationReasonDependency && !showDepends {
|
} else if installationReason == bpmlib.InstallationReasonDependency && !showDepends {
|
||||||
@@ -379,7 +405,15 @@ func showPackageList() {
|
|||||||
if n != 0 {
|
if n != 0 {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
fmt.Println(bpmpkg.CreateReadableInfo(rootDir, showHumanReadableSize))
|
|
||||||
|
fmt.Println(pkg.pkgInfo.CreateReadableInfo(rootDir))
|
||||||
|
if pkg.pkgInfo.Type == "binary" {
|
||||||
|
if !showHumanReadableSize {
|
||||||
|
fmt.Printf("Installed size: %d\n", pkg.installedSize)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Installed size: %s\n", bpmlib.BytesToHumanReadable(pkg.installedSize))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -570,6 +604,9 @@ func installPackages() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get optional dependencies
|
||||||
|
optionalDepends := operation.GetOptionalDependencies()
|
||||||
|
|
||||||
// Execute operation
|
// Execute operation
|
||||||
err = operation.Execute(verbose, force)
|
err = operation.Execute(verbose, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -586,6 +623,18 @@ func installPackages() {
|
|||||||
exitCode = 1
|
exitCode = 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show optional dependencies
|
||||||
|
if !installOptional && len(optionalDepends) != 0 {
|
||||||
|
// List optional dependencies
|
||||||
|
fmt.Println("The following optional dependenices have been discovered:")
|
||||||
|
for dependant, depends := range optionalDepends {
|
||||||
|
fmt.Printf("%s: \n", dependant)
|
||||||
|
for _, depend := range depends {
|
||||||
|
fmt.Printf(" - %s\n", depend)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removePackages() {
|
func removePackages() {
|
||||||
@@ -847,6 +896,7 @@ func updatePackages() {
|
|||||||
force, _ := currentFlagSet.GetBool("force")
|
force, _ := currentFlagSet.GetBool("force")
|
||||||
yesAll, _ := currentFlagSet.GetBool("yes")
|
yesAll, _ := currentFlagSet.GetBool("yes")
|
||||||
noSync, _ := currentFlagSet.GetBool("no-sync")
|
noSync, _ := currentFlagSet.GetBool("no-sync")
|
||||||
|
allowDowngrades, _ := currentFlagSet.GetBool("allow-downgrades")
|
||||||
installOptional, _ := currentFlagSet.GetBool("optional")
|
installOptional, _ := currentFlagSet.GetBool("optional")
|
||||||
|
|
||||||
// Check for required permissions
|
// Check for required permissions
|
||||||
@@ -875,14 +925,25 @@ func updatePackages() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Confirmation Prompt
|
||||||
|
if !noSync && !yesAll {
|
||||||
|
if !showConfirmationPrompt("Do you wish to sync all databases?", false) {
|
||||||
|
fmt.Println("Cancelling package update...")
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create update operation
|
// Create update operation
|
||||||
operation, err := bpmlib.UpdatePackages(rootDir, !noSync, installOptional, force, verbose)
|
operation, err := bpmlib.UpdatePackages(rootDir, !noSync, allowDowngrades, installOptional, force, verbose)
|
||||||
if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) {
|
if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) {
|
||||||
log.Printf("Error: %s", err)
|
log.Printf("Error: %s", err)
|
||||||
exitCode = 1
|
exitCode = 1
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Printf("Error: could not setup operation: %s\n", err)
|
log.Printf("Error: could not setup operation: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exit if operation contains no actions
|
// Exit if operation contains no actions
|
||||||
@@ -935,6 +996,9 @@ func updatePackages() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get optional dependencies
|
||||||
|
optionalDepends := operation.GetOptionalDependencies()
|
||||||
|
|
||||||
// Execute operation
|
// Execute operation
|
||||||
err = operation.Execute(verbose, force)
|
err = operation.Execute(verbose, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -951,6 +1015,18 @@ func updatePackages() {
|
|||||||
exitCode = 1
|
exitCode = 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show optional dependencies
|
||||||
|
if !installOptional && len(optionalDepends) != 0 {
|
||||||
|
// List optional dependencies
|
||||||
|
fmt.Println("The following optional dependenices have been discovered:")
|
||||||
|
for dependant, depends := range optionalDepends {
|
||||||
|
fmt.Printf("%s: \n", dependant)
|
||||||
|
for _, depend := range depends {
|
||||||
|
fmt.Printf(" - %s\n", depend)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFileOwner() {
|
func getFileOwner() {
|
||||||
@@ -1027,6 +1103,8 @@ func getFileOwner() {
|
|||||||
// Print packages
|
// Print packages
|
||||||
if len(pkgList) == 0 {
|
if len(pkgList) == 0 {
|
||||||
fmt.Printf("%s (%s) is not owned by any packages!\n", absPath, pathType)
|
fmt.Printf("%s (%s) is not owned by any packages!\n", absPath, pathType)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("%s (%s) is owned by the following packages:\n", absPath, pathType)
|
fmt.Printf("%s (%s) is owned by the following packages:\n", absPath, pathType)
|
||||||
for _, pkg := range pkgList {
|
for _, pkg := range pkgList {
|
||||||
@@ -1268,7 +1346,20 @@ func compilePackage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func listSubcommands() {
|
func compareVersions() {
|
||||||
|
if currentFlagSet.NArg() < 2 {
|
||||||
|
log.Printf("Error: vercmp subcommand requires 2 arguments")
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v1 := currentFlagSet.Arg(0)
|
||||||
|
v2 := currentFlagSet.Arg(1)
|
||||||
|
|
||||||
|
fmt.Println(bpmlib.CompareVersions(v1, v2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func printUsage() {
|
||||||
fmt.Printf("Usage: %s <subcommand> [options]\n", os.Args[0])
|
fmt.Printf("Usage: %s <subcommand> [options]\n", os.Args[0])
|
||||||
fmt.Println("Description: Manage system packages")
|
fmt.Println("Description: Manage system packages")
|
||||||
fmt.Println("Subcommands:")
|
fmt.Println("Subcommands:")
|
||||||
@@ -1282,6 +1373,7 @@ func listSubcommands() {
|
|||||||
fmt.Println(" u, update Update installed packages")
|
fmt.Println(" u, update Update installed packages")
|
||||||
fmt.Println(" o, owner Show what packages own the specified paths")
|
fmt.Println(" o, owner Show what packages own the specified paths")
|
||||||
fmt.Println(" c, compile Compile source packages and convert them to binary ones")
|
fmt.Println(" c, compile Compile source packages and convert them to binary ones")
|
||||||
|
fmt.Println(" p, vercmp Compare package version numbers")
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupFlagsAndHelp(flagset *flag.FlagSet, usage, desc string, args []string) {
|
func setupFlagsAndHelp(flagset *flag.FlagSet, usage, desc string, args []string) {
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks, k
|
|||||||
env = append(env, "BPM_PKG_NAME="+bpmpkg.PkgInfo.Name)
|
env = append(env, "BPM_PKG_NAME="+bpmpkg.PkgInfo.Name)
|
||||||
env = append(env, "BPM_PKG_VERSION="+bpmpkg.PkgInfo.Version)
|
env = append(env, "BPM_PKG_VERSION="+bpmpkg.PkgInfo.Version)
|
||||||
env = append(env, "BPM_PKG_REVISION="+strconv.Itoa(bpmpkg.PkgInfo.Revision))
|
env = append(env, "BPM_PKG_REVISION="+strconv.Itoa(bpmpkg.PkgInfo.Revision))
|
||||||
|
env = append(env, "BPM_PKG_URL="+bpmpkg.PkgInfo.Url)
|
||||||
env = append(env, "BPM_PKG_ARCH="+bpmpkg.PkgInfo.OutputArch)
|
env = append(env, "BPM_PKG_ARCH="+bpmpkg.PkgInfo.OutputArch)
|
||||||
env = append(env, CompilationBPMConfig.CompilationEnvironment...)
|
env = append(env, CompilationBPMConfig.CompilationEnvironment...)
|
||||||
|
|
||||||
@@ -261,6 +262,17 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks, k
|
|||||||
fmt.Printf("Stripped %s (%s)\n", path, mimetype)
|
fmt.Printf("Stripped %s (%s)\n", path, mimetype)
|
||||||
}
|
}
|
||||||
} else if strings.HasPrefix(mimetype, "application/x-pie-executable") || strings.HasPrefix(mimetype, "application/x-sharedlib") {
|
} else if strings.HasPrefix(mimetype, "application/x-pie-executable") || strings.HasPrefix(mimetype, "application/x-sharedlib") {
|
||||||
|
cmd = exec.Command("file", "-b", path)
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
output, err = cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Skip files that use ELF as a container format
|
||||||
|
if strings.Contains(string(output), "no machine") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
cmd := exec.Command("strip", "--strip-unneeded", path)
|
cmd := exec.Command("strip", "--strip-unneeded", path)
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
@@ -423,10 +435,12 @@ func downloadPackageFiles(pkgInfo *PackageInfo, tempDirectory string, verbose bo
|
|||||||
// Replace variables
|
// Replace variables
|
||||||
replaceVars := func(s string) string {
|
replaceVars := func(s string) string {
|
||||||
switch s {
|
switch s {
|
||||||
case "BPM_PKG_VERSION":
|
|
||||||
return pkgInfo.Version
|
|
||||||
case "BPM_PKG_NAME":
|
case "BPM_PKG_NAME":
|
||||||
return pkgInfo.Name
|
return pkgInfo.Name
|
||||||
|
case "BPM_PKG_VERSION":
|
||||||
|
return pkgInfo.Version
|
||||||
|
case "BPM_PKG_URL":
|
||||||
|
return pkgInfo.Url
|
||||||
case "BPM_SOURCE":
|
case "BPM_SOURCE":
|
||||||
return path.Join(tempDirectory, "source/")
|
return path.Join(tempDirectory, "source/")
|
||||||
default:
|
default:
|
||||||
@@ -546,10 +560,12 @@ func downloadPackageFiles(pkgInfo *PackageInfo, tempDirectory string, verbose bo
|
|||||||
gitBranch := download.GitBranch
|
gitBranch := download.GitBranch
|
||||||
gitBranch, err := envsubst.Eval(gitBranch, func(s string) string {
|
gitBranch, err := envsubst.Eval(gitBranch, func(s string) string {
|
||||||
switch s {
|
switch s {
|
||||||
case "BPM_PKG_VERSION":
|
|
||||||
return pkgInfo.Version
|
|
||||||
case "BPM_PKG_NAME":
|
case "BPM_PKG_NAME":
|
||||||
return pkgInfo.Name
|
return pkgInfo.Name
|
||||||
|
case "BPM_PKG_VERSION":
|
||||||
|
return pkgInfo.Version
|
||||||
|
case "BPM_PKG_URL":
|
||||||
|
return pkgInfo.Url
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-13
@@ -28,8 +28,8 @@ type BPMDatabase struct {
|
|||||||
type BPMDatabaseEntry struct {
|
type BPMDatabaseEntry struct {
|
||||||
Info *PackageInfo `yaml:"info"`
|
Info *PackageInfo `yaml:"info"`
|
||||||
Filepath string `yaml:"filepath"`
|
Filepath string `yaml:"filepath"`
|
||||||
DownloadSize uint64 `yaml:"download_size"`
|
DownloadSize int64 `yaml:"download_size"`
|
||||||
InstalledSize uint64 `yaml:"installed_size"`
|
InstalledSize int64 `yaml:"installed_size"`
|
||||||
Database *BPMDatabase
|
Database *BPMDatabase
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,11 +63,12 @@ func (db *configDatabase) ReadLocalDatabase() error {
|
|||||||
database.Name = db.Name
|
database.Name = db.Name
|
||||||
database.Source = db.Source
|
database.Source = db.Source
|
||||||
|
|
||||||
entriesToRemove := make([]string, 0)
|
|
||||||
for entryName, entry := range database.Entries {
|
for entryName, entry := range database.Entries {
|
||||||
entry.Database = database
|
entry.Database = database
|
||||||
|
|
||||||
if entry.Info.IsSplitPackage() {
|
if entry.Info.IsSplitPackage() {
|
||||||
|
delete(database.Entries, entryName)
|
||||||
|
|
||||||
// Handle split packages
|
// Handle split packages
|
||||||
for _, splitPkg := range entry.Info.SplitPackages {
|
for _, splitPkg := range entry.Info.SplitPackages {
|
||||||
// Turn split package into json data
|
// Turn split package into json data
|
||||||
@@ -106,9 +107,6 @@ func (db *configDatabase) ReadLocalDatabase() error {
|
|||||||
for _, p := range splitPkg.Provides {
|
for _, p := range splitPkg.Provides {
|
||||||
database.VirtualPackages[p] = append(database.VirtualPackages[p], splitPkg.Name)
|
database.VirtualPackages[p] = append(database.VirtualPackages[p], splitPkg.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add current entry to list for removal
|
|
||||||
entriesToRemove = append(entriesToRemove, entryName)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Add virtual packages to database
|
// Add virtual packages to database
|
||||||
@@ -118,11 +116,6 @@ func (db *configDatabase) ReadLocalDatabase() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove entries
|
|
||||||
for _, entryName := range entriesToRemove {
|
|
||||||
delete(database.Entries, entryName)
|
|
||||||
}
|
|
||||||
|
|
||||||
BPMDatabases[db.Name] = database
|
BPMDatabases[db.Name] = database
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -400,10 +393,10 @@ func (entry *BPMDatabaseEntry) CreateReadableInfo(rootDir string, humanReadableS
|
|||||||
ret = append(ret, "Installation Reason: "+installationReasonString)
|
ret = append(ret, "Installation Reason: "+installationReasonString)
|
||||||
}
|
}
|
||||||
if entry.Info.Type == "binary" {
|
if entry.Info.Type == "binary" {
|
||||||
installedSize := int64(entry.InstalledSize)
|
installedSize := entry.InstalledSize
|
||||||
var installedSizeStr string
|
var installedSizeStr string
|
||||||
if humanReadableSize {
|
if humanReadableSize {
|
||||||
installedSizeStr = bytesToHumanReadable(installedSize)
|
installedSizeStr = BytesToHumanReadable(installedSize)
|
||||||
} else {
|
} else {
|
||||||
installedSizeStr = strconv.FormatInt(installedSize, 10)
|
installedSizeStr = strconv.FormatInt(installedSize, 10)
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-28
@@ -177,39 +177,33 @@ func resolvePackageDependenciesFromDatabase(resolved *[]pkgInstallationReason, u
|
|||||||
|
|
||||||
func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string) (dependants []string) {
|
func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string) (dependants []string) {
|
||||||
// Get installed package names
|
// Get installed package names
|
||||||
pkgs, err := GetInstalledPackages(rootDir)
|
pkgs, ok := localPackageInformation[rootDir]
|
||||||
if err != nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through all installed packages
|
// Loop through all installed packages
|
||||||
for _, installedPkgName := range pkgs {
|
for _, installedPkg := range pkgs {
|
||||||
// Get installed BPM package
|
|
||||||
installedPkg := GetPackage(installedPkgName, rootDir)
|
|
||||||
if installedPkg == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip iteration if comparing the same packages
|
// Skip iteration if comparing the same packages
|
||||||
if installedPkg.PkgInfo.Name == pkgInfo.Name {
|
if installedPkg.Name == pkgInfo.Name {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add installed package to list if its dependencies include pkgName
|
// Add installed package to list if its dependencies include pkgName
|
||||||
if slices.ContainsFunc(installedPkg.PkgInfo.Depends, func(n string) bool {
|
if slices.ContainsFunc(installedPkg.Depends, func(n string) bool {
|
||||||
return n == pkgInfo.Name
|
return n == pkgInfo.Name
|
||||||
}) {
|
}) {
|
||||||
dependants = append(dependants, installedPkgName)
|
dependants = append(dependants, installedPkg.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through each virtual package
|
// Loop through each virtual package
|
||||||
for _, vpkg := range pkgInfo.Provides {
|
for _, vpkg := range pkgInfo.Provides {
|
||||||
// Add installed package to list if its dependencies contain a provided virtual package
|
// Add installed package to list if its dependencies contain a provided virtual package
|
||||||
if slices.ContainsFunc(installedPkg.PkgInfo.Depends, func(n string) bool {
|
if slices.ContainsFunc(installedPkg.Depends, func(n string) bool {
|
||||||
return n == vpkg
|
return n == vpkg
|
||||||
}) {
|
}) {
|
||||||
dependants = append(dependants, installedPkgName)
|
dependants = append(dependants, installedPkg.Name)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,39 +214,33 @@ func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string) (dependants []s
|
|||||||
|
|
||||||
func (pkgInfo *PackageInfo) GetPackageOptionalDependants(rootDir string) (dependants []string) {
|
func (pkgInfo *PackageInfo) GetPackageOptionalDependants(rootDir string) (dependants []string) {
|
||||||
// Get installed package names
|
// Get installed package names
|
||||||
pkgs, err := GetInstalledPackages(rootDir)
|
pkgs, ok := localPackageInformation[rootDir]
|
||||||
if err != nil {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through all installed packages
|
// Loop through all installed packages
|
||||||
for _, installedPkgName := range pkgs {
|
for _, installedPkg := range pkgs {
|
||||||
// Get installed BPM package
|
|
||||||
installedPkg := GetPackage(installedPkgName, rootDir)
|
|
||||||
if installedPkg == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip iteration if comparing the same packages
|
// Skip iteration if comparing the same packages
|
||||||
if installedPkg.PkgInfo.Name == pkgInfo.Name {
|
if installedPkg.Name == pkgInfo.Name {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add installed package to list if its optional dependencies include pkgName
|
// Add installed package to list if its optional dependencies include pkgName
|
||||||
if slices.ContainsFunc(installedPkg.PkgInfo.OptionalDepends, func(n string) bool {
|
if slices.ContainsFunc(installedPkg.OptionalDepends, func(n string) bool {
|
||||||
return n == pkgInfo.Name
|
return n == pkgInfo.Name
|
||||||
}) {
|
}) {
|
||||||
dependants = append(dependants, installedPkgName)
|
dependants = append(dependants, installedPkg.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through each virtual package
|
// Loop through each virtual package
|
||||||
for _, vpkg := range pkgInfo.Provides {
|
for _, vpkg := range pkgInfo.Provides {
|
||||||
// Add installed package to list if its optional dependencies contain a provided virtual package
|
// Add installed package to list if its optional dependencies contain a provided virtual package
|
||||||
if slices.ContainsFunc(installedPkg.PkgInfo.OptionalDepends, func(n string) bool {
|
if slices.ContainsFunc(installedPkg.OptionalDepends, func(n string) bool {
|
||||||
return n == vpkg
|
return n == vpkg
|
||||||
}) {
|
}) {
|
||||||
dependants = append(dependants, installedPkgName)
|
dependants = append(dependants, installedPkg.Name)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-9
@@ -21,7 +21,6 @@ const (
|
|||||||
|
|
||||||
// InstallPackages installs the specified packages into the given root directory by fetching them from databases or directly from local bpm archives
|
// InstallPackages installs the specified packages into the given root directory by fetching them from databases or directly from local bpm archives
|
||||||
func InstallPackages(rootDir string, forceInstallationReason InstallationReason, reinstallMethod ReinstallMethod, installOptionalDependencies, forceInstallation, verbose bool, packages ...string) (operation *BPMOperation, err error) {
|
func InstallPackages(rootDir string, forceInstallationReason InstallationReason, reinstallMethod ReinstallMethod, installOptionalDependencies, forceInstallation, verbose bool, packages ...string) (operation *BPMOperation, err error) {
|
||||||
|
|
||||||
// Setup operation struct
|
// Setup operation struct
|
||||||
operation = &BPMOperation{
|
operation = &BPMOperation{
|
||||||
Actions: make([]OperationAction, 0),
|
Actions: make([]OperationAction, 0),
|
||||||
@@ -31,6 +30,9 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
compiledPackages: make(map[string]string),
|
compiledPackages: make(map[string]string),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove duplicates from packages
|
||||||
|
packages = removeDuplicates(packages)
|
||||||
|
|
||||||
// Resolve packages
|
// Resolve packages
|
||||||
pkgsNotFound := make([]string, 0)
|
pkgsNotFound := make([]string, 0)
|
||||||
for _, pkg := range packages {
|
for _, pkg := range packages {
|
||||||
@@ -145,12 +147,9 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
operation.ReplaceObsoletePackages()
|
operation.ReplaceObsoletePackages()
|
||||||
|
|
||||||
// Check for conflicts
|
// Check for conflicts
|
||||||
conflicts, err := operation.CheckForConflicts()
|
conflicts := operation.CheckForConflicts()
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not complete package conflict check: %s", err)
|
|
||||||
}
|
|
||||||
if len(conflicts) > 0 {
|
if len(conflicts) > 0 {
|
||||||
err = nil
|
err = fmt.Errorf("conflicts detected")
|
||||||
for pkg, conflict := range conflicts {
|
for pkg, conflict := range conflicts {
|
||||||
err = errors.Join(err, PackageConflictErr{pkg, conflict})
|
err = errors.Join(err, PackageConflictErr{pkg, conflict})
|
||||||
}
|
}
|
||||||
@@ -196,6 +195,9 @@ func RemovePackages(rootDir string, force, cleanupDependencies bool, packages ..
|
|||||||
compiledPackages: make(map[string]string),
|
compiledPackages: make(map[string]string),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove duplicates from packages
|
||||||
|
packages = removeDuplicates(packages)
|
||||||
|
|
||||||
// Search for packages
|
// Search for packages
|
||||||
for _, pkg := range packages {
|
for _, pkg := range packages {
|
||||||
bpmpkg := GetPackage(pkg, rootDir)
|
bpmpkg := GetPackage(pkg, rootDir)
|
||||||
@@ -363,7 +365,7 @@ func CleanupCache(rootDir string, cleanupCompilationFiles, cleanupCompiledPackag
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePackages fetches the newest versions of all installed packages from
|
// UpdatePackages fetches the newest versions of all installed packages from
|
||||||
func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependencies, forceInstallation, verbose bool) (operation *BPMOperation, err error) {
|
func UpdatePackages(rootDir string, syncDatabase bool, allowDowngrades bool, installOptionalDependencies, forceInstallation, verbose bool) (operation *BPMOperation, err error) {
|
||||||
// Sync databases
|
// Sync databases
|
||||||
if syncDatabase {
|
if syncDatabase {
|
||||||
err := SyncDatabase(verbose)
|
err := SyncDatabase(verbose)
|
||||||
@@ -416,8 +418,8 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci
|
|||||||
if installedInfo == nil {
|
if installedInfo == nil {
|
||||||
return nil, fmt.Errorf("could not get package info for package (%s)", pkg)
|
return nil, fmt.Errorf("could not get package info for package (%s)", pkg)
|
||||||
} else {
|
} else {
|
||||||
comparison := ComparePackageVersions(*entry.Info, *installedInfo)
|
comparison := CompareVersions(entry.Info.GetFullVersion(), installedInfo.GetFullVersion())
|
||||||
if comparison > 0 {
|
if (!allowDowngrades && comparison > 0) || (allowDowngrades && comparison != 0) {
|
||||||
operation.AppendAction(&FetchPackageAction{
|
operation.AppendAction(&FetchPackageAction{
|
||||||
InstallationReason: GetInstallationReason(pkg, rootDir),
|
InstallationReason: GetInstallationReason(pkg, rootDir),
|
||||||
DatabaseEntry: entry,
|
DatabaseEntry: entry,
|
||||||
@@ -441,6 +443,21 @@ func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependenci
|
|||||||
|
|
||||||
// Replace obsolete packages
|
// Replace obsolete packages
|
||||||
operation.ReplaceObsoletePackages()
|
operation.ReplaceObsoletePackages()
|
||||||
|
|
||||||
|
// Check for conflicts
|
||||||
|
conflicts := operation.CheckForConflicts()
|
||||||
|
if len(conflicts) > 0 {
|
||||||
|
err = fmt.Errorf("conflicts detected")
|
||||||
|
for pkg, conflict := range conflicts {
|
||||||
|
err = errors.Join(err, PackageConflictErr{pkg, conflict})
|
||||||
|
}
|
||||||
|
if !forceInstallation {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
log.Printf("Warning: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return operation, nil
|
return operation, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
module git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib
|
module github.com/EnumeratedDev/bpm/src/bpmlib
|
||||||
|
|
||||||
go 1.24.0
|
go 1.24.0
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var localPackageInformation map[string]map[string]*BPMPackage = make(map[string]map[string]*BPMPackage)
|
var localPackageInformation map[string]map[string]*PackageInfo = make(map[string]map[string]*PackageInfo)
|
||||||
|
|
||||||
func initializeLocalPackageInformation(rootDir string) (err error) {
|
func initializeLocalPackageInformation(rootDir string) (err error) {
|
||||||
// Return if information is already initialized
|
// Return if information is already initialized
|
||||||
@@ -17,7 +17,7 @@ func initializeLocalPackageInformation(rootDir string) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
tempPackageInformation := make(map[string]*BPMPackage)
|
tempPackageInformation := make(map[string]*PackageInfo)
|
||||||
|
|
||||||
// Get path to installed package information directory
|
// Get path to installed package information directory
|
||||||
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
@@ -25,7 +25,7 @@ func initializeLocalPackageInformation(rootDir string) (err error) {
|
|||||||
// Get directory content
|
// Get directory content
|
||||||
items, err := os.ReadDir(installedDir)
|
items, err := os.ReadDir(installedDir)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
localPackageInformation[rootDir] = make(map[string]*BPMPackage)
|
localPackageInformation[rootDir] = make(map[string]*PackageInfo)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -49,14 +49,8 @@ func initializeLocalPackageInformation(rootDir string) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read package files
|
|
||||||
files := getPackageFiles(info.Name, rootDir)
|
|
||||||
|
|
||||||
// Add package to slice
|
// Add package to slice
|
||||||
tempPackageInformation[info.Name] = &BPMPackage{
|
tempPackageInformation[info.Name] = info
|
||||||
PkgInfo: info,
|
|
||||||
PkgFiles: files,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
localPackageInformation[rootDir] = tempPackageInformation
|
localPackageInformation[rootDir] = tempPackageInformation
|
||||||
@@ -71,8 +65,8 @@ func GetInstalledPackages(rootDir string) (ret []string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Loop through each package and add it to slice
|
// Loop through each package and add it to slice
|
||||||
for _, bpmpkg := range localPackageInformation[rootDir] {
|
for _, pkgInfo := range localPackageInformation[rootDir] {
|
||||||
ret = append(ret, bpmpkg.PkgInfo.Name)
|
ret = append(ret, pkgInfo.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort packages
|
// Sort packages
|
||||||
@@ -94,18 +88,6 @@ func IsPackageInstalled(pkg, rootDir string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPackageInfo(pkg string, rootDir string) *PackageInfo {
|
|
||||||
// Get BPM package
|
|
||||||
bpmpkg := GetPackage(pkg, rootDir)
|
|
||||||
|
|
||||||
// Return nil if not found
|
|
||||||
if bpmpkg == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return bpmpkg.PkgInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsVirtualPackage(pkg, rootDir string) (bool, string) {
|
func IsVirtualPackage(pkg, rootDir string) (bool, string) {
|
||||||
pkgs, err := GetInstalledPackages(rootDir)
|
pkgs, err := GetInstalledPackages(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -146,15 +128,27 @@ func IsPackageProvided(pkg, rootDir string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPackage(pkg, rootDir string) *BPMPackage {
|
func GetPackageInfo(pkg string, rootDir string) *PackageInfo {
|
||||||
err := initializeLocalPackageInformation(rootDir)
|
err := initializeLocalPackageInformation(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
bpmpkg := localPackageInformation[rootDir][pkg]
|
return localPackageInformation[rootDir][pkg]
|
||||||
|
}
|
||||||
|
|
||||||
return bpmpkg
|
func GetPackage(pkg, rootDir string) *BPMPackage {
|
||||||
|
pkgInfo := GetPackageInfo(pkg, rootDir)
|
||||||
|
if pkgInfo == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
files := getPackageFiles(pkgInfo.Name, rootDir)
|
||||||
|
|
||||||
|
return &BPMPackage{
|
||||||
|
PkgInfo: pkgInfo,
|
||||||
|
PkgFiles: files,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllPackageFiles(rootDir string, excludePackages ...string) (map[string][]*BPMPackage, error) {
|
func GetAllPackageFiles(rootDir string, excludePackages ...string) (map[string][]*BPMPackage, error) {
|
||||||
@@ -225,7 +219,7 @@ func getPackageFiles(pkg, rootDir string) []*PackageFileEntry {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
size, err := strconv.ParseUint(stringEntry[len(stringEntry)-1], 0, 64)
|
size, err := strconv.ParseInt(stringEntry[len(stringEntry)-1], 0, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+123
-48
@@ -87,8 +87,8 @@ func (operation *BPMOperation) RemoveAction(pkg, actionType string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) GetTotalDownloadSize() uint64 {
|
func (operation *BPMOperation) GetTotalDownloadSize() int64 {
|
||||||
var ret uint64 = 0
|
var ret int64 = 0
|
||||||
for _, action := range operation.Actions {
|
for _, action := range operation.Actions {
|
||||||
if action.GetActionType() == "fetch" {
|
if action.GetActionType() == "fetch" {
|
||||||
ret += action.(*FetchPackageAction).DatabaseEntry.DownloadSize
|
ret += action.(*FetchPackageAction).DatabaseEntry.DownloadSize
|
||||||
@@ -97,8 +97,8 @@ func (operation *BPMOperation) GetTotalDownloadSize() uint64 {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) GetTotalInstalledSize() uint64 {
|
func (operation *BPMOperation) GetTotalInstalledSize() int64 {
|
||||||
var ret uint64 = 0
|
var ret int64 = 0
|
||||||
for _, action := range operation.Actions {
|
for _, action := range operation.Actions {
|
||||||
if action.GetActionType() == "install" {
|
if action.GetActionType() == "install" {
|
||||||
ret += action.(*InstallPackageAction).BpmPackage.GetInstalledSize()
|
ret += action.(*InstallPackageAction).BpmPackage.GetInstalledSize()
|
||||||
@@ -113,14 +113,17 @@ func (operation *BPMOperation) GetFinalActionSize(rootDir string) int64 {
|
|||||||
var ret int64 = 0
|
var ret int64 = 0
|
||||||
for _, action := range operation.Actions {
|
for _, action := range operation.Actions {
|
||||||
if action.GetActionType() == "install" {
|
if action.GetActionType() == "install" {
|
||||||
ret += int64(action.(*InstallPackageAction).BpmPackage.GetInstalledSize())
|
ret += action.(*InstallPackageAction).BpmPackage.GetInstalledSize()
|
||||||
if IsPackageInstalled(action.(*InstallPackageAction).BpmPackage.PkgInfo.Name, rootDir) {
|
if IsPackageInstalled(action.(*InstallPackageAction).BpmPackage.PkgInfo.Name, rootDir) {
|
||||||
ret -= int64(GetPackage(action.(*InstallPackageAction).BpmPackage.PkgInfo.Name, rootDir).GetInstalledSize())
|
ret -= GetPackage(action.(*InstallPackageAction).BpmPackage.PkgInfo.Name, rootDir).GetInstalledSize()
|
||||||
}
|
}
|
||||||
} else if action.GetActionType() == "fetch" {
|
} else if action.GetActionType() == "fetch" {
|
||||||
ret += int64(action.(*FetchPackageAction).DatabaseEntry.InstalledSize)
|
ret += action.(*FetchPackageAction).DatabaseEntry.InstalledSize
|
||||||
|
if IsPackageInstalled(action.(*FetchPackageAction).DatabaseEntry.Info.Name, rootDir) {
|
||||||
|
ret -= action.(*FetchPackageAction).DatabaseEntry.InstalledSize
|
||||||
|
}
|
||||||
} else if action.GetActionType() == "remove" {
|
} else if action.GetActionType() == "remove" {
|
||||||
ret -= int64(action.(*RemovePackageAction).BpmPackage.GetInstalledSize())
|
ret -= action.(*RemovePackageAction).BpmPackage.GetInstalledSize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
@@ -277,54 +280,92 @@ func (operation *BPMOperation) ReplaceObsoletePackages() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) CheckForConflicts() (map[string][]string, error) {
|
func (operation *BPMOperation) CheckForConflicts() map[string][]string {
|
||||||
conflicts := make(map[string][]string)
|
conflicts := make(map[string][]string)
|
||||||
installedPackages, err := GetInstalledPackages(operation.RootDir)
|
|
||||||
if err != nil {
|
// Get installed packages
|
||||||
return nil, err
|
installedPackages := localPackageInformation[operation.RootDir]
|
||||||
}
|
|
||||||
allPackages := make([]*PackageInfo, len(installedPackages))
|
// Get packages to be removed
|
||||||
for i, value := range installedPackages {
|
removedPackages := make([]string, 0)
|
||||||
bpmpkg := GetPackage(value, operation.RootDir)
|
for _, value := range slices.Clone(operation.Actions) {
|
||||||
if bpmpkg == nil {
|
if value.GetActionType() != "remove" {
|
||||||
return nil, fmt.Errorf("could not find installed package (%s)", value)
|
continue
|
||||||
}
|
}
|
||||||
allPackages[i] = bpmpkg.PkgInfo
|
|
||||||
|
removedPackages = append(removedPackages, value.(*RemovePackageAction).BpmPackage.PkgInfo.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all new packages to the allPackages slice
|
// Check for conflicts
|
||||||
for _, value := range slices.Clone(operation.Actions) {
|
for _, value := range slices.Clone(operation.Actions) {
|
||||||
|
var pkgInfo *PackageInfo
|
||||||
if value.GetActionType() == "install" {
|
if value.GetActionType() == "install" {
|
||||||
action := value.(*InstallPackageAction)
|
pkgInfo = value.(*InstallPackageAction).BpmPackage.PkgInfo
|
||||||
pkgInfo := action.BpmPackage.PkgInfo
|
|
||||||
allPackages = append(allPackages, pkgInfo)
|
|
||||||
} else if value.GetActionType() == "fetch" {
|
} else if value.GetActionType() == "fetch" {
|
||||||
action := value.(*FetchPackageAction)
|
pkgInfo = value.(*FetchPackageAction).DatabaseEntry.Info
|
||||||
pkgInfo := action.DatabaseEntry.Info
|
} else {
|
||||||
allPackages = append(allPackages, pkgInfo)
|
continue
|
||||||
} else if value.GetActionType() == "remove" {
|
}
|
||||||
action := value.(*RemovePackageAction)
|
|
||||||
pkgInfo := action.BpmPackage.PkgInfo
|
// Check for conflicts with installed packages
|
||||||
for i := len(allPackages) - 1; i >= 0; i-- {
|
for _, installedPkg := range installedPackages {
|
||||||
info := allPackages[i]
|
// Skip if package is to be removed
|
||||||
if info.Name == pkgInfo.Name {
|
if slices.Contains(removedPackages, installedPkg.Name) {
|
||||||
allPackages = append(allPackages[:i], allPackages[i+1:]...)
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if same package
|
||||||
|
if pkgInfo.Name == installedPkg.Name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for new package conflicts
|
||||||
|
if slices.Contains(pkgInfo.Conflicts, installedPkg.Name) {
|
||||||
|
conflicts[pkgInfo.Name] = append(conflicts[pkgInfo.Name], installedPkg.Name)
|
||||||
|
}
|
||||||
|
for _, vpkg := range installedPkg.Provides {
|
||||||
|
if slices.Contains(pkgInfo.Conflicts, vpkg) {
|
||||||
|
conflicts[pkgInfo.Name] = append(conflicts[pkgInfo.Name], vpkg+" ("+installedPkg.Name+")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for installed package conflicts
|
||||||
|
for _, vpkg := range pkgInfo.Provides {
|
||||||
|
if slices.Contains(installedPkg.Conflicts, vpkg) {
|
||||||
|
conflicts[installedPkg.Name] = append(conflicts[installedPkg.Name], vpkg+" ("+pkgInfo.Name+")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for conflicts with other new packages
|
||||||
|
for _, value := range slices.Clone(operation.Actions) {
|
||||||
|
var pkgInfo2 *PackageInfo
|
||||||
|
if value.GetActionType() == "install" {
|
||||||
|
pkgInfo2 = value.(*InstallPackageAction).BpmPackage.PkgInfo
|
||||||
|
} else if value.GetActionType() == "fetch" {
|
||||||
|
pkgInfo2 = value.(*FetchPackageAction).DatabaseEntry.Info
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if same package
|
||||||
|
if pkgInfo.Name == pkgInfo2.Name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for other package conflicts
|
||||||
|
if slices.Contains(pkgInfo.Conflicts, pkgInfo2.Name) {
|
||||||
|
conflicts[pkgInfo.Name] = append(conflicts[pkgInfo.Name], pkgInfo2.Name)
|
||||||
|
}
|
||||||
|
for _, vpkg := range pkgInfo2.Provides {
|
||||||
|
if slices.Contains(pkgInfo.Conflicts, vpkg) {
|
||||||
|
conflicts[pkgInfo.Name] = append(conflicts[pkgInfo.Name], vpkg+" ("+pkgInfo2.Name+")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, value := range allPackages {
|
return conflicts
|
||||||
for _, conflict := range value.Conflicts {
|
|
||||||
if slices.ContainsFunc(allPackages, func(info *PackageInfo) bool {
|
|
||||||
return info.Name == conflict
|
|
||||||
}) {
|
|
||||||
conflicts[value.Name] = append(conflicts[value.Name], conflict)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return conflicts, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) ShowOperationSummary() {
|
func (operation *BPMOperation) ShowOperationSummary() {
|
||||||
@@ -370,7 +411,7 @@ func (operation *BPMOperation) ShowOperationSummary() {
|
|||||||
if installedInfo == nil {
|
if installedInfo == nil {
|
||||||
fmt.Fprintf(writer, "%s\t%s\t%s\t%s\t%t\n", pkgInfo.Name, pkgInfo.GetFullVersion(), "Install", installationReasonStr, pkgInfo.Type == "source")
|
fmt.Fprintf(writer, "%s\t%s\t%s\t%s\t%t\n", pkgInfo.Name, pkgInfo.GetFullVersion(), "Install", installationReasonStr, pkgInfo.Type == "source")
|
||||||
} else {
|
} else {
|
||||||
comparison := ComparePackageVersions(*pkgInfo, *installedInfo)
|
comparison := CompareVersions(pkgInfo.GetFullVersion(), installedInfo.GetFullVersion())
|
||||||
if comparison < 0 {
|
if comparison < 0 {
|
||||||
fmt.Fprintf(writer, "%s\t%s -> %s\t%s\t%s\t%t\n", pkgInfo.Name, installedInfo.GetFullVersion(), pkgInfo.GetFullVersion(), "Downgrade", installationReasonStr, pkgInfo.Type == "source")
|
fmt.Fprintf(writer, "%s\t%s -> %s\t%s\t%s\t%t\n", pkgInfo.Name, installedInfo.GetFullVersion(), pkgInfo.GetFullVersion(), "Downgrade", installationReasonStr, pkgInfo.Type == "source")
|
||||||
} else if comparison > 0 {
|
} else if comparison > 0 {
|
||||||
@@ -388,12 +429,12 @@ func (operation *BPMOperation) ShowOperationSummary() {
|
|||||||
fmt.Println("Warning: Operating in " + operation.RootDir)
|
fmt.Println("Warning: Operating in " + operation.RootDir)
|
||||||
}
|
}
|
||||||
if operation.GetTotalDownloadSize() > 0 {
|
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", BytesToHumanReadable(operation.GetTotalDownloadSize()))
|
||||||
}
|
}
|
||||||
if operation.GetFinalActionSize(operation.RootDir) > 0 {
|
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 {
|
} 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)), "-"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,6 +466,40 @@ func (operation *BPMOperation) ShowSourcePackageContent() (sourcePackagesShown i
|
|||||||
return sourcePackagesShown, nil
|
return sourcePackagesShown, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (operation *BPMOperation) GetOptionalDependencies() (optionalDepends map[string][]string) {
|
||||||
|
optionalDepends = make(map[string][]string)
|
||||||
|
|
||||||
|
// Find all optional dependencies
|
||||||
|
for _, value := range slices.Clone(operation.Actions) {
|
||||||
|
var pkgInfo *PackageInfo
|
||||||
|
if value.GetActionType() == "install" {
|
||||||
|
action := value.(*InstallPackageAction)
|
||||||
|
pkgInfo = action.BpmPackage.PkgInfo
|
||||||
|
} else if value.GetActionType() == "fetch" {
|
||||||
|
action := value.(*FetchPackageAction)
|
||||||
|
pkgInfo = action.DatabaseEntry.Info
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, depend := range pkgInfo.OptionalDepends {
|
||||||
|
// Skip if dependency is already installed
|
||||||
|
if IsPackageInstalled(depend, operation.RootDir) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if not a new dependency of the package
|
||||||
|
if installedPkg := GetPackage(pkgInfo.Name, operation.RootDir); installedPkg != nil && slices.Contains(installedPkg.PkgInfo.OptionalDepends, depend) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
optionalDepends[pkgInfo.Name] = append(optionalDepends[pkgInfo.Name], depend)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) RunHooks(verbose bool) error {
|
func (operation *BPMOperation) RunHooks(verbose bool) error {
|
||||||
// Return if hooks directory does not exist
|
// Return if hooks directory does not exist
|
||||||
if stat, err := os.Stat(path.Join(operation.RootDir, "var/lib/bpm/hooks")); err != nil || !stat.IsDir() {
|
if stat, err := os.Stat(path.Join(operation.RootDir, "var/lib/bpm/hooks")); err != nil || !stat.IsDir() {
|
||||||
|
|||||||
+86
-67
@@ -17,7 +17,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
version "github.com/knqyf263/go-rpm-version"
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -70,11 +69,11 @@ type PackageFileEntry struct {
|
|||||||
OctalPerms uint32
|
OctalPerms uint32
|
||||||
UserID int
|
UserID int
|
||||||
GroupID int
|
GroupID int
|
||||||
SizeInBytes uint64
|
SizeInBytes int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pkg *BPMPackage) GetInstalledSize() uint64 {
|
func (pkg *BPMPackage) GetInstalledSize() int64 {
|
||||||
var totalSize uint64 = 0
|
var totalSize int64 = 0
|
||||||
for _, entry := range pkg.PkgFiles {
|
for _, entry := range pkg.PkgFiles {
|
||||||
totalSize += entry.SizeInBytes
|
totalSize += entry.SizeInBytes
|
||||||
}
|
}
|
||||||
@@ -121,13 +120,6 @@ const (
|
|||||||
InstallationReasonUnknown InstallationReason = "unknown"
|
InstallationReasonUnknown InstallationReason = "unknown"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ComparePackageVersions(info1, info2 PackageInfo) int {
|
|
||||||
v1 := version.NewVersion(info1.GetFullVersion())
|
|
||||||
v2 := version.NewVersion(info2.GetFullVersion())
|
|
||||||
|
|
||||||
return v1.Compare(v2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetInstallationReason(pkg, rootDir string) InstallationReason {
|
func GetInstallationReason(pkg, rootDir string) InstallationReason {
|
||||||
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
pkgDir := path.Join(installedDir, pkg)
|
pkgDir := path.Join(installedDir, pkg)
|
||||||
@@ -240,7 +232,7 @@ func ReadPackage(filename string) (*BPMPackage, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
size, err := strconv.ParseUint(stringEntry[len(stringEntry)-1], 0, 64)
|
size, err := strconv.ParseInt(stringEntry[len(stringEntry)-1], 0, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -376,9 +368,44 @@ func executePackageScript(pkg, rootDir string, verbose bool, packageScript strin
|
|||||||
cmd := exec.Command("/bin/bash", "-c", content)
|
cmd := exec.Command("/bin/bash", "-c", content)
|
||||||
// Setup subprocess environment
|
// Setup subprocess environment
|
||||||
cmd.Dir = "/"
|
cmd.Dir = "/"
|
||||||
// Run hook in chroot if using the -R flag
|
// Run package script in chroot if using the -R flag
|
||||||
if rootDir != "/" {
|
if rootDir != "/" {
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{Chroot: rootDir}
|
cmd.SysProcAttr = &syscall.SysProcAttr{Chroot: rootDir}
|
||||||
|
|
||||||
|
// Bind mount /etc/resolv.conf
|
||||||
|
mounted, err := func() (bool, error) {
|
||||||
|
if _, err := os.Stat("/etc/resolv.conf"); err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(path.Join(rootDir, "etc/resolv.conf")); os.IsNotExist(err) {
|
||||||
|
err = os.WriteFile(path.Join(rootDir, "/etc/resolv.conf"), nil, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
} else if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mntCmd := exec.Command("mount", "-o", "ro,bind", "/etc/resolv.conf", path.Join(rootDir, "/etc/resolv.conf"))
|
||||||
|
if verbose {
|
||||||
|
mntCmd.Stdout = os.Stdout
|
||||||
|
mntCmd.Stderr = os.Stderr
|
||||||
|
}
|
||||||
|
err = mntCmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if mounted {
|
||||||
|
defer exec.Command("umount", "-f", path.Join(rootDir, "/etc/resolv.conf")).Run()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Show output if verbose
|
// Show output if verbose
|
||||||
if verbose {
|
if verbose {
|
||||||
@@ -509,60 +536,57 @@ func ReadPackageInfo(contents string) (*PackageInfo, error) {
|
|||||||
return pkgInfo, nil
|
return pkgInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bpmpkg *BPMPackage) CreateReadableInfo(rootDir string, humanReadableSize bool) string {
|
func (pkgInfo *PackageInfo) CreateReadableInfo(rootDir string) string {
|
||||||
ret := make([]string, 0)
|
ret := make([]string, 0)
|
||||||
appendArray := func(label string, array []string) {
|
appendArray := func(label string, array []string) {
|
||||||
if len(array) == 0 {
|
if len(array) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort array
|
|
||||||
slices.Sort(array)
|
|
||||||
|
|
||||||
ret = append(ret, fmt.Sprintf("%s: %s", label, strings.Join(array, ", ")))
|
ret = append(ret, fmt.Sprintf("%s: %s", label, strings.Join(array, ", ")))
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = append(ret, "Name: "+bpmpkg.PkgInfo.Name)
|
ret = append(ret, "Name: "+pkgInfo.Name)
|
||||||
ret = append(ret, "Description: "+bpmpkg.PkgInfo.Description)
|
ret = append(ret, "Description: "+pkgInfo.Description)
|
||||||
ret = append(ret, "Version: "+bpmpkg.PkgInfo.GetFullVersion())
|
ret = append(ret, "Version: "+pkgInfo.GetFullVersion())
|
||||||
if bpmpkg.PkgInfo.Url != "" {
|
if pkgInfo.Url != "" {
|
||||||
ret = append(ret, "URL: "+bpmpkg.PkgInfo.Url)
|
ret = append(ret, "URL: "+pkgInfo.Url)
|
||||||
}
|
}
|
||||||
if bpmpkg.PkgInfo.License != "" {
|
if pkgInfo.License != "" {
|
||||||
ret = append(ret, "License: "+bpmpkg.PkgInfo.License)
|
ret = append(ret, "License: "+pkgInfo.License)
|
||||||
}
|
}
|
||||||
ret = append(ret, "Architecture: "+bpmpkg.PkgInfo.Arch)
|
ret = append(ret, "Architecture: "+pkgInfo.Arch)
|
||||||
if bpmpkg.PkgInfo.Type == "source" && bpmpkg.PkgInfo.OutputArch != "" && bpmpkg.PkgInfo.OutputArch != GetArch() {
|
if pkgInfo.Type == "source" && pkgInfo.OutputArch != "" && pkgInfo.OutputArch != GetArch() {
|
||||||
ret = append(ret, "Output architecture: "+bpmpkg.PkgInfo.Arch)
|
ret = append(ret, "Output architecture: "+pkgInfo.Arch)
|
||||||
}
|
}
|
||||||
ret = append(ret, "Type: "+bpmpkg.PkgInfo.Type)
|
ret = append(ret, "Type: "+pkgInfo.Type)
|
||||||
appendArray("Dependencies", bpmpkg.PkgInfo.Depends)
|
appendArray("Dependencies", pkgInfo.Depends)
|
||||||
if bpmpkg.PkgInfo.Type == "source" {
|
if pkgInfo.Type == "source" {
|
||||||
appendArray("Make Dependencies", bpmpkg.PkgInfo.MakeDepends)
|
appendArray("Make Dependencies", pkgInfo.MakeDepends)
|
||||||
}
|
}
|
||||||
appendArray("Optional dependencies", bpmpkg.PkgInfo.OptionalDepends)
|
appendArray("Optional dependencies", pkgInfo.OptionalDepends)
|
||||||
dependants := bpmpkg.PkgInfo.GetPackageDependants(rootDir)
|
dependants := pkgInfo.GetPackageDependants(rootDir)
|
||||||
if len(dependants) > 0 {
|
if len(dependants) > 0 {
|
||||||
appendArray("Dependant packages", dependants)
|
appendArray("Dependant packages", dependants)
|
||||||
}
|
}
|
||||||
optionalDependants := bpmpkg.PkgInfo.GetPackageOptionalDependants(rootDir)
|
optionalDependants := pkgInfo.GetPackageOptionalDependants(rootDir)
|
||||||
if len(optionalDependants) > 0 {
|
if len(optionalDependants) > 0 {
|
||||||
appendArray("Optionally dependant packages", optionalDependants)
|
appendArray("Optionally dependant packages", optionalDependants)
|
||||||
}
|
}
|
||||||
appendArray("Conflicting packages", bpmpkg.PkgInfo.Conflicts)
|
appendArray("Conflicting packages", pkgInfo.Conflicts)
|
||||||
appendArray("Provided packages", bpmpkg.PkgInfo.Provides)
|
appendArray("Provided packages", pkgInfo.Provides)
|
||||||
appendArray("Replaces packages", bpmpkg.PkgInfo.Replaces)
|
appendArray("Replaces packages", pkgInfo.Replaces)
|
||||||
|
|
||||||
if bpmpkg.PkgInfo.Type == "source" && len(bpmpkg.PkgInfo.SplitPackages) != 0 {
|
if pkgInfo.Type == "source" && len(pkgInfo.SplitPackages) != 0 {
|
||||||
splitPkgs := make([]string, len(bpmpkg.PkgInfo.SplitPackages))
|
splitPkgs := make([]string, len(pkgInfo.SplitPackages))
|
||||||
for i, splitPkgInfo := range bpmpkg.PkgInfo.SplitPackages {
|
for i, splitPkgInfo := range pkgInfo.SplitPackages {
|
||||||
splitPkgs[i] = splitPkgInfo.Name
|
splitPkgs[i] = splitPkgInfo.Name
|
||||||
}
|
}
|
||||||
appendArray("Split Packages", splitPkgs)
|
appendArray("Split Packages", splitPkgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rootDir != "" && IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) {
|
if rootDir != "" && IsPackageInstalled(pkgInfo.Name, rootDir) {
|
||||||
installationReason := GetInstallationReason(bpmpkg.PkgInfo.Name, rootDir)
|
installationReason := GetInstallationReason(pkgInfo.Name, rootDir)
|
||||||
var installationReasonString string
|
var installationReasonString string
|
||||||
switch installationReason {
|
switch installationReason {
|
||||||
case InstallationReasonManual:
|
case InstallationReasonManual:
|
||||||
@@ -576,31 +600,11 @@ func (bpmpkg *BPMPackage) CreateReadableInfo(rootDir string, humanReadableSize b
|
|||||||
}
|
}
|
||||||
ret = append(ret, "Installation Reason: "+installationReasonString)
|
ret = append(ret, "Installation Reason: "+installationReasonString)
|
||||||
}
|
}
|
||||||
if bpmpkg.PkgInfo.Type == "binary" {
|
|
||||||
installedSize := int64(bpmpkg.GetInstalledSize())
|
|
||||||
var installedSizeStr string
|
|
||||||
if humanReadableSize {
|
|
||||||
installedSizeStr = bytesToHumanReadable(installedSize)
|
|
||||||
} else {
|
|
||||||
installedSizeStr = strconv.FormatInt(installedSize, 10)
|
|
||||||
}
|
|
||||||
ret = append(ret, "Installed size: "+installedSizeStr)
|
|
||||||
}
|
|
||||||
return strings.Join(ret, "\n")
|
return strings.Join(ret, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) error {
|
func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) error {
|
||||||
if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) {
|
|
||||||
err := executePackageScript(filename, rootDir, verbose, "pre_install.sh")
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Warning: %s\n", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err := executePackageScript(filename, rootDir, verbose, "pre_update.sh")
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Warning: %s\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
seenHardlinks := make(map[string]string)
|
seenHardlinks := make(map[string]string)
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -608,7 +612,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize progress bar
|
// Initialize progress bar
|
||||||
bar := createProgressBar(int64(bpmpkg.GetInstalledSize()), "Installing "+bpmpkg.PkgInfo.Name, verbose)
|
bar := createProgressBar(bpmpkg.GetInstalledSize(), "Installing "+bpmpkg.PkgInfo.Name, verbose)
|
||||||
defer bar.Close()
|
defer bar.Close()
|
||||||
|
|
||||||
tarballFile, err := readTarballFile(filename, "files.tar.gz")
|
tarballFile, err := readTarballFile(filename, "files.tar.gz")
|
||||||
@@ -776,6 +780,20 @@ func installPackage(filename, rootDir string, verbose, force bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
packageInstalled := IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir)
|
packageInstalled := IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir)
|
||||||
|
|
||||||
|
// Run pre-* package scripts
|
||||||
|
if !packageInstalled {
|
||||||
|
err := executePackageScript(filename, rootDir, verbose, "pre_install.sh")
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Warning: %s\n", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := executePackageScript(filename, rootDir, verbose, "pre_update.sh")
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Warning: %s\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if package is installed and remove current files
|
// Check if package is installed and remove current files
|
||||||
if packageInstalled {
|
if packageInstalled {
|
||||||
// Fetching and reversing package file entry list
|
// Fetching and reversing package file entry list
|
||||||
@@ -957,6 +975,7 @@ func installPackage(filename, rootDir string, verbose, force bool) error {
|
|||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run post-* package scripts
|
||||||
if !packageInstalled {
|
if !packageInstalled {
|
||||||
err = executePackageScript(filename, rootDir, verbose, "post_install.sh")
|
err = executePackageScript(filename, rootDir, verbose, "post_install.sh")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -976,7 +995,7 @@ func installPackage(filename, rootDir string, verbose, force bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add or update package information for rootDir
|
// Add or update package information for rootDir
|
||||||
localPackageInformation[rootDir][bpmpkg.PkgInfo.Name] = bpmpkg
|
localPackageInformation[rootDir][bpmpkg.PkgInfo.Name] = bpmpkg.PkgInfo
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -1008,12 +1027,12 @@ func removePackage(pkg string, verbose bool, rootDir string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
bar := createProgressBar(int64(bpmpkg.GetInstalledSize()), "Removing "+bpmpkg.PkgInfo.Name, verbose)
|
bar := createProgressBar(bpmpkg.GetInstalledSize(), "Removing "+bpmpkg.PkgInfo.Name, verbose)
|
||||||
defer bar.Close()
|
defer bar.Close()
|
||||||
|
|
||||||
// Removing package files
|
// Removing package files
|
||||||
for _, entry := range fileEntries {
|
for _, entry := range fileEntries {
|
||||||
bar.Add64(int64(entry.SizeInBytes))
|
bar.Add64(entry.SizeInBytes)
|
||||||
file := path.Join(rootDir, entry.Path)
|
file := path.Join(rootDir, entry.Path)
|
||||||
lstat, err := os.Lstat(file)
|
lstat, err := os.Lstat(file)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
|||||||
+31
-22
@@ -9,6 +9,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
version "github.com/knqyf263/go-rpm-version"
|
||||||
"github.com/schollz/progressbar/v3"
|
"github.com/schollz/progressbar/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,20 +18,6 @@ type BPMLock struct {
|
|||||||
path string
|
path string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lock *BPMLock) Unlock() error {
|
|
||||||
err := lock.file.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.Remove(lock.path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func LockBPM(rootDir string) (*BPMLock, error) {
|
func LockBPM(rootDir string) (*BPMLock, error) {
|
||||||
// Create parent directories if they don't already exist
|
// Create parent directories if they don't already exist
|
||||||
err := os.MkdirAll(path.Join(rootDir, "/var/lib/bpm"), 0755)
|
err := os.MkdirAll(path.Join(rootDir, "/var/lib/bpm"), 0755)
|
||||||
@@ -53,6 +40,20 @@ func LockBPM(rootDir string) (*BPMLock, error) {
|
|||||||
return &BPMLock{f, path.Join(rootDir, "var/lib/bpm/bpm.lock")}, nil
|
return &BPMLock{f, path.Join(rootDir, "var/lib/bpm/bpm.lock")}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lock *BPMLock) Unlock() error {
|
||||||
|
err := lock.file.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Remove(lock.path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetArch() string {
|
func GetArch() string {
|
||||||
uname := syscall.Utsname{}
|
uname := syscall.Utsname{}
|
||||||
err := syscall.Uname(&uname)
|
err := syscall.Uname(&uname)
|
||||||
@@ -68,6 +69,13 @@ func GetArch() string {
|
|||||||
return string(byteString[:indexLength])
|
return string(byteString[:indexLength])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CompareVersions(version1, version2 string) int {
|
||||||
|
v1 := version.NewVersion(version1)
|
||||||
|
v2 := version.NewVersion(version2)
|
||||||
|
|
||||||
|
return v1.Compare(v2)
|
||||||
|
}
|
||||||
|
|
||||||
func createProgressBar(max int64, description string, hideBar bool) *progressbar.ProgressBar {
|
func createProgressBar(max int64, description string, hideBar bool) *progressbar.ProgressBar {
|
||||||
var output io.Writer
|
var output io.Writer
|
||||||
if hideBar {
|
if hideBar {
|
||||||
@@ -111,7 +119,7 @@ func stringSliceRemove(s []string, r string) []string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func unsignedBytesToHumanReadable(b uint64) string {
|
func BytesToHumanReadable(b int64) string {
|
||||||
bf := float64(b)
|
bf := float64(b)
|
||||||
for _, unit := range []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"} {
|
for _, unit := range []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"} {
|
||||||
if math.Abs(bf) < 1024.0 {
|
if math.Abs(bf) < 1024.0 {
|
||||||
@@ -122,13 +130,14 @@ func unsignedBytesToHumanReadable(b uint64) string {
|
|||||||
return fmt.Sprintf("%.1fYiB", bf)
|
return fmt.Sprintf("%.1fYiB", bf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bytesToHumanReadable(b int64) string {
|
func removeDuplicates[T comparable](sliceList []T) []T {
|
||||||
bf := float64(b)
|
allKeys := make(map[T]bool)
|
||||||
for _, unit := range []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"} {
|
list := []T{}
|
||||||
if math.Abs(bf) < 1024.0 {
|
for _, item := range sliceList {
|
||||||
return fmt.Sprintf("%3.1f%sB", bf, unit)
|
if _, value := allKeys[item]; !value {
|
||||||
|
allKeys[item] = true
|
||||||
|
list = append(list, item)
|
||||||
}
|
}
|
||||||
bf /= 1024.0
|
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%.1fYiB", bf)
|
return list
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user