mirror of
https://github.com/EnumeratedDev/bpm.git
synced 2026-09-26 15:36:13 +00:00
Compare commits
11
Commits
0.5.0
..
0c754a7e0f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c754a7e0f
|
||
|
|
eeb9a01e31
|
||
|
|
53e08ce7f9
|
||
|
|
6f124e0586
|
||
|
|
93921d4093
|
||
|
|
bc89db8cef
|
||
|
|
ea6d722fa8
|
||
|
|
264a0f87ba
|
||
|
|
926b0e35fc
|
||
|
|
a4d1365e55 | ||
|
|
bc3fe6fd7e |
@@ -9,6 +9,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
|
replace git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib => ../bpmlib
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/drone/envsubst v1.0.3 // indirect
|
||||||
github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f // indirect
|
github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g=
|
||||||
|
github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
|
||||||
|
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
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 h1:xt29M2T6STgldg+WEP51gGePQCsQvklmP2eIhPIBK3g=
|
||||||
github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f/go.mod h1:i4sF0l1fFnY1aiw08QQSwVAFxHEm311Me3WsU/X7nL0=
|
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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
|||||||
+254
-72
@@ -21,7 +21,7 @@ import (
|
|||||||
/* A simple-to-use package manager */
|
/* A simple-to-use package manager */
|
||||||
/* ------------------------------------------------------- */
|
/* ------------------------------------------------------- */
|
||||||
|
|
||||||
var bpmVer = "0.5.0"
|
var bpmVer = "0.6.0"
|
||||||
|
|
||||||
var subcommand = "help"
|
var subcommand = "help"
|
||||||
var subcommandArgs []string
|
var subcommandArgs []string
|
||||||
@@ -44,12 +44,15 @@ var showDatabaseInfo = false
|
|||||||
var installSrcPkgDepends = false
|
var installSrcPkgDepends = false
|
||||||
var skipChecks = false
|
var skipChecks = false
|
||||||
var outputDirectory = ""
|
var outputDirectory = ""
|
||||||
|
var outputFd = -1
|
||||||
var cleanupDependencies = false
|
var cleanupDependencies = false
|
||||||
var cleanupMakeDependencies = false
|
var cleanupMakeDependencies = false
|
||||||
var cleanupCompilationFiles = false
|
var cleanupCompilationFiles = false
|
||||||
var cleanupCompiledPackages = false
|
var cleanupCompiledPackages = false
|
||||||
var cleanupFetchedPackages = false
|
var cleanupFetchedPackages = false
|
||||||
|
|
||||||
|
var exitCode = 0
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err := bpmlib.ReadConfig()
|
err := bpmlib.ReadConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -57,6 +60,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
resolveFlags()
|
resolveFlags()
|
||||||
resolveCommand()
|
resolveCommand()
|
||||||
|
|
||||||
|
if exitCode != 0 {
|
||||||
|
os.Exit(exitCode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type commandType uint8
|
type commandType uint8
|
||||||
@@ -120,7 +127,9 @@ func resolveCommand() {
|
|||||||
// Read local databases
|
// Read local databases
|
||||||
err := bpmlib.ReadLocalDatabaseFiles()
|
err := bpmlib.ReadLocalDatabaseFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not read local databases: %s", err)
|
log.Printf("Error: could not read local databases: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for n, pkg := range packages {
|
for n, pkg := range packages {
|
||||||
@@ -133,14 +142,18 @@ func resolveCommand() {
|
|||||||
entry, _, err = bpmlib.GetDatabaseEntry(pkg)
|
entry, _, err = bpmlib.GetDatabaseEntry(pkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if entry = bpmlib.ResolveVirtualPackage(pkg); entry == nil {
|
if entry = bpmlib.ResolveVirtualPackage(pkg); entry == nil {
|
||||||
log.Fatalf("Error: could not find package (%s) in any database\n", pkg)
|
log.Printf("Error: could not find package (%s) in any database\n", pkg)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info = entry.Info
|
info = entry.Info
|
||||||
} else if stat, err := os.Stat(pkg); err == nil && !stat.IsDir() {
|
} else if stat, err := os.Stat(pkg); err == nil && !stat.IsDir() {
|
||||||
bpmpkg, err := bpmlib.ReadPackage(pkg)
|
bpmpkg, err := bpmlib.ReadPackage(pkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not read package: %s\n", err)
|
log.Printf("Error: could not read package: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
info = bpmpkg.PkgInfo
|
info = bpmpkg.PkgInfo
|
||||||
isFile = true
|
isFile = true
|
||||||
@@ -153,7 +166,9 @@ func resolveCommand() {
|
|||||||
showInstallationReason = true
|
showInstallationReason = true
|
||||||
}
|
}
|
||||||
if info == nil {
|
if info == nil {
|
||||||
log.Fatalf("Error: package (%s) is not installed\n", pkg)
|
log.Printf("Error: package (%s) is not installed\n", pkg)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if n != 0 {
|
if n != 0 {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
@@ -161,7 +176,9 @@ func resolveCommand() {
|
|||||||
if isFile {
|
if isFile {
|
||||||
abs, err := filepath.Abs(pkg)
|
abs, err := filepath.Abs(pkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get absolute path of file (%s)\n", abs)
|
log.Printf("Error: could not get absolute path of file (%s)\n", abs)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("File: " + abs)
|
fmt.Println("File: " + abs)
|
||||||
}
|
}
|
||||||
@@ -171,12 +188,15 @@ func resolveCommand() {
|
|||||||
// Read local databases
|
// Read local databases
|
||||||
err := bpmlib.ReadLocalDatabaseFiles()
|
err := bpmlib.ReadLocalDatabaseFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not read local databases: %s", err)
|
log.Printf("Error: could not read local databases: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
packages, err := bpmlib.GetInstalledPackages(rootDir)
|
packages, err := bpmlib.GetInstalledPackages(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get installed packages: %s", err.Error())
|
log.Printf("Error: could not get installed packages: %s", err.Error())
|
||||||
|
exitCode = 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if pkgListNumbers {
|
if pkgListNumbers {
|
||||||
@@ -205,19 +225,23 @@ func resolveCommand() {
|
|||||||
case search:
|
case search:
|
||||||
searchTerms := subcommandArgs
|
searchTerms := subcommandArgs
|
||||||
if len(searchTerms) == 0 {
|
if len(searchTerms) == 0 {
|
||||||
log.Fatalf("Error: no search terms given")
|
log.Printf("Error: no search terms given")
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read local databases
|
// Read local databases
|
||||||
err := bpmlib.ReadLocalDatabaseFiles()
|
err := bpmlib.ReadLocalDatabaseFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not read local databases: %s", err)
|
log.Printf("Error: could not read local databases: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, term := range searchTerms {
|
for i, term := range searchTerms {
|
||||||
nameResults := make([]*bpmlib.PackageInfo, 0)
|
nameResults := make([]*bpmlib.PackageInfo, 0)
|
||||||
descResults := make([]*bpmlib.PackageInfo, 0)
|
descResults := make([]*bpmlib.PackageInfo, 0)
|
||||||
for _, db := range bpmlib.MainBPMConfig.Databases {
|
for _, db := range bpmlib.BPMDatabases {
|
||||||
for _, entry := range db.Entries {
|
for _, entry := range db.Entries {
|
||||||
if strings.Contains(entry.Info.Name, term) {
|
if strings.Contains(entry.Info.Name, term) {
|
||||||
nameResults = append(nameResults, entry.Info)
|
nameResults = append(nameResults, entry.Info)
|
||||||
@@ -228,7 +252,9 @@ func resolveCommand() {
|
|||||||
}
|
}
|
||||||
results := append(nameResults, descResults...)
|
results := append(nameResults, descResults...)
|
||||||
if len(results) == 0 {
|
if len(results) == 0 {
|
||||||
log.Fatalf("Error: no results for term (%s) were found\n", term)
|
log.Printf("Error: no results for term (%s) were found\n", term)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
@@ -241,7 +267,9 @@ func resolveCommand() {
|
|||||||
case install:
|
case install:
|
||||||
// Check for required permissions
|
// Check for required permissions
|
||||||
if os.Getuid() != 0 {
|
if os.Getuid() != 0 {
|
||||||
log.Fatalf("Error: this subcommand needs to be run with superuser permissions")
|
log.Printf("Error: this subcommand needs to be run with superuser permissions")
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return if no packages are specified
|
// Return if no packages are specified
|
||||||
@@ -261,7 +289,9 @@ func resolveCommand() {
|
|||||||
ir = bpmlib.InstallationReasonMakeDependency
|
ir = bpmlib.InstallationReasonMakeDependency
|
||||||
case "":
|
case "":
|
||||||
default:
|
default:
|
||||||
log.Fatalf("Error: %s is not a valid installation reason", installationReason)
|
log.Printf("Error: %s is not a valid installation reason", installationReason)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get reinstall method
|
// Get reinstall method
|
||||||
@@ -274,18 +304,33 @@ func resolveCommand() {
|
|||||||
reinstallMethod = bpmlib.ReinstallMethodNone
|
reinstallMethod = bpmlib.ReinstallMethodNone
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read local databases
|
// Create BPM Lock file
|
||||||
err := bpmlib.ReadLocalDatabaseFiles()
|
fileLock, err := bpmlib.LockBPM(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not read local databases: %s", err)
|
log.Printf("Error: could not create BPM lock file: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fileLock.Unlock()
|
||||||
|
|
||||||
|
// Read local databases
|
||||||
|
err = bpmlib.ReadLocalDatabaseFiles()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error: could not read local databases: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create installation operation
|
// Create installation operation
|
||||||
operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallMethod, installOptional, force, verbose, subcommandArgs...)
|
operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallMethod, installOptional, force, verbose, subcommandArgs...)
|
||||||
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.Fatalf("Error: %s", err)
|
log.Printf("Error: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Fatalf("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
|
||||||
@@ -309,42 +354,62 @@ func resolveCommand() {
|
|||||||
text, _ := reader.ReadString('\n')
|
text, _ := reader.ReadString('\n')
|
||||||
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
||||||
fmt.Println("Cancelling package installation...")
|
fmt.Println("Cancelling package installation...")
|
||||||
os.Exit(1)
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute operation
|
// Execute operation
|
||||||
err = operation.Execute(verbose, force)
|
err = operation.Execute(verbose, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not complete operation: %s\n", err)
|
log.Printf("Error: could not complete operation: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executing hooks
|
// Executing hooks
|
||||||
fmt.Println("Running hooks...")
|
fmt.Println("Running hooks...")
|
||||||
err = operation.RunHooks(verbose)
|
err = operation.RunHooks(verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not run hooks: %s\n", err)
|
log.Printf("Error: could not run hooks: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
case update:
|
case update:
|
||||||
// Check for required permissions
|
// Check for required permissions
|
||||||
if os.Getuid() != 0 {
|
if os.Getuid() != 0 {
|
||||||
log.Fatalf("Error: this subcommand needs to be run with superuser permissions")
|
log.Printf("Error: this subcommand needs to be run with superuser permissions")
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create BPM Lock file
|
||||||
|
fileLock, err := bpmlib.LockBPM(rootDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error: could not create BPM lock file: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fileLock.Unlock()
|
||||||
|
|
||||||
// Read local databases if no sync
|
// Read local databases if no sync
|
||||||
if nosync {
|
if nosync {
|
||||||
err := bpmlib.ReadLocalDatabaseFiles()
|
err := bpmlib.ReadLocalDatabaseFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not read local databases: %s", err)
|
log.Printf("Error: could not read local databases: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create update operation
|
// Create update operation
|
||||||
operation, err := bpmlib.UpdatePackages(rootDir, !nosync, installOptional, force, verbose)
|
operation, err := bpmlib.UpdatePackages(rootDir, !nosync, 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.Fatalf("Error: %s", err)
|
log.Printf("Error: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Fatalf("Error: could not setup operation: %s\n", err)
|
log.Printf("Error: could not setup operation: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exit if operation contains no actions
|
// Exit if operation contains no actions
|
||||||
@@ -363,28 +428,44 @@ func resolveCommand() {
|
|||||||
text, _ := reader.ReadString('\n')
|
text, _ := reader.ReadString('\n')
|
||||||
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
||||||
fmt.Println("Cancelling package update...")
|
fmt.Println("Cancelling package update...")
|
||||||
os.Exit(1)
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute operation
|
// Execute operation
|
||||||
err = operation.Execute(verbose, force)
|
err = operation.Execute(verbose, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not complete operation: %s\n", err)
|
log.Printf("Error: could not complete operation: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executing hooks
|
// Executing hooks
|
||||||
fmt.Println("Running hooks...")
|
fmt.Println("Running hooks...")
|
||||||
err = operation.RunHooks(verbose)
|
err = operation.RunHooks(verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not run hooks: %s\n", err)
|
log.Printf("Error: could not run hooks: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
case sync:
|
case sync:
|
||||||
// Check for required permissions
|
// Check for required permissions
|
||||||
if os.Getuid() != 0 {
|
if os.Getuid() != 0 {
|
||||||
log.Fatalf("Error: this subcommand needs to be run with superuser permissions")
|
log.Printf("Error: this subcommand needs to be run with superuser permissions")
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create BPM Lock file
|
||||||
|
fileLock, err := bpmlib.LockBPM(rootDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error: could not create BPM lock file: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fileLock.Unlock()
|
||||||
|
|
||||||
// Confirmation Prompt
|
// Confirmation Prompt
|
||||||
if !yesAll {
|
if !yesAll {
|
||||||
fmt.Printf("Are you sure you wish to sync all databases? [y\\N] ")
|
fmt.Printf("Are you sure you wish to sync all databases? [y\\N] ")
|
||||||
@@ -392,21 +473,26 @@ func resolveCommand() {
|
|||||||
text, _ := reader.ReadString('\n')
|
text, _ := reader.ReadString('\n')
|
||||||
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
||||||
fmt.Println("Cancelling database synchronization...")
|
fmt.Println("Cancelling database synchronization...")
|
||||||
os.Exit(1)
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync databases
|
// Sync databases
|
||||||
err := bpmlib.SyncDatabase(verbose)
|
err = bpmlib.SyncDatabase(verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not sync local database: %s\n", err)
|
log.Printf("Error: could not sync local database: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("All package databases synced successfully!")
|
fmt.Println("All package databases synced successfully!")
|
||||||
case remove:
|
case remove:
|
||||||
// Check for required permissions
|
// Check for required permissions
|
||||||
if os.Getuid() != 0 {
|
if os.Getuid() != 0 {
|
||||||
log.Fatalf("Error: this subcommand needs to be run with superuser permissions")
|
log.Printf("Error: this subcommand needs to be run with superuser permissions")
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(subcommandArgs) == 0 {
|
if len(subcommandArgs) == 0 {
|
||||||
@@ -414,18 +500,33 @@ func resolveCommand() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read local databases
|
// Create BPM Lock file
|
||||||
err := bpmlib.ReadLocalDatabaseFiles()
|
fileLock, err := bpmlib.LockBPM(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not read local databases: %s", err)
|
log.Printf("Error: could not create BPM lock file: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fileLock.Unlock()
|
||||||
|
|
||||||
|
// Read local databases
|
||||||
|
err = bpmlib.ReadLocalDatabaseFiles()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error: could not read local databases: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create remove operation
|
// Create remove operation
|
||||||
operation, err := bpmlib.RemovePackages(rootDir, removeUnused, doCleanup, subcommandArgs...)
|
operation, err := bpmlib.RemovePackages(rootDir, removeUnused, doCleanup, subcommandArgs...)
|
||||||
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.Fatalf("Error: %s", err)
|
log.Printf("Error: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Fatalf("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
|
||||||
@@ -444,46 +545,70 @@ func resolveCommand() {
|
|||||||
text, _ := reader.ReadString('\n')
|
text, _ := reader.ReadString('\n')
|
||||||
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
||||||
fmt.Println("Cancelling package removal...")
|
fmt.Println("Cancelling package removal...")
|
||||||
os.Exit(1)
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute operation
|
// Execute operation
|
||||||
err = operation.Execute(verbose, force)
|
err = operation.Execute(verbose, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not complete operation: %s\n", err)
|
log.Printf("Error: could not complete operation: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executing hooks
|
// Executing hooks
|
||||||
fmt.Println("Running hooks...")
|
fmt.Println("Running hooks...")
|
||||||
err = operation.RunHooks(verbose)
|
err = operation.RunHooks(verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not run hooks: %s\n", err)
|
log.Printf("Error: could not run hooks: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
case cleanup:
|
case cleanup:
|
||||||
// Check for required permissions
|
// Check for required permissions
|
||||||
if os.Getuid() != 0 {
|
if os.Getuid() != 0 {
|
||||||
log.Fatalf("Error: this subcommand needs to be run with superuser permissions")
|
log.Printf("Error: this subcommand needs to be run with superuser permissions")
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := bpmlib.CleanupCache(rootDir, cleanupCompilationFiles, cleanupCompiledPackages, cleanupFetchedPackages, verbose)
|
// Create BPM Lock file
|
||||||
|
fileLock, err := bpmlib.LockBPM(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not complete cache cleanup: %s", err)
|
log.Printf("Error: could not create BPM lock file: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fileLock.Unlock()
|
||||||
|
|
||||||
|
err = bpmlib.CleanupCache(rootDir, cleanupCompilationFiles, cleanupCompiledPackages, cleanupFetchedPackages, verbose)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error: could not complete cache cleanup: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if cleanupDependencies || cleanupMakeDependencies {
|
if cleanupDependencies || cleanupMakeDependencies {
|
||||||
// Read local databases
|
// Read local databases
|
||||||
err := bpmlib.ReadLocalDatabaseFiles()
|
err := bpmlib.ReadLocalDatabaseFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not read local databases: %s", err)
|
log.Printf("Error: could not read local databases: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create cleanup operation
|
// Create cleanup operation
|
||||||
operation, err := bpmlib.CleanupPackages(cleanupMakeDependencies, rootDir)
|
operation, err := bpmlib.CleanupPackages(cleanupMakeDependencies, rootDir)
|
||||||
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.Fatalf("Error: %s", err)
|
log.Printf("Error: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
log.Fatalf("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
|
||||||
@@ -502,21 +627,26 @@ func resolveCommand() {
|
|||||||
text, _ := reader.ReadString('\n')
|
text, _ := reader.ReadString('\n')
|
||||||
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" {
|
||||||
fmt.Println("Cancelling package removal...")
|
fmt.Println("Cancelling package removal...")
|
||||||
os.Exit(1)
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute operation
|
// Execute operation
|
||||||
err = operation.Execute(verbose, force)
|
err = operation.Execute(verbose, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not complete operation: %s\n", err)
|
log.Printf("Error: could not complete operation: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executing hooks
|
// Executing hooks
|
||||||
fmt.Println("Running hooks...")
|
fmt.Println("Running hooks...")
|
||||||
err = operation.RunHooks(verbose)
|
err = operation.RunHooks(verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not run hooks: %s\n", err)
|
log.Printf("Error: could not run hooks: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case file:
|
case file:
|
||||||
@@ -528,23 +658,33 @@ func resolveCommand() {
|
|||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
absFile, err := filepath.Abs(file)
|
absFile, err := filepath.Abs(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get absolute path of file (%s)\n", file)
|
log.Printf("Error: could not get absolute path of file (%s)\n", file)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
stat, err := os.Stat(absFile)
|
stat, err := os.Stat(absFile)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
log.Fatalf("Error: file (%s) does not exist!\n", absFile)
|
log.Printf("Error: file (%s) does not exist!\n", absFile)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
pkgs, err := bpmlib.GetInstalledPackages(rootDir)
|
pkgs, err := bpmlib.GetInstalledPackages(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get installed packages: %s\n", err.Error())
|
log.Printf("Error: could not get installed packages: %s\n", err.Error())
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.HasPrefix(absFile, rootDir) {
|
if !strings.HasPrefix(absFile, rootDir) {
|
||||||
log.Fatalf("Error: could not get path of file (%s) relative to root path", absFile)
|
log.Printf("Error: could not get path of file (%s) relative to root path", absFile)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
absFile, err = filepath.Rel(rootDir, absFile)
|
absFile, err = filepath.Rel(rootDir, absFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get path of file (%s) relative to root path", absFile)
|
log.Printf("Error: could not get path of file (%s) relative to root path", absFile)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
absFile = strings.TrimPrefix(absFile, "/")
|
absFile = strings.TrimPrefix(absFile, "/")
|
||||||
if stat.IsDir() {
|
if stat.IsDir() {
|
||||||
@@ -577,24 +717,32 @@ func resolveCommand() {
|
|||||||
// Read local databases
|
// Read local databases
|
||||||
err := bpmlib.ReadLocalDatabaseFiles()
|
err := bpmlib.ReadLocalDatabaseFiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not read local databases: %s", err)
|
log.Printf("Error: could not read local databases: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile packages
|
// Compile packages
|
||||||
for _, sourcePackage := range subcommandArgs {
|
for _, sourcePackage := range subcommandArgs {
|
||||||
if _, err := os.Stat(sourcePackage); os.IsNotExist(err) {
|
if _, err := os.Stat(sourcePackage); os.IsNotExist(err) {
|
||||||
log.Fatalf("Error: file (%s) does not exist!", sourcePackage)
|
log.Printf("Error: file (%s) does not exist!", sourcePackage)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read archive
|
// Read archive
|
||||||
bpmpkg, err := bpmlib.ReadPackage(sourcePackage)
|
bpmpkg, err := bpmlib.ReadPackage(sourcePackage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Could not read package (%s): %s", sourcePackage, err)
|
log.Printf("Could not read package (%s): %s", sourcePackage, err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure archive is source BPM package
|
// Ensure archive is source BPM package
|
||||||
if bpmpkg.PkgInfo.Type != "source" {
|
if bpmpkg.PkgInfo.Type != "source" {
|
||||||
log.Fatalf("Error: cannot compile a non-source package!")
|
log.Printf("Error: cannot compile a non-source package!")
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get direct runtime and make dependencies
|
// Get direct runtime and make dependencies
|
||||||
@@ -609,7 +757,9 @@ func resolveCommand() {
|
|||||||
unmetDepends := slices.Clone(totalDepends)
|
unmetDepends := slices.Clone(totalDepends)
|
||||||
installedPackages, err := bpmlib.GetInstalledPackages("/")
|
installedPackages, err := bpmlib.GetInstalledPackages("/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get installed packages: %s\n", err)
|
log.Printf("Error: could not get installed packages: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
for i := len(unmetDepends) - 1; i >= 0; i-- {
|
for i := len(unmetDepends) - 1; i >= 0; i-- {
|
||||||
if slices.Contains(installedPackages, unmetDepends[i]) {
|
if slices.Contains(installedPackages, unmetDepends[i]) {
|
||||||
@@ -624,7 +774,9 @@ func resolveCommand() {
|
|||||||
// Get path to current executable
|
// Get path to current executable
|
||||||
executable, err := os.Executable()
|
executable, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get path to executable: %s\n", err)
|
log.Printf("Error: could not get path to executable: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run 'bpm install' using the set privilege escalator command
|
// Run 'bpm install' using the set privilege escalator command
|
||||||
@@ -642,25 +794,33 @@ func resolveCommand() {
|
|||||||
}
|
}
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: dependency installation command failed: %s\n", err)
|
log.Printf("Error: dependency installation command failed: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Ensure the required dependencies are installed
|
// Ensure the required dependencies are installed
|
||||||
if len(unmetDepends) != 0 {
|
if len(unmetDepends) != 0 {
|
||||||
log.Fatalf("Error: could not resolve dependencies: the following dependencies were not found in any databases: " + strings.Join(unmetDepends, ", "))
|
log.Printf("Error: could not resolve dependencies: the following dependencies were not found in any databases: " + strings.Join(unmetDepends, ", "))
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current working directory
|
// Get current working directory
|
||||||
workdir, err := os.Getwd()
|
workdir, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get working directory: %s", err)
|
log.Printf("Error: could not get working directory: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get user home directory
|
// Get user home directory
|
||||||
homedir, err := os.UserHomeDir()
|
homedir, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get user home directory: %s", err)
|
log.Printf("Error: could not get user home directory: %s", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trim output directory
|
// Trim output directory
|
||||||
@@ -690,19 +850,35 @@ func resolveCommand() {
|
|||||||
// Ensure output directory exists and is a directory
|
// Ensure output directory exists and is a directory
|
||||||
stat, err := os.Stat(outputDirectory)
|
stat, err := os.Stat(outputDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not stat output directory (%s): %s", outputDirectory, err)
|
log.Printf("Error: could not stat output directory (%s): %s", outputDirectory, err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if !stat.IsDir() {
|
if !stat.IsDir() {
|
||||||
log.Fatalf("Error: output directory (%s) is not a directory", outputDirectory)
|
log.Printf("Error: output directory (%s) is not a directory", outputDirectory)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
outputBpmPackages, err := bpmlib.CompileSourcePackage(sourcePackage, outputDirectory, skipChecks)
|
outputBpmPackages, err := bpmlib.CompileSourcePackage(sourcePackage, outputDirectory, skipChecks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not compile source package (%s): %s", sourcePackage, err)
|
log.Printf("Error: could not compile source package (%s): %s", sourcePackage, err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range outputBpmPackages {
|
for k, v := range outputBpmPackages {
|
||||||
fmt.Printf("Package (%s) was successfully compiled! Binary package generated at: %s\n", k, v)
|
if outputFd < 0 {
|
||||||
|
fmt.Printf("Package (%s) was successfully compiled! Binary package generated at: %s\n", k, v)
|
||||||
|
} else {
|
||||||
|
f := os.NewFile(uintptr(outputFd), "output_file_descrptor")
|
||||||
|
defer f.Close()
|
||||||
|
if f == nil {
|
||||||
|
log.Printf("Warning: invalid file descriptor: %d", outputFd)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fmt.Fprintln(f, v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove unused packages
|
// Remove unused packages
|
||||||
@@ -710,7 +886,9 @@ func resolveCommand() {
|
|||||||
// Get path to current executable
|
// Get path to current executable
|
||||||
executable, err := os.Executable()
|
executable, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not get path to executable: %s\n", err)
|
log.Printf("Error: could not get path to executable: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run 'bpm cleanup' using the set privilege escalator command
|
// Run 'bpm cleanup' using the set privilege escalator command
|
||||||
@@ -726,7 +904,9 @@ func resolveCommand() {
|
|||||||
}
|
}
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: dependency cleanup command failed: %s\n", err)
|
log.Printf("Error: dependency cleanup command failed: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -793,6 +973,7 @@ func printHelp() {
|
|||||||
fmt.Println(" -s skips the check function in source.sh scripts")
|
fmt.Println(" -s skips the check function in source.sh scripts")
|
||||||
fmt.Println(" -o sets output directory")
|
fmt.Println(" -o sets output directory")
|
||||||
fmt.Println(" -y skips the confirmation prompt")
|
fmt.Println(" -y skips the confirmation prompt")
|
||||||
|
fmt.Println(" --fd=<file descriptor> Set the file descriptor output package names will be written to")
|
||||||
|
|
||||||
fmt.Println("\033[1m----------------\033[0m")
|
fmt.Println("\033[1m----------------\033[0m")
|
||||||
}
|
}
|
||||||
@@ -862,6 +1043,7 @@ func resolveFlags() {
|
|||||||
compileFlagSet.BoolVar(&installSrcPkgDepends, "d", false, "Install required dependencies for package compilation")
|
compileFlagSet.BoolVar(&installSrcPkgDepends, "d", false, "Install required dependencies for package compilation")
|
||||||
compileFlagSet.BoolVar(&skipChecks, "s", false, "Skip the check function in source.sh scripts")
|
compileFlagSet.BoolVar(&skipChecks, "s", false, "Skip the check function in source.sh scripts")
|
||||||
compileFlagSet.StringVar(&outputDirectory, "o", "", "Set output directory")
|
compileFlagSet.StringVar(&outputDirectory, "o", "", "Set output directory")
|
||||||
|
compileFlagSet.IntVar(&outputFd, "fd", -1, "Set the file descriptor output package names will be written to")
|
||||||
compileFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing")
|
compileFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing")
|
||||||
compileFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts")
|
compileFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts")
|
||||||
compileFlagSet.Usage = printHelp
|
compileFlagSet.Usage = printHelp
|
||||||
|
|||||||
+188
-54
@@ -1,15 +1,20 @@
|
|||||||
package bpmlib
|
package bpmlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/drone/envsubst"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -31,12 +36,6 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks bo
|
|||||||
return nil, errors.New("cannot compile a non-source package")
|
return nil, errors.New("cannot compile a non-source package")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read compilation options file in current directory
|
|
||||||
compilationOptions, err := readCompilationOptionsFile()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get HOME directory
|
// Get HOME directory
|
||||||
homeDir, err := os.UserHomeDir()
|
homeDir, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -122,6 +121,12 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks bo
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Download files
|
||||||
|
err = downloadPackageFiles(bpmpkg.PkgInfo, tempDirectory)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Setup environment for commands
|
// Setup environment for commands
|
||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
env = append(env, "HOME="+tempDirectory)
|
env = append(env, "HOME="+tempDirectory)
|
||||||
@@ -131,12 +136,7 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks bo
|
|||||||
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))
|
||||||
// Check for architecture override in compilation options
|
env = append(env, "BPM_PKG_ARCH="+bpmpkg.PkgInfo.OutputArch)
|
||||||
if val, ok := compilationOptions["ARCH"]; ok {
|
|
||||||
env = append(env, "BPM_PKG_ARCH="+val)
|
|
||||||
} else {
|
|
||||||
env = append(env, "BPM_PKG_ARCH="+GetArch())
|
|
||||||
}
|
|
||||||
env = append(env, CompilationBPMConfig.CompilationEnvironment...)
|
env = append(env, CompilationBPMConfig.CompilationEnvironment...)
|
||||||
|
|
||||||
// Execute prepare and build functions in source.sh script
|
// Execute prepare and build functions in source.sh script
|
||||||
@@ -259,14 +259,12 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks bo
|
|||||||
pkgInfo.Type = "binary"
|
pkgInfo.Type = "binary"
|
||||||
|
|
||||||
// Set package architecture
|
// Set package architecture
|
||||||
if val, ok := compilationOptions["ARCH"]; ok {
|
pkgInfo.Arch = pkg.OutputArch
|
||||||
pkgInfo.Arch = val
|
pkgInfo.OutputArch = ""
|
||||||
} else {
|
|
||||||
pkgInfo.Arch = GetArch()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove split package field
|
// Remove split package and downloads fields
|
||||||
pkgInfo.SplitPackages = nil
|
pkgInfo.SplitPackages = nil
|
||||||
|
pkgInfo.Downloads = nil
|
||||||
|
|
||||||
// Marshal package info
|
// Marshal package info
|
||||||
pkgInfoBytes, err := yaml.Marshal(pkgInfo)
|
pkgInfoBytes, err := yaml.Marshal(pkgInfo)
|
||||||
@@ -338,46 +336,182 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks bo
|
|||||||
return outputBpmPackages, nil
|
return outputBpmPackages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readCompilationOptionsFile() (options map[string]string, err error) {
|
func downloadPackageFiles(pkgInfo *PackageInfo, tempDirectory string) error {
|
||||||
// Initialize options map
|
for _, download := range pkgInfo.Downloads {
|
||||||
options = make(map[string]string)
|
// Replace variables
|
||||||
|
replaceVars := func(s string) string {
|
||||||
// Check if file compilation options file exists
|
switch s {
|
||||||
stat, err := os.Stat(".compilation-options")
|
case "BPM_PKG_VERSION":
|
||||||
if err != nil {
|
return pkgInfo.Version
|
||||||
return nil, nil
|
case "BPM_PKG_NAME":
|
||||||
}
|
return pkgInfo.Name
|
||||||
|
case "BPM_SOURCE":
|
||||||
// Ensure it is a regular file
|
return path.Join(tempDirectory, "source/")
|
||||||
if !stat.Mode().IsRegular() {
|
default:
|
||||||
return nil, fmt.Errorf("%s is not a regular file", stat.Name())
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read file data
|
|
||||||
data, err := os.ReadFile(stat.Name())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, line := range strings.Split(string(data), "\n") {
|
|
||||||
// Trim line
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
|
|
||||||
// Skip empty lines
|
|
||||||
if line == "" {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split line
|
downloadUrl, err := envsubst.Eval(strings.TrimSpace(download.Url), replaceVars)
|
||||||
split := strings.SplitN(line, "=", 2)
|
if err != nil {
|
||||||
|
return err
|
||||||
// Throw error if line isn't valid
|
}
|
||||||
if len(split) < 2 {
|
extractTo, err := envsubst.Eval(strings.TrimSpace(download.ExtractTo), replaceVars)
|
||||||
return nil, fmt.Errorf("invalid line in compilation-options file: '%s'", line)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cloneTo, err := envsubst.Eval(strings.TrimSpace(download.CloneTo), replaceVars)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
options[split[0]] = split[1]
|
// Make relative paths absolute
|
||||||
|
if extractTo != "" && extractTo[0] != '/' {
|
||||||
|
extractTo = path.Join(tempDirectory, extractTo)
|
||||||
|
}
|
||||||
|
// Make relative paths absolute
|
||||||
|
if cloneTo != "" && cloneTo[0] != '/' {
|
||||||
|
cloneTo = path.Join(tempDirectory, cloneTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch download.Type {
|
||||||
|
case "", "file":
|
||||||
|
filepath := path.Join(tempDirectory, path.Base(downloadUrl))
|
||||||
|
if download.Filepath != "" && download.Filepath[0] != '/' {
|
||||||
|
filepath = path.Join(tempDirectory, download.Filepath)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := downloadFile(downloadUrl, filepath, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if download.Checksum != "skip" {
|
||||||
|
f, err := os.Open(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
h := sha256.New()
|
||||||
|
_, err = io.Copy(h, f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if hex.EncodeToString(h.Sum(nil)) != download.Checksum {
|
||||||
|
fmt.Printf("Downloaded file checksum: %x\n", h.Sum(nil))
|
||||||
|
return fmt.Errorf("downloaded file checksums did not match")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("Skipping checksum checking...")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !download.NoExtract && (strings.Contains(filepath, ".tar") || strings.HasSuffix(filepath, ".tgz")) {
|
||||||
|
cmd := exec.Command("tar", "xvf", filepath, "--strip-components="+strconv.Itoa(download.ExtractStripComponents))
|
||||||
|
cmd.Dir = tempDirectory
|
||||||
|
if extractTo != "" {
|
||||||
|
err := os.MkdirAll(extractTo, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd.Args = append(cmd.Args, "-C", extractTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if !download.NoExtract && strings.HasSuffix(filepath, ".zip") {
|
||||||
|
cmd := exec.Command("unzip", filepath)
|
||||||
|
if extractTo != "" {
|
||||||
|
err := os.MkdirAll(extractTo, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd.Args = append(cmd.Args, "-d", extractTo)
|
||||||
|
} else {
|
||||||
|
err := os.Mkdir(path.Join(tempDirectory, strings.TrimSuffix(path.Base(filepath), ".zip")), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Args = append(cmd.Args, "-d", path.Join(tempDirectory, strings.TrimSuffix(path.Base(filepath), ".zip")))
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "git":
|
||||||
|
// Replace variables in git branch
|
||||||
|
gitBranch := download.GitBranch
|
||||||
|
gitBranch, err := envsubst.Eval(gitBranch, func(s string) string {
|
||||||
|
switch s {
|
||||||
|
case "BPM_PKG_VERSION":
|
||||||
|
return pkgInfo.Version
|
||||||
|
case "BPM_PKG_NAME":
|
||||||
|
return pkgInfo.Name
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command("git", "clone", "--depth=1", downloadUrl)
|
||||||
|
cmd.Dir = tempDirectory
|
||||||
|
if gitBranch != "" {
|
||||||
|
cmd.Args = slices.Insert(cmd.Args, len(cmd.Args)-1, "--branch="+gitBranch)
|
||||||
|
}
|
||||||
|
if cloneTo != "" {
|
||||||
|
err := os.MkdirAll(cloneTo, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cmd.Args = append(cmd.Args, cloneTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if download.Checksum != "skip" {
|
||||||
|
cmd := exec.Command("git", "rev-parse", "HEAD")
|
||||||
|
if cloneTo != "" {
|
||||||
|
cmd.Dir = cloneTo
|
||||||
|
} else {
|
||||||
|
cmd.Dir = path.Join(tempDirectory, strings.TrimSuffix(path.Base(downloadUrl), ".git"))
|
||||||
|
}
|
||||||
|
|
||||||
|
branchChecksum, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.TrimSpace(string(branchChecksum)) != download.Checksum {
|
||||||
|
fmt.Printf("Git branch checksum: %s\n", strings.TrimSpace(string(branchChecksum)))
|
||||||
|
return fmt.Errorf("Cloned git repository checksum did not match")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("Skipping checksum checking...")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown download type (%s)", download.Type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return options, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type MainBPMConfigStruct struct {
|
type MainBPMConfigStruct struct {
|
||||||
IgnorePackages []string `yaml:"ignore_packages"`
|
IgnorePackages []string `yaml:"ignore_packages"`
|
||||||
CleanupMakeDependencies bool `yaml:"cleanup_make_dependencies"`
|
CleanupMakeDependencies bool `yaml:"cleanup_make_dependencies"`
|
||||||
Databases []*BPMDatabase `yaml:"databases"`
|
Databases []configDatabase `yaml:"databases"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type configDatabase struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Source string `yaml:"source"`
|
||||||
|
Disabled *bool `yaml:"disabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompilationBPMConfigStruct struct {
|
type CompilationBPMConfigStruct struct {
|
||||||
|
|||||||
+50
-83
@@ -3,8 +3,6 @@ package bpmlib
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@@ -14,27 +12,28 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type BPMDatabase struct {
|
type BPMDatabase struct {
|
||||||
Name string `yaml:"name"`
|
DatabaseVersion int `yaml:"database_version"`
|
||||||
Source string `yaml:"source"`
|
Entries map[string]*BPMDatabaseEntry `yaml:"entries"`
|
||||||
Disabled *bool `yaml:"disabled"`
|
|
||||||
Entries map[string]*BPMDatabaseEntry
|
|
||||||
VirtualPackages map[string][]string
|
VirtualPackages map[string][]string
|
||||||
|
Source string
|
||||||
}
|
}
|
||||||
|
|
||||||
type BPMDatabaseEntry struct {
|
type BPMDatabaseEntry struct {
|
||||||
Info *PackageInfo `yaml:"info"`
|
Info *PackageInfo `yaml:"info"`
|
||||||
Download string `yaml:"download"`
|
Filepath string `yaml:"filepath"`
|
||||||
DownloadSize uint64 `yaml:"download_size"`
|
DownloadSize uint64 `yaml:"download_size"`
|
||||||
InstalledSize uint64 `yaml:"installed_size"`
|
InstalledSize uint64 `yaml:"installed_size"`
|
||||||
Database *BPMDatabase
|
Database *BPMDatabase
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var BPMDatabases = make(map[string]*BPMDatabase)
|
||||||
|
|
||||||
func (db *BPMDatabase) ContainsPackage(pkg string) bool {
|
func (db *BPMDatabase) ContainsPackage(pkg string) bool {
|
||||||
_, ok := db.Entries[pkg]
|
_, ok := db.Entries[pkg]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *BPMDatabase) ReadLocalDatabase() error {
|
func (db *configDatabase) ReadLocalDatabase() error {
|
||||||
dbFile := "/var/lib/bpm/databases/" + db.Name + ".bpmdb"
|
dbFile := "/var/lib/bpm/databases/" + db.Name + ".bpmdb"
|
||||||
if _, err := os.Stat(dbFile); err != nil {
|
if _, err := os.Stat(dbFile); err != nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -45,37 +44,23 @@ func (db *BPMDatabase) ReadLocalDatabase() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := string(bytes)
|
// Unmarshal yaml
|
||||||
for _, b := range strings.Split(data, "---") {
|
database := &BPMDatabase{}
|
||||||
entry := BPMDatabaseEntry{
|
err = yaml.Unmarshal(bytes, database)
|
||||||
Info: &PackageInfo{
|
if err != nil {
|
||||||
Name: "",
|
return err
|
||||||
Description: "",
|
}
|
||||||
Version: "",
|
|
||||||
Revision: 1,
|
// Initialize struct values
|
||||||
Url: "",
|
database.VirtualPackages = make(map[string][]string)
|
||||||
License: "",
|
database.Source = db.Source
|
||||||
Arch: "",
|
|
||||||
Type: "",
|
entriesToRemove := make([]string, 0)
|
||||||
Keep: make([]string, 0),
|
for entryName, entry := range database.Entries {
|
||||||
Depends: make([]string, 0),
|
entry.Database = database
|
||||||
MakeDepends: make([]string, 0),
|
|
||||||
OptionalDepends: make([]string, 0),
|
|
||||||
Conflicts: make([]string, 0),
|
|
||||||
Provides: make([]string, 0),
|
|
||||||
},
|
|
||||||
Download: "",
|
|
||||||
DownloadSize: 0,
|
|
||||||
InstalledSize: 0,
|
|
||||||
Database: db,
|
|
||||||
}
|
|
||||||
err := yaml.Unmarshal([]byte(b), &entry)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create database entries
|
|
||||||
if entry.Info.IsSplitPackage() {
|
if entry.Info.IsSplitPackage() {
|
||||||
|
// 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
|
||||||
splitPkgJson, err := yaml.Marshal(splitPkg)
|
splitPkgJson, err := yaml.Marshal(splitPkg)
|
||||||
@@ -101,35 +86,41 @@ func (db *BPMDatabase) ReadLocalDatabase() error {
|
|||||||
splitPkgClone.Url = entry.Info.Url
|
splitPkgClone.Url = entry.Info.Url
|
||||||
|
|
||||||
// Create entry for split package
|
// Create entry for split package
|
||||||
db.Entries[splitPkg.Name] = &BPMDatabaseEntry{
|
database.Entries[splitPkg.Name] = &BPMDatabaseEntry{
|
||||||
Info: &splitPkgClone,
|
Info: &splitPkgClone,
|
||||||
Download: entry.Download,
|
Filepath: entry.Filepath,
|
||||||
DownloadSize: entry.DownloadSize,
|
DownloadSize: entry.DownloadSize,
|
||||||
InstalledSize: 0,
|
InstalledSize: 0,
|
||||||
Database: db,
|
Database: database,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add virtual packages to database
|
// Add virtual packages to database
|
||||||
for _, p := range splitPkg.Provides {
|
for _, p := range splitPkg.Provides {
|
||||||
db.VirtualPackages[p] = append(db.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 {
|
||||||
// Create entry for package
|
|
||||||
db.Entries[entry.Info.Name] = &entry
|
|
||||||
|
|
||||||
// Add virtual packages to database
|
// Add virtual packages to database
|
||||||
for _, p := range entry.Info.Provides {
|
for _, p := range entry.Info.Provides {
|
||||||
db.VirtualPackages[p] = append(db.VirtualPackages[p], entry.Info.Name)
|
database.VirtualPackages[p] = append(database.VirtualPackages[p], entry.Info.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove entries
|
||||||
|
for _, entryName := range entriesToRemove {
|
||||||
|
delete(database.Entries, entryName)
|
||||||
|
}
|
||||||
|
|
||||||
|
BPMDatabases[db.Name] = database
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *BPMDatabase) SyncLocalDatabaseFile() error {
|
func (db *configDatabase) SyncLocalDatabaseFile() error {
|
||||||
dbFile := "/var/lib/bpm/databases/" + db.Name + ".bpmdb"
|
dbFile := "/var/lib/bpm/databases/" + db.Name + ".bpmdb"
|
||||||
|
|
||||||
// Get URL to database
|
// Get URL to database
|
||||||
@@ -139,14 +130,10 @@ func (db *BPMDatabase) SyncLocalDatabaseFile() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve data from URL
|
// Retrieve data from URL
|
||||||
resp, err := http.Get(u)
|
buffer, err := retrieveUrlData(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 database
|
// Unmarshal data to ensure it is a valid BPM database
|
||||||
err = yaml.Unmarshal(buffer, &BPMDatabase{})
|
err = yaml.Unmarshal(buffer, &BPMDatabase{})
|
||||||
@@ -174,10 +161,6 @@ func (db *BPMDatabase) SyncLocalDatabaseFile() error {
|
|||||||
|
|
||||||
func ReadLocalDatabaseFiles() (err error) {
|
func ReadLocalDatabaseFiles() (err error) {
|
||||||
for _, db := range MainBPMConfig.Databases {
|
for _, db := range MainBPMConfig.Databases {
|
||||||
// Initialize struct values
|
|
||||||
db.Entries = make(map[string]*BPMDatabaseEntry)
|
|
||||||
db.VirtualPackages = make(map[string][]string)
|
|
||||||
|
|
||||||
// Read database
|
// Read database
|
||||||
err = db.ReadLocalDatabase()
|
err = db.ReadLocalDatabase()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -188,15 +171,6 @@ func ReadLocalDatabaseFiles() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDatabase(name string) *BPMDatabase {
|
|
||||||
for _, db := range MainBPMConfig.Databases {
|
|
||||||
if db.Name == name {
|
|
||||||
return db
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDatabaseEntry(str string) (*BPMDatabaseEntry, *BPMDatabase, error) {
|
func GetDatabaseEntry(str string) (*BPMDatabaseEntry, *BPMDatabase, error) {
|
||||||
split := strings.Split(str, "/")
|
split := strings.Split(str, "/")
|
||||||
if len(split) == 1 {
|
if len(split) == 1 {
|
||||||
@@ -204,7 +178,7 @@ func GetDatabaseEntry(str string) (*BPMDatabaseEntry, *BPMDatabase, error) {
|
|||||||
if pkgName == "" {
|
if pkgName == "" {
|
||||||
return nil, nil, errors.New("could not find database entry for this package")
|
return nil, nil, errors.New("could not find database entry for this package")
|
||||||
}
|
}
|
||||||
for _, db := range MainBPMConfig.Databases {
|
for _, db := range BPMDatabases {
|
||||||
if db.ContainsPackage(pkgName) {
|
if db.ContainsPackage(pkgName) {
|
||||||
return db.Entries[pkgName], db, nil
|
return db.Entries[pkgName], db, nil
|
||||||
}
|
}
|
||||||
@@ -216,7 +190,7 @@ func GetDatabaseEntry(str string) (*BPMDatabaseEntry, *BPMDatabase, error) {
|
|||||||
if dbName == "" || pkgName == "" {
|
if dbName == "" || pkgName == "" {
|
||||||
return nil, nil, errors.New("could not find database entry for this package")
|
return nil, nil, errors.New("could not find database entry for this package")
|
||||||
}
|
}
|
||||||
db := GetDatabase(dbName)
|
db := BPMDatabases[dbName]
|
||||||
if db == nil || !db.ContainsPackage(pkgName) {
|
if db == nil || !db.ContainsPackage(pkgName) {
|
||||||
return nil, nil, errors.New("could not find database entry for this package")
|
return nil, nil, errors.New("could not find database entry for this package")
|
||||||
}
|
}
|
||||||
@@ -227,7 +201,7 @@ func GetDatabaseEntry(str string) (*BPMDatabaseEntry, *BPMDatabase, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func FindReplacement(pkg string) *BPMDatabaseEntry {
|
func FindReplacement(pkg string) *BPMDatabaseEntry {
|
||||||
for _, db := range MainBPMConfig.Databases {
|
for _, db := range BPMDatabases {
|
||||||
for _, entry := range db.Entries {
|
for _, entry := range db.Entries {
|
||||||
for _, replaced := range entry.Info.Replaces {
|
for _, replaced := range entry.Info.Replaces {
|
||||||
if replaced == pkg {
|
if replaced == pkg {
|
||||||
@@ -241,7 +215,7 @@ func FindReplacement(pkg string) *BPMDatabaseEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ResolveVirtualPackage(vpkg string) *BPMDatabaseEntry {
|
func ResolveVirtualPackage(vpkg string) *BPMDatabaseEntry {
|
||||||
for _, db := range MainBPMConfig.Databases {
|
for _, db := range BPMDatabases {
|
||||||
if v, ok := db.VirtualPackages[vpkg]; ok {
|
if v, ok := db.VirtualPackages[vpkg]; ok {
|
||||||
for _, pkg := range v {
|
for _, pkg := range v {
|
||||||
return db.Entries[pkg]
|
return db.Entries[pkg]
|
||||||
@@ -253,30 +227,23 @@ func ResolveVirtualPackage(vpkg string) *BPMDatabaseEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *BPMDatabase) FetchPackage(pkg string) (string, error) {
|
func (db *BPMDatabase) FetchPackage(pkg string) (string, error) {
|
||||||
|
// Check if package exists in database
|
||||||
if !db.ContainsPackage(pkg) {
|
if !db.ContainsPackage(pkg) {
|
||||||
return "", errors.New("could not fetch package '" + pkg + "'")
|
return "", errors.New("could not fetch package '" + pkg + "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get package url from database
|
||||||
entry := db.Entries[pkg]
|
entry := db.Entries[pkg]
|
||||||
URL, err := url.JoinPath(db.Source, entry.Download)
|
u, err := url.JoinPath(db.Source, entry.Filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
resp, err := http.Get(URL)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
err = os.MkdirAll("/var/cache/bpm/fetched/", 0755)
|
// Download package from url
|
||||||
|
err = downloadFile(u, path.Join("/var/cache/bpm/fetched/", path.Base(entry.Filepath)), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
out, err := os.Create("/var/cache/bpm/fetched/" + path.Base(entry.Download))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(out, resp.Body)
|
return path.Join("/var/cache/bpm/fetched/", path.Base(entry.Filepath)), nil
|
||||||
return "/var/cache/bpm/fetched/" + path.Base(entry.Download), nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,14 +164,14 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
if rootDir != "/" {
|
if rootDir != "/" {
|
||||||
sourcePackages := make([]string, 0)
|
sourcePackages := make([]string, 0)
|
||||||
for _, action := range operation.Actions {
|
for _, action := range operation.Actions {
|
||||||
switch action.(type) {
|
switch action := action.(type) {
|
||||||
case *InstallPackageAction:
|
case *InstallPackageAction:
|
||||||
if action.(*InstallPackageAction).BpmPackage.PkgInfo.Type == "source" {
|
if action.BpmPackage.PkgInfo.Type == "source" {
|
||||||
sourcePackages = append(sourcePackages, action.(*InstallPackageAction).BpmPackage.PkgInfo.Name)
|
sourcePackages = append(sourcePackages, action.BpmPackage.PkgInfo.Name)
|
||||||
}
|
}
|
||||||
case *FetchPackageAction:
|
case *FetchPackageAction:
|
||||||
if action.(*FetchPackageAction).DatabaseEntry.Info.Type == "source" {
|
if action.DatabaseEntry.Info.Type == "source" {
|
||||||
sourcePackages = append(sourcePackages, action.(*FetchPackageAction).DatabaseEntry.Info.Name)
|
sourcePackages = append(sourcePackages, action.DatabaseEntry.Info.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ module git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib
|
|||||||
go 1.23
|
go 1.23
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/drone/envsubst v1.0.3
|
||||||
github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f
|
github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
github.com/drone/envsubst v1.0.3 h1:PCIBwNDYjs50AsLZPYdfhSATKaRg/FJmDc2D6+C2x8g=
|
||||||
|
github.com/drone/envsubst v1.0.3/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
|
||||||
|
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
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 h1:xt29M2T6STgldg+WEP51gGePQCsQvklmP2eIhPIBK3g=
|
||||||
github.com/knqyf263/go-rpm-version v0.0.0-20240918084003-2afd7dc6a38f/go.mod h1:i4sF0l1fFnY1aiw08QQSwVAFxHEm311Me3WsU/X7nL0=
|
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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package bpmlib
|
package bpmlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@@ -169,14 +168,11 @@ func GetAllPackageFiles(rootDir string, excludePackages ...string) (map[string][
|
|||||||
}
|
}
|
||||||
bpmpkg := GetPackage(pkgName, rootDir)
|
bpmpkg := GetPackage(pkgName, rootDir)
|
||||||
if bpmpkg == nil {
|
if bpmpkg == nil {
|
||||||
return nil, errors.New(fmt.Sprintf("could not get BPM package (%s)", pkgName))
|
return nil, fmt.Errorf("could not get BPM package (%s)", pkgName)
|
||||||
}
|
}
|
||||||
for _, entry := range bpmpkg.PkgFiles {
|
for _, entry := range bpmpkg.PkgFiles {
|
||||||
if _, ok := ret[entry.Path]; ok {
|
ret[entry.Path] = append(ret[entry.Path], bpmpkg)
|
||||||
ret[entry.Path] = append(ret[entry.Path], bpmpkg)
|
|
||||||
} else {
|
|
||||||
ret[entry.Path] = []*BPMPackage{bpmpkg}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package bpmlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func retrieveUrlData(u string) ([]byte, error) {
|
||||||
|
resp, err := http.Get(u)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// Load data into byte buffer
|
||||||
|
buffer, err := io.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
return buffer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadFile(u, filepath string, perm os.FileMode) error {
|
||||||
|
if strings.HasSuffix(filepath, "/") {
|
||||||
|
return fmt.Errorf("Filepath must not end in '/'")
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := retrieveUrlData(u)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create parent directories
|
||||||
|
err = os.MkdirAll(path.Dir(filepath), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create file
|
||||||
|
file, err := os.Create(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// Copy data
|
||||||
|
_, err = file.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set file permissions
|
||||||
|
err = file.Chmod(perm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -448,7 +448,7 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
|
|||||||
var bpmpkg *BPMPackage
|
var bpmpkg *BPMPackage
|
||||||
|
|
||||||
// Check if package has already been fetched from download link
|
// Check if package has already been fetched from download link
|
||||||
if _, ok := fetchedPackages[entry.Download]; !ok {
|
if _, ok := fetchedPackages[entry.Filepath]; !ok {
|
||||||
// Fetch package from database
|
// Fetch package from database
|
||||||
fetchedPackage, err := entry.Database.FetchPackage(entry.Info.Name)
|
fetchedPackage, err := entry.Database.FetchPackage(entry.Info.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -462,12 +462,12 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add fetched package to map
|
// Add fetched package to map
|
||||||
fetchedPackages[entry.Download] = fetchedPackage
|
fetchedPackages[entry.Filepath] = fetchedPackage
|
||||||
|
|
||||||
fmt.Printf("Package (%s) was successfully fetched!\n", entry.Info.Name)
|
fmt.Printf("Package (%s) was successfully fetched!\n", entry.Info.Name)
|
||||||
} else {
|
} else {
|
||||||
// Read fetched package
|
// Read fetched package
|
||||||
bpmpkg, err = ReadPackage(fetchedPackages[entry.Download])
|
bpmpkg, err = ReadPackage(fetchedPackages[entry.Filepath])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not read package (%s): %s\n", entry.Info.Name, err)
|
return fmt.Errorf("could not read package (%s): %s\n", entry.Info.Name, err)
|
||||||
}
|
}
|
||||||
@@ -477,14 +477,14 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
|
|||||||
|
|
||||||
if bpmpkg.PkgInfo.IsSplitPackage() {
|
if bpmpkg.PkgInfo.IsSplitPackage() {
|
||||||
operation.Actions[i] = &InstallPackageAction{
|
operation.Actions[i] = &InstallPackageAction{
|
||||||
File: fetchedPackages[entry.Download],
|
File: fetchedPackages[entry.Filepath],
|
||||||
InstallationReason: action.(*FetchPackageAction).InstallationReason,
|
InstallationReason: action.(*FetchPackageAction).InstallationReason,
|
||||||
BpmPackage: bpmpkg,
|
BpmPackage: bpmpkg,
|
||||||
SplitPackageToInstall: entry.Info.Name,
|
SplitPackageToInstall: entry.Info.Name,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
operation.Actions[i] = &InstallPackageAction{
|
operation.Actions[i] = &InstallPackageAction{
|
||||||
File: fetchedPackages[entry.Download],
|
File: fetchedPackages[entry.Filepath],
|
||||||
InstallationReason: action.(*FetchPackageAction).InstallationReason,
|
InstallationReason: action.(*FetchPackageAction).InstallationReason,
|
||||||
BpmPackage: bpmpkg,
|
BpmPackage: bpmpkg,
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-40
@@ -26,22 +26,41 @@ type BPMPackage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PackageInfo struct {
|
type PackageInfo struct {
|
||||||
Name string `yaml:"name,omitempty"`
|
Name string `yaml:"name"`
|
||||||
Description string `yaml:"description,omitempty"`
|
Description string `yaml:"description,omitempty"`
|
||||||
Version string `yaml:"version,omitempty"`
|
Version string `yaml:"version,omitempty"`
|
||||||
Revision int `yaml:"revision,omitempty"`
|
Revision int `yaml:"revision,omitempty"`
|
||||||
Url string `yaml:"url,omitempty"`
|
Url string `yaml:"url,omitempty"`
|
||||||
License string `yaml:"license,omitempty"`
|
License string `yaml:"license,omitempty"`
|
||||||
Arch string `yaml:"architecture,omitempty"`
|
Arch string `yaml:"architecture,omitempty"`
|
||||||
Type string `yaml:"type,omitempty"`
|
OutputArch string `yaml:"output_architecture,omitempty"`
|
||||||
Keep []string `yaml:"keep,omitempty"`
|
Type string `yaml:"type,omitempty"`
|
||||||
Depends []string `yaml:"depends,omitempty"`
|
Keep []string `yaml:"keep,omitempty"`
|
||||||
MakeDepends []string `yaml:"make_depends,omitempty"`
|
Depends []string `yaml:"depends,omitempty"`
|
||||||
OptionalDepends []string `yaml:"optional_depends,omitempty"`
|
OptionalDepends []string `yaml:"optional_depends,omitempty"`
|
||||||
Conflicts []string `yaml:"conflicts,omitempty"`
|
MakeDepends []string `yaml:"make_depends,omitempty"`
|
||||||
Replaces []string `yaml:"replaces,omitempty"`
|
Conflicts []string `yaml:"conflicts,omitempty"`
|
||||||
Provides []string `yaml:"provides,omitempty"`
|
Replaces []string `yaml:"replaces,omitempty"`
|
||||||
SplitPackages []*PackageInfo `yaml:"split_packages,omitempty"`
|
Provides []string `yaml:"provides,omitempty"`
|
||||||
|
Downloads []PackageDownload `yaml:"downloads,omitempty"`
|
||||||
|
SplitPackages []*PackageInfo `yaml:"split_packages,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PackageDownload struct {
|
||||||
|
Url string `yaml:"url"`
|
||||||
|
Type string `yaml:"type,omitempty"`
|
||||||
|
Filepath string `yaml:"filepath,omitempty,omitempty"`
|
||||||
|
|
||||||
|
// Archive options
|
||||||
|
NoExtract bool `yaml:"no_extract,omitempty"`
|
||||||
|
ExtractTo string `yaml:"extract_to,omitempty"`
|
||||||
|
ExtractStripComponents int `yaml:"extract_strip_components,omitempty"`
|
||||||
|
|
||||||
|
// Git options
|
||||||
|
CloneTo string `yaml:"clone_to,omitempty"`
|
||||||
|
GitBranch string `yaml:"git_branch,omitempty"`
|
||||||
|
|
||||||
|
Checksum string `yaml:"checksum,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PackageFileEntry struct {
|
type PackageFileEntry struct {
|
||||||
@@ -177,10 +196,10 @@ func ReadPackage(filename string) (*BPMPackage, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
defer file.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
tr := tar.NewReader(file)
|
tr := tar.NewReader(file)
|
||||||
for {
|
for {
|
||||||
@@ -303,14 +322,6 @@ func ReadPackageScripts(filename string) (map[string]string, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type packageOperation uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
packageOperationInstall packageOperation = 0
|
|
||||||
packageOperationUpdate = 1
|
|
||||||
packageOperationRemove = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
func executePackageScript(pkg, rootDir string, verbose bool, packageScript string) error {
|
func executePackageScript(pkg, rootDir string, verbose bool, packageScript string) error {
|
||||||
var bpmpkg *BPMPackage
|
var bpmpkg *BPMPackage
|
||||||
var err error
|
var err error
|
||||||
@@ -413,14 +424,8 @@ func executePackageScript(pkg, rootDir string, verbose bool, packageScript strin
|
|||||||
|
|
||||||
func ReadPackageInfo(contents string) (*PackageInfo, error) {
|
func ReadPackageInfo(contents string) (*PackageInfo, error) {
|
||||||
pkgInfo := &PackageInfo{
|
pkgInfo := &PackageInfo{
|
||||||
Name: "",
|
|
||||||
Description: "",
|
|
||||||
Version: "",
|
|
||||||
Revision: 1,
|
Revision: 1,
|
||||||
Url: "",
|
OutputArch: GetArch(),
|
||||||
License: "",
|
|
||||||
Arch: "",
|
|
||||||
Type: "",
|
|
||||||
Keep: make([]string, 0),
|
Keep: make([]string, 0),
|
||||||
Depends: make([]string, 0),
|
Depends: make([]string, 0),
|
||||||
MakeDepends: make([]string, 0),
|
MakeDepends: make([]string, 0),
|
||||||
@@ -428,6 +433,7 @@ func ReadPackageInfo(contents string) (*PackageInfo, error) {
|
|||||||
Conflicts: make([]string, 0),
|
Conflicts: make([]string, 0),
|
||||||
Replaces: make([]string, 0),
|
Replaces: make([]string, 0),
|
||||||
Provides: make([]string, 0),
|
Provides: make([]string, 0),
|
||||||
|
Downloads: make([]PackageDownload, 0),
|
||||||
SplitPackages: make([]*PackageInfo, 0),
|
SplitPackages: make([]*PackageInfo, 0),
|
||||||
}
|
}
|
||||||
err := yaml.Unmarshal([]byte(contents), &pkgInfo)
|
err := yaml.Unmarshal([]byte(contents), &pkgInfo)
|
||||||
@@ -462,28 +468,29 @@ func ReadPackageInfo(contents string) (*PackageInfo, error) {
|
|||||||
return nil, fmt.Errorf("invalid split package name: %s", splitPkg.Name)
|
return nil, fmt.Errorf("invalid split package name: %s", splitPkg.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn split package into json data
|
// Turn split package into yaml data
|
||||||
splitPkgJson, err := yaml.Marshal(splitPkg)
|
splitPkgYaml, err := yaml.Marshal(splitPkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone all main package fields onto split package
|
// Clone all main package fields onto split package
|
||||||
pkgInfoClone := *pkgInfo
|
*splitPkg = *pkgInfo
|
||||||
pkgInfo.SplitPackages[i] = &pkgInfoClone
|
|
||||||
|
|
||||||
// Set split package field of split package to nil
|
// Set split package field of split package to nil
|
||||||
pkgInfo.SplitPackages[i].SplitPackages = nil
|
splitPkg.SplitPackages = nil
|
||||||
|
|
||||||
// Unmarshal json data back to struct
|
// Unmarshal json data back to struct
|
||||||
err = yaml.Unmarshal(splitPkgJson, &pkgInfo.SplitPackages[i])
|
err = yaml.Unmarshal(splitPkgYaml, splitPkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force set split package version, revision
|
// Force set split package version, revision
|
||||||
pkgInfo.SplitPackages[i].Version = pkgInfo.Version
|
splitPkg.Version = pkgInfo.Version
|
||||||
pkgInfo.SplitPackages[i].Revision = pkgInfo.Revision
|
splitPkg.Revision = pkgInfo.Revision
|
||||||
|
|
||||||
|
pkgInfo.SplitPackages[i] = splitPkg
|
||||||
}
|
}
|
||||||
|
|
||||||
return pkgInfo, nil
|
return pkgInfo, nil
|
||||||
|
|||||||
@@ -3,9 +3,52 @@ package bpmlib
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type BPMLock struct {
|
||||||
|
file *os.File
|
||||||
|
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) {
|
||||||
|
// Create parent directories if they don't already exist
|
||||||
|
err := os.MkdirAll(path.Join(rootDir, "/var/lib/bpm"), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create file
|
||||||
|
f, err := os.Create(path.Join(rootDir, "var/lib/bpm/bpm.lock"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get exclusive file lock on file
|
||||||
|
err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &BPMLock{f, path.Join(rootDir, "var/lib/bpm/bpm.lock")}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetArch() string {
|
func GetArch() string {
|
||||||
uname := syscall.Utsname{}
|
uname := syscall.Utsname{}
|
||||||
err := syscall.Uname(&uname)
|
err := syscall.Uname(&uname)
|
||||||
|
|||||||
Reference in New Issue
Block a user