Add file locks to prevent multiple processes at the same time

This commit is contained in:
2025-10-04 17:24:20 +03:00
parent 53e08ce7f9
commit eeb9a01e31
2 changed files with 281 additions and 69 deletions
+238 -69
View File
@@ -51,6 +51,8 @@ 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 {
@@ -58,6 +60,10 @@ func main() {
} }
resolveFlags() resolveFlags()
resolveCommand() resolveCommand()
if exitCode != 0 {
os.Exit(exitCode)
}
} }
type commandType uint8 type commandType uint8
@@ -121,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 {
@@ -134,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
@@ -154,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()
@@ -162,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)
} }
@@ -172,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 {
@@ -206,13 +225,17 @@ 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 {
@@ -229,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()
@@ -242,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
@@ -262,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
@@ -275,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
@@ -310,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
@@ -364,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] ")
@@ -393,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 {
@@ -415,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
@@ -445,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
@@ -503,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:
@@ -529,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() {
@@ -578,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
@@ -610,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]) {
@@ -625,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
@@ -643,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
@@ -691,15 +850,21 @@ 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 {
@@ -721,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
@@ -737,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
} }
} }
} }
+43
View File
@@ -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)