Compare commits
No commits in common. "e60381beb1d923177489f952fc619adf179cc163" and "9485248d8ee831cd6065f716d4a13a75324d5b75" have entirely different histories.
e60381beb1
...
9485248d8e
254
src/bpm/main.go
254
src/bpm/main.go
@ -202,41 +202,107 @@ func resolveCommand() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case install:
|
case install:
|
||||||
// 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.Fatalf("Error: this subcommand needs to be run with superuser permissions")
|
||||||
}
|
}
|
||||||
|
pkgs := subcommandArgs
|
||||||
// Return if no packages are specified
|
if len(pkgs) == 0 {
|
||||||
if len(subcommandArgs) == 0 {
|
|
||||||
fmt.Println("No packages or files were given to install")
|
fmt.Println("No packages or files were given to install")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if installationReason argument is valid
|
// Check if installationReason argument is valid
|
||||||
ir := bpmlib.InstallationReasonUnknown
|
ir := bpmlib.Unknown
|
||||||
switch installationReason {
|
if installationReason == "manual" {
|
||||||
case "manual":
|
ir = bpmlib.Manual
|
||||||
ir = bpmlib.InstallationReasonManual
|
} else if installationReason == "dependency" {
|
||||||
case "dependency":
|
ir = bpmlib.Dependency
|
||||||
ir = bpmlib.InstallationReasonDependency
|
} else if installationReason != "" {
|
||||||
case "":
|
|
||||||
default:
|
|
||||||
log.Fatalf("Error: %s is not a valid installation reason", installationReason)
|
log.Fatalf("Error: %s is not a valid installation reason", installationReason)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get reinstall method
|
operation := bpmlib.BPMOperation{
|
||||||
var reinstallMethod bpmlib.ReinstallMethod
|
Actions: make([]bpmlib.OperationAction, 0),
|
||||||
if reinstallAll {
|
UnresolvedDepends: make([]string, 0),
|
||||||
reinstallMethod = bpmlib.ReinstallMethodAll
|
Changes: make(map[string]string),
|
||||||
} else if reinstall {
|
RootDir: rootDir,
|
||||||
reinstallMethod = bpmlib.ReinstallMethodSpecified
|
ForceInstallationReason: ir,
|
||||||
} else {
|
|
||||||
reinstallMethod = bpmlib.ReinstallMethodNone
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Installation Operation
|
// Search for packages
|
||||||
operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallMethod, !noOptional, force, verbose, subcommandArgs...)
|
for _, pkg := range pkgs {
|
||||||
|
if stat, err := os.Stat(pkg); err == nil && !stat.IsDir() {
|
||||||
|
bpmpkg, err := bpmlib.ReadPackage(pkg)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: could not read package: %s\n", err)
|
||||||
|
}
|
||||||
|
if !reinstall && bpmlib.IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) && bpmlib.GetPackageInfo(bpmpkg.PkgInfo.Name, rootDir).GetFullVersion() == bpmpkg.PkgInfo.GetFullVersion() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
operation.AppendAction(&bpmlib.InstallPackageAction{
|
||||||
|
File: pkg,
|
||||||
|
IsDependency: false,
|
||||||
|
BpmPackage: bpmpkg,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
var entry *bpmlib.RepositoryEntry
|
||||||
|
|
||||||
|
if e, _, err := bpmlib.GetRepositoryEntry(pkg); err == nil {
|
||||||
|
entry = e
|
||||||
|
} else if isVirtual, p := bpmlib.IsVirtualPackage(pkg, rootDir); isVirtual {
|
||||||
|
entry, _, err = bpmlib.GetRepositoryEntry(p)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: could not find package (%s) in any repository\n", p)
|
||||||
|
}
|
||||||
|
} else if e := bpmlib.ResolveVirtualPackage(pkg); e != nil {
|
||||||
|
entry = e
|
||||||
|
} else {
|
||||||
|
log.Fatalf("Error: could not find package (%s) in any repository\n", pkg)
|
||||||
|
}
|
||||||
|
if !reinstall && bpmlib.IsPackageInstalled(entry.Info.Name, rootDir) && bpmlib.GetPackageInfo(entry.Info.Name, rootDir).GetFullVersion() == entry.Info.GetFullVersion() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
operation.AppendAction(&bpmlib.FetchPackageAction{
|
||||||
|
IsDependency: false,
|
||||||
|
RepositoryEntry: entry,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve dependencies
|
||||||
|
err := operation.ResolveDependencies(reinstallAll, !noOptional, verbose)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: could not resolve dependencies: %s\n", err)
|
||||||
|
}
|
||||||
|
if len(operation.UnresolvedDepends) != 0 {
|
||||||
|
if !force {
|
||||||
|
log.Fatalf("Error: the following dependencies could not be found in any repositories: %s\n", strings.Join(operation.UnresolvedDepends, ", "))
|
||||||
|
} else {
|
||||||
|
log.Println("Warning: The following dependencies could not be found in any repositories: " + strings.Join(operation.UnresolvedDepends, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace obsolete packages
|
||||||
|
operation.ReplaceObsoletePackages()
|
||||||
|
|
||||||
|
// Check for conflicts
|
||||||
|
conflicts, err := operation.CheckForConflicts()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: could not complete package conflict check: %s\n", err)
|
||||||
|
}
|
||||||
|
if len(conflicts) > 0 {
|
||||||
|
if !force {
|
||||||
|
log.Println("Error: conflicting packages found")
|
||||||
|
} else {
|
||||||
|
log.Fatalf("Warning: conflicting packages found")
|
||||||
|
}
|
||||||
|
for pkg, conflict := range conflicts {
|
||||||
|
fmt.Printf("%s is in conflict with the following packages: %s\n", pkg, strings.Join(conflict, ", "))
|
||||||
|
}
|
||||||
|
if !force {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Show operation summary
|
// Show operation summary
|
||||||
operation.ShowOperationSummary()
|
operation.ShowOperationSummary()
|
||||||
@ -270,17 +336,81 @@ func resolveCommand() {
|
|||||||
log.Fatalf("Error: could not run hooks: %s\n", err)
|
log.Fatalf("Error: could not run hooks: %s\n", err)
|
||||||
}
|
}
|
||||||
case update:
|
case update:
|
||||||
// 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.Fatalf("Error: this subcommand needs to be run with superuser permissions")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Update Operation
|
// Sync repositories
|
||||||
operation, err := bpmlib.UpdatePackages(rootDir, !nosync, !noOptional, force, verbose)
|
if !nosync {
|
||||||
if err != nil {
|
for _, repo := range bpmlib.BPMConfig.Repositories {
|
||||||
log.Fatalf("Error: could not update packages: %s\n", err)
|
fmt.Printf("Fetching package database for repository (%s)...\n", repo.Name)
|
||||||
|
err := repo.SyncLocalDatabase()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: could not sync local database for repository (%s): %s\n", repo.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("All package databases synced successfully!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bpmlib.ReadConfig()
|
||||||
|
|
||||||
|
// Get installed packages and check for updates
|
||||||
|
pkgs, err := bpmlib.GetInstalledPackages(rootDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: could not get installed packages: %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
operation := bpmlib.BPMOperation{
|
||||||
|
Actions: make([]bpmlib.OperationAction, 0),
|
||||||
|
UnresolvedDepends: make([]string, 0),
|
||||||
|
Changes: make(map[string]string),
|
||||||
|
RootDir: rootDir,
|
||||||
|
ForceInstallationReason: bpmlib.Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for packages
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
if slices.Contains(bpmlib.BPMConfig.IgnorePackages, pkg) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var entry *bpmlib.RepositoryEntry
|
||||||
|
// Check if installed package can be replaced and install that instead
|
||||||
|
if e := bpmlib.FindReplacement(pkg); e != nil {
|
||||||
|
entry = e
|
||||||
|
} else if entry, _, err = bpmlib.GetRepositoryEntry(pkg); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
installedInfo := bpmlib.GetPackageInfo(pkg, rootDir)
|
||||||
|
if installedInfo == nil {
|
||||||
|
log.Fatalf("Error: could not get package info for (%s)\n", pkg)
|
||||||
|
} else {
|
||||||
|
comparison := bpmlib.ComparePackageVersions(*entry.Info, *installedInfo)
|
||||||
|
if comparison > 0 || reinstall {
|
||||||
|
operation.AppendAction(&bpmlib.FetchPackageAction{
|
||||||
|
IsDependency: false,
|
||||||
|
RepositoryEntry: entry,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for new dependencies in updated packages
|
||||||
|
err = operation.ResolveDependencies(reinstallAll, !noOptional, verbose)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: could not resolve dependencies: %s\n", err)
|
||||||
|
}
|
||||||
|
if len(operation.UnresolvedDepends) != 0 {
|
||||||
|
if !force {
|
||||||
|
log.Fatalf("Error: the following dependencies could not be found in any repositories: %s\n", strings.Join(operation.UnresolvedDepends, ", "))
|
||||||
|
} else {
|
||||||
|
log.Println("Warning: The following dependencies could not be found in any repositories: " + strings.Join(operation.UnresolvedDepends, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace obsolete packages
|
||||||
|
operation.ReplaceObsoletePackages()
|
||||||
|
|
||||||
// Show operation summary
|
// Show operation summary
|
||||||
operation.ShowOperationSummary()
|
operation.ShowOperationSummary()
|
||||||
|
|
||||||
@ -308,12 +438,9 @@ func resolveCommand() {
|
|||||||
log.Fatalf("Error: could not run hooks: %s\n", err)
|
log.Fatalf("Error: could not run hooks: %s\n", err)
|
||||||
}
|
}
|
||||||
case sync:
|
case sync:
|
||||||
// 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.Fatalf("Error: this subcommand needs to be run with superuser permissions")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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] ")
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
@ -323,28 +450,54 @@ func resolveCommand() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, repo := range bpmlib.BPMConfig.Repositories {
|
||||||
err := bpmlib.SyncDatabase(verbose)
|
fmt.Printf("Fetching package database for repository (%s)...\n", repo.Name)
|
||||||
if err != nil {
|
err := repo.SyncLocalDatabase()
|
||||||
log.Fatalf("Error: could not sync local database: %s\n", err)
|
if err != nil {
|
||||||
|
log.Fatalf("Error: could not sync local database for repository (%s): %s\n", repo.Name, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("All package databases synced successfully!")
|
fmt.Println("All package databases synced successfully!")
|
||||||
case remove:
|
case remove:
|
||||||
// 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.Fatalf("Error: this subcommand needs to be run with superuser permissions")
|
||||||
}
|
}
|
||||||
|
packages := subcommandArgs
|
||||||
if len(subcommandArgs) == 0 {
|
if len(packages) == 0 {
|
||||||
fmt.Println("No packages were given")
|
fmt.Println("No packages were given")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove packages
|
operation := &bpmlib.BPMOperation{
|
||||||
operation, err := bpmlib.RemovePackages(rootDir, removeUnused, doCleanup, verbose, subcommandArgs...)
|
Actions: make([]bpmlib.OperationAction, 0),
|
||||||
if err != nil {
|
UnresolvedDepends: make([]string, 0),
|
||||||
log.Fatalf("Error: could not remove packages: %s\n", err)
|
Changes: make(map[string]string),
|
||||||
|
RootDir: rootDir,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for packages
|
||||||
|
for _, pkg := range packages {
|
||||||
|
bpmpkg := bpmlib.GetPackage(pkg, rootDir)
|
||||||
|
if bpmpkg == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
operation.AppendAction(&bpmlib.RemovePackageAction{BpmPackage: bpmpkg})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip needed packages if the --unused flag is on
|
||||||
|
if removeUnused {
|
||||||
|
err := operation.RemoveNeededPackages()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: could not skip needed packages: %s\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do package cleanup
|
||||||
|
if doCleanup {
|
||||||
|
err := operation.Cleanup(verbose)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: could not perform cleanup for operation: %s\n", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show operation summary
|
// Show operation summary
|
||||||
@ -362,7 +515,7 @@ func resolveCommand() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.Fatalf("Error: could not complete operation: %s\n", err)
|
||||||
}
|
}
|
||||||
@ -374,15 +527,21 @@ func resolveCommand() {
|
|||||||
log.Fatalf("Error: could not run hooks: %s\n", err)
|
log.Fatalf("Error: could not run hooks: %s\n", err)
|
||||||
}
|
}
|
||||||
case cleanup:
|
case cleanup:
|
||||||
// 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.Fatalf("Error: this subcommand needs to be run with superuser permissions")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do cleanup
|
operation := &bpmlib.BPMOperation{
|
||||||
operation, err := bpmlib.CleanupPackages(rootDir, verbose)
|
Actions: make([]bpmlib.OperationAction, 0),
|
||||||
|
UnresolvedDepends: make([]string, 0),
|
||||||
|
Changes: make(map[string]string),
|
||||||
|
RootDir: rootDir,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do package cleanup
|
||||||
|
err := operation.Cleanup(verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: could not cleanup packages: %s\n", err)
|
log.Fatalf("Error: could not perform cleanup for operation: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show operation summary
|
// Show operation summary
|
||||||
@ -552,6 +711,7 @@ func resolveFlags() {
|
|||||||
updateFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing")
|
updateFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing")
|
||||||
updateFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts")
|
updateFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts")
|
||||||
updateFlagSet.BoolVar(&force, "f", false, "Force update by skipping architecture and dependency resolution")
|
updateFlagSet.BoolVar(&force, "f", false, "Force update by skipping architecture and dependency resolution")
|
||||||
|
updateFlagSet.BoolVar(&reinstall, "reinstall", false, "Fetches and reinstalls all packages even if they do not have a newer version available")
|
||||||
updateFlagSet.BoolVar(&nosync, "no-sync", false, "Skips package database syncing")
|
updateFlagSet.BoolVar(&nosync, "no-sync", false, "Skips package database syncing")
|
||||||
updateFlagSet.Usage = printHelp
|
updateFlagSet.Usage = printHelp
|
||||||
// Sync flags
|
// Sync flags
|
||||||
|
@ -1,250 +0,0 @@
|
|||||||
package bpmlib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"slices"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ReinstallMethod uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
ReinstallMethodNone ReinstallMethod = iota
|
|
||||||
ReinstallMethodSpecified ReinstallMethod = iota
|
|
||||||
ReinstallMethodAll ReinstallMethod = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
// InstallPackages installs the specified packages into the given root directory by fetching them from repositories or directly from local bpm archives
|
|
||||||
func InstallPackages(rootDir string, installationReason InstallationReason, reinstallMethod ReinstallMethod, installOptionalDependencies, forceInstallation, verbose bool, packages ...string) (operation *BPMOperation, err error) {
|
|
||||||
// Setup operation struct
|
|
||||||
operation = &BPMOperation{
|
|
||||||
Actions: make([]OperationAction, 0),
|
|
||||||
UnresolvedDepends: make([]string, 0),
|
|
||||||
Changes: make(map[string]string),
|
|
||||||
RootDir: rootDir,
|
|
||||||
ForceInstallationReason: installationReason,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve packages
|
|
||||||
for _, pkg := range packages {
|
|
||||||
if stat, err := os.Stat(pkg); err == nil && !stat.IsDir() {
|
|
||||||
bpmpkg, err := ReadPackage(pkg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not read package: %s", err)
|
|
||||||
}
|
|
||||||
if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) && GetPackageInfo(bpmpkg.PkgInfo.Name, rootDir).GetFullVersion() == bpmpkg.PkgInfo.GetFullVersion() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
operation.AppendAction(&InstallPackageAction{
|
|
||||||
File: pkg,
|
|
||||||
IsDependency: false,
|
|
||||||
BpmPackage: bpmpkg,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
var entry *RepositoryEntry
|
|
||||||
|
|
||||||
if e, _, err := GetRepositoryEntry(pkg); err == nil {
|
|
||||||
entry = e
|
|
||||||
} else if isVirtual, p := IsVirtualPackage(pkg, rootDir); isVirtual {
|
|
||||||
entry, _, err = GetRepositoryEntry(p)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not find package (%s) in any repositor", p)
|
|
||||||
}
|
|
||||||
} else if e := ResolveVirtualPackage(pkg); e != nil {
|
|
||||||
entry = e
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("could not find package (%s) in any repository", pkg)
|
|
||||||
}
|
|
||||||
if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(entry.Info.Name, rootDir) && GetPackageInfo(entry.Info.Name, rootDir).GetFullVersion() == entry.Info.GetFullVersion() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
operation.AppendAction(&FetchPackageAction{
|
|
||||||
IsDependency: false,
|
|
||||||
RepositoryEntry: entry,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve dependencies
|
|
||||||
err = operation.ResolveDependencies(reinstallMethod == ReinstallMethodAll, installOptionalDependencies, verbose)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not resolve dependencies: %s", err)
|
|
||||||
}
|
|
||||||
if len(operation.UnresolvedDepends) != 0 {
|
|
||||||
if !forceInstallation {
|
|
||||||
return nil, fmt.Errorf("dependencies (%s) could not be found in any repositories", strings.Join(operation.UnresolvedDepends, ", "))
|
|
||||||
} else if verbose {
|
|
||||||
log.Println("Warning: The following dependencies could not be found in any repositories: " + strings.Join(operation.UnresolvedDepends, ", "))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace obsolete packages
|
|
||||||
operation.ReplaceObsoletePackages()
|
|
||||||
|
|
||||||
// Check for conflicts
|
|
||||||
conflicts, err := operation.CheckForConflicts()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not complete package conflict check: %s", err)
|
|
||||||
}
|
|
||||||
if len(conflicts) > 0 {
|
|
||||||
if verbose {
|
|
||||||
for pkg, conflict := range conflicts {
|
|
||||||
fmt.Printf("%s is in conflict with packages (%s)\n", pkg, strings.Join(conflict, ", "))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !forceInstallation {
|
|
||||||
return nil, fmt.Errorf("conflicting packages found")
|
|
||||||
} else {
|
|
||||||
log.Println("Warning: conflicting packages found")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return operation, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemovePackages removes the specified packages from the given root directory
|
|
||||||
func RemovePackages(rootDir string, removeUnusedPackagesOnly, cleanupDependencies, verbose bool, packages ...string) (operation *BPMOperation, err error) {
|
|
||||||
operation = &BPMOperation{
|
|
||||||
Actions: make([]OperationAction, 0),
|
|
||||||
UnresolvedDepends: make([]string, 0),
|
|
||||||
Changes: make(map[string]string),
|
|
||||||
RootDir: rootDir,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for packages
|
|
||||||
for _, pkg := range packages {
|
|
||||||
bpmpkg := GetPackage(pkg, rootDir)
|
|
||||||
if bpmpkg == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
operation.AppendAction(&RemovePackageAction{BpmPackage: bpmpkg})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not remove packages which other packages depend on
|
|
||||||
if removeUnusedPackagesOnly {
|
|
||||||
err := operation.RemoveNeededPackages()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not skip needed packages: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do package cleanup
|
|
||||||
if cleanupDependencies {
|
|
||||||
err := operation.Cleanup(verbose)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not perform cleanup for operation: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return operation, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CleanupPackages finds packages installed as dependencies which are no longer required by the rest of the system in the given root directory
|
|
||||||
func CleanupPackages(rootDir string, verbose bool) (operation *BPMOperation, err error) {
|
|
||||||
operation = &BPMOperation{
|
|
||||||
Actions: make([]OperationAction, 0),
|
|
||||||
UnresolvedDepends: make([]string, 0),
|
|
||||||
Changes: make(map[string]string),
|
|
||||||
RootDir: rootDir,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do package cleanup
|
|
||||||
err = operation.Cleanup(verbose)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not perform cleanup for operation: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return operation, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdatePackages fetches the newest versions of all installed packages from
|
|
||||||
func UpdatePackages(rootDir string, syncDatabase bool, installOptionalDependencies, forceInstallation, verbose bool) (operation *BPMOperation, err error) {
|
|
||||||
// Sync repositories
|
|
||||||
if syncDatabase {
|
|
||||||
err := SyncDatabase(verbose)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not sync local database: %s", err)
|
|
||||||
}
|
|
||||||
if verbose {
|
|
||||||
fmt.Println("All package databases synced successfully!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reload config and local databases
|
|
||||||
ReadConfig()
|
|
||||||
|
|
||||||
// Get installed packages and check for updates
|
|
||||||
pkgs, err := GetInstalledPackages(rootDir)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get installed packages: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
operation = &BPMOperation{
|
|
||||||
Actions: make([]OperationAction, 0),
|
|
||||||
UnresolvedDepends: make([]string, 0),
|
|
||||||
Changes: make(map[string]string),
|
|
||||||
RootDir: rootDir,
|
|
||||||
ForceInstallationReason: InstallationReasonUnknown,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for packages
|
|
||||||
for _, pkg := range pkgs {
|
|
||||||
if slices.Contains(BPMConfig.IgnorePackages, pkg) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var entry *RepositoryEntry
|
|
||||||
// Check if installed package can be replaced and install that instead
|
|
||||||
if e := FindReplacement(pkg); e != nil {
|
|
||||||
entry = e
|
|
||||||
} else if entry, _, err = GetRepositoryEntry(pkg); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
installedInfo := GetPackageInfo(pkg, rootDir)
|
|
||||||
if installedInfo == nil {
|
|
||||||
return nil, fmt.Errorf("could not get package info for package (%s)", pkg)
|
|
||||||
} else {
|
|
||||||
comparison := ComparePackageVersions(*entry.Info, *installedInfo)
|
|
||||||
if comparison > 0 {
|
|
||||||
operation.AppendAction(&FetchPackageAction{
|
|
||||||
IsDependency: false,
|
|
||||||
RepositoryEntry: entry,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for new dependencies in updated packages
|
|
||||||
err = operation.ResolveDependencies(false, installOptionalDependencies, verbose)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not resolve dependencies: %s", err)
|
|
||||||
}
|
|
||||||
if len(operation.UnresolvedDepends) != 0 {
|
|
||||||
if !forceInstallation {
|
|
||||||
return nil, fmt.Errorf("dependencies (%s) could not be found in any repositories", strings.Join(operation.UnresolvedDepends, ", "))
|
|
||||||
} else if verbose {
|
|
||||||
log.Printf("Warning: dependencies (%s) could not be found in any repositories\n", strings.Join(operation.UnresolvedDepends, ", "))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace obsolete packages
|
|
||||||
operation.ReplaceObsoletePackages()
|
|
||||||
return operation, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SyncDatabase syncs all databases declared in /etc/bpm.conf
|
|
||||||
func SyncDatabase(verbose bool) (err error) {
|
|
||||||
for _, repo := range BPMConfig.Repositories {
|
|
||||||
if verbose {
|
|
||||||
fmt.Printf("Fetching package database for repository (%s)...\n", repo.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := repo.SyncLocalDatabase()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -217,7 +217,7 @@ func (operation *BPMOperation) Cleanup(verbose bool) error {
|
|||||||
// Get manually installed packages, resolve all their dependencies and add them to the keepPackages slice
|
// Get manually installed packages, resolve all their dependencies and add them to the keepPackages slice
|
||||||
keepPackages := make([]string, 0)
|
keepPackages := make([]string, 0)
|
||||||
for _, pkg := range slices.Clone(installedPackages) {
|
for _, pkg := range slices.Clone(installedPackages) {
|
||||||
if GetInstallationReason(pkg.Name, operation.RootDir) != InstallationReasonManual {
|
if GetInstallationReason(pkg.Name, operation.RootDir) != Manual {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,13 +475,13 @@ func (operation *BPMOperation) Execute(verbose, force bool) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New(fmt.Sprintf("could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err))
|
return errors.New(fmt.Sprintf("could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err))
|
||||||
}
|
}
|
||||||
if operation.ForceInstallationReason != InstallationReasonUnknown && !value.IsDependency {
|
if operation.ForceInstallationReason != Unknown && !value.IsDependency {
|
||||||
err := SetInstallationReason(bpmpkg.PkgInfo.Name, operation.ForceInstallationReason, operation.RootDir)
|
err := SetInstallationReason(bpmpkg.PkgInfo.Name, operation.ForceInstallationReason, operation.RootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New(fmt.Sprintf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err))
|
return errors.New(fmt.Sprintf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err))
|
||||||
}
|
}
|
||||||
} else if value.IsDependency && !isReinstall {
|
} else if value.IsDependency && !isReinstall {
|
||||||
err := SetInstallationReason(bpmpkg.PkgInfo.Name, InstallationReasonDependency, operation.RootDir)
|
err := SetInstallationReason(bpmpkg.PkgInfo.Name, Dependency, operation.RootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New(fmt.Sprintf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err))
|
return errors.New(fmt.Sprintf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err))
|
||||||
}
|
}
|
||||||
|
@ -74,9 +74,9 @@ func (pkgInfo *PackageInfo) GetFullVersion() string {
|
|||||||
type InstallationReason string
|
type InstallationReason string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
InstallationReasonManual InstallationReason = "manual"
|
Manual InstallationReason = "manual"
|
||||||
InstallationReasonDependency InstallationReason = "dependency"
|
Dependency InstallationReason = "dependency"
|
||||||
InstallationReasonUnknown InstallationReason = "unknown"
|
Unknown InstallationReason = "unknown"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ComparePackageVersions(info1, info2 PackageInfo) int {
|
func ComparePackageVersions(info1, info2 PackageInfo) int {
|
||||||
@ -90,19 +90,19 @@ func GetInstallationReason(pkg, rootDir string) InstallationReason {
|
|||||||
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
pkgDir := path.Join(installedDir, pkg)
|
pkgDir := path.Join(installedDir, pkg)
|
||||||
if stat, err := os.Stat(path.Join(pkgDir, "installation_reason")); err != nil || stat.IsDir() {
|
if stat, err := os.Stat(path.Join(pkgDir, "installation_reason")); err != nil || stat.IsDir() {
|
||||||
return InstallationReasonManual
|
return Manual
|
||||||
}
|
}
|
||||||
b, err := os.ReadFile(path.Join(pkgDir, "installation_reason"))
|
b, err := os.ReadFile(path.Join(pkgDir, "installation_reason"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return InstallationReasonUnknown
|
return Unknown
|
||||||
}
|
}
|
||||||
reason := strings.TrimSpace(string(b))
|
reason := strings.TrimSpace(string(b))
|
||||||
if reason == "manual" {
|
if reason == "manual" {
|
||||||
return InstallationReasonManual
|
return Manual
|
||||||
} else if reason == "dependency" {
|
} else if reason == "dependency" {
|
||||||
return InstallationReasonDependency
|
return Dependency
|
||||||
}
|
}
|
||||||
return InstallationReasonUnknown
|
return Unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetInstallationReason(pkg string, reason InstallationReason, rootDir string) error {
|
func SetInstallationReason(pkg string, reason InstallationReason, rootDir string) error {
|
||||||
@ -280,15 +280,15 @@ func ReadPackageScripts(filename string) (map[string]string, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type packageOperation uint8
|
type Operation uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
packageOperationInstall packageOperation = 0
|
Install Operation = 0
|
||||||
packageOperationUpdate = 1
|
Update = 1
|
||||||
packageOperationRemove = 2
|
Remove = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
func executePackageScripts(filename, rootDir string, operation packageOperation, postOperation bool) error {
|
func executePackageScripts(filename, rootDir string, operation Operation, postOperation bool) error {
|
||||||
pkgInfo, err := ReadPackage(filename)
|
pkgInfo, err := ReadPackage(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -320,11 +320,11 @@ func executePackageScripts(filename, rootDir string, operation packageOperation,
|
|||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_NAME=%s", pkgInfo.PkgInfo.Name))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_NAME=%s", pkgInfo.PkgInfo.Name))
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_DESC=%s", pkgInfo.PkgInfo.Description))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_DESC=%s", pkgInfo.PkgInfo.Description))
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_VERSION=%s", pkgInfo.PkgInfo.Version))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_VERSION=%s", pkgInfo.PkgInfo.Version))
|
||||||
if operation != packageOperationInstall {
|
if operation != Install {
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_OLD_VERSION=%s", GetPackageInfo(pkgInfo.PkgInfo.Name, rootDir).Version))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_OLD_VERSION=%s", GetPackageInfo(pkgInfo.PkgInfo.Name, rootDir).Version))
|
||||||
}
|
}
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_REVISION=%d", pkgInfo.PkgInfo.Revision))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_REVISION=%d", pkgInfo.PkgInfo.Revision))
|
||||||
if operation != packageOperationInstall {
|
if operation != Install {
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_OLD_REVISION=%d", GetPackageInfo(pkgInfo.PkgInfo.Name, rootDir).Revision))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_OLD_REVISION=%d", GetPackageInfo(pkgInfo.PkgInfo.Name, rootDir).Revision))
|
||||||
}
|
}
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_URL=%s", pkgInfo.PkgInfo.Url))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("BPM_PKG_URL=%s", pkgInfo.PkgInfo.Url))
|
||||||
@ -349,7 +349,7 @@ func executePackageScripts(filename, rootDir string, operation packageOperation,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if operation == packageOperationInstall {
|
if operation == Install {
|
||||||
if val, ok := scripts["pre_install.sh"]; !postOperation && ok {
|
if val, ok := scripts["pre_install.sh"]; !postOperation && ok {
|
||||||
err := run("pre_install.sh", val)
|
err := run("pre_install.sh", val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -362,7 +362,7 @@ func executePackageScripts(filename, rootDir string, operation packageOperation,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if operation == packageOperationUpdate {
|
} else if operation == Update {
|
||||||
if val, ok := scripts["pre_update.sh"]; !postOperation && ok {
|
if val, ok := scripts["pre_update.sh"]; !postOperation && ok {
|
||||||
err := run("pre_update.sh", val)
|
err := run("pre_update.sh", val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -375,7 +375,7 @@ func executePackageScripts(filename, rootDir string, operation packageOperation,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if operation == packageOperationRemove {
|
} else if operation == Remove {
|
||||||
if val, ok := scripts["pre_remove.sh"]; !postOperation && ok {
|
if val, ok := scripts["pre_remove.sh"]; !postOperation && ok {
|
||||||
err := run("pre_remove.sh", val)
|
err := run("pre_remove.sh", val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -478,12 +478,12 @@ func CreateReadableInfo(showArchitecture, showType, showPackageRelations bool, p
|
|||||||
|
|
||||||
func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) error {
|
func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) error {
|
||||||
if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) {
|
if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) {
|
||||||
err := executePackageScripts(filename, rootDir, packageOperationInstall, false)
|
err := executePackageScripts(filename, rootDir, Install, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err := executePackageScripts(filename, rootDir, packageOperationUpdate, false)
|
err := executePackageScripts(filename, rootDir, Update, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -629,12 +629,12 @@ func isSplitPackage(filename string) bool {
|
|||||||
func compilePackage(bpmpkg *BPMPackage, filename, rootDir string, verbose, binaryPkgFromSrc, skipCheck, keepTempDir bool) (error, []string) {
|
func compilePackage(bpmpkg *BPMPackage, filename, rootDir string, verbose, binaryPkgFromSrc, skipCheck, keepTempDir bool) (error, []string) {
|
||||||
var files []string
|
var files []string
|
||||||
if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) {
|
if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) {
|
||||||
err := executePackageScripts(filename, rootDir, packageOperationInstall, false)
|
err := executePackageScripts(filename, rootDir, Install, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err, nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err := executePackageScripts(filename, rootDir, packageOperationUpdate, false)
|
err := executePackageScripts(filename, rootDir, Update, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err, nil
|
||||||
}
|
}
|
||||||
@ -747,12 +747,12 @@ func compilePackage(bpmpkg *BPMPackage, filename, rootDir string, verbose, binar
|
|||||||
}
|
}
|
||||||
fmt.Println("Running source.sh file...")
|
fmt.Println("Running source.sh file...")
|
||||||
if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) {
|
if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) {
|
||||||
err = executePackageScripts(filename, rootDir, packageOperationInstall, false)
|
err = executePackageScripts(filename, rootDir, Install, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err, nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = executePackageScripts(filename, rootDir, packageOperationUpdate, false)
|
err = executePackageScripts(filename, rootDir, Update, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, nil
|
return err, nil
|
||||||
}
|
}
|
||||||
@ -1246,12 +1246,12 @@ func installPackage(filename, rootDir string, verbose, force, binaryPkgFromSrc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !packageInstalled {
|
if !packageInstalled {
|
||||||
err = executePackageScripts(filename, rootDir, packageOperationInstall, true)
|
err = executePackageScripts(filename, rootDir, Install, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = executePackageScripts(filename, rootDir, packageOperationUpdate, true)
|
err = executePackageScripts(filename, rootDir, Update, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user