5 Commits
8 changed files with 131 additions and 26 deletions
+19 -5
View File
@@ -87,10 +87,12 @@ func main() {
currentFlagSet.BoolP("verbose", "v", false, "Show additional information about the current operation") currentFlagSet.BoolP("verbose", "v", false, "Show additional information about the current operation")
currentFlagSet.BoolP("force", "f", false, "Bypass warnings during package installation") currentFlagSet.BoolP("force", "f", false, "Bypass warnings during package installation")
currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts") currentFlagSet.BoolP("yes", "y", false, "Enter 'yes' in all prompts")
currentFlagSet.Bool("runtime", true, "Install all runtime dependencies")
currentFlagSet.BoolP("optional", "o", false, "Install all optional dependencies") currentFlagSet.BoolP("optional", "o", false, "Install all optional dependencies")
currentFlagSet.String("installation-reason", "", "Specify the installation reason to use for the specified packages") currentFlagSet.String("installation-reason", "", "Specify the installation reason to use for the specified packages")
currentFlagSet.BoolP("reinstall", "r", false, "Reinstall the specified packages") currentFlagSet.BoolP("reinstall", "r", false, "Reinstall the specified packages")
currentFlagSet.BoolP("reinstall-all", "a", false, "Reinstall the specified packages and their dependencies") currentFlagSet.BoolP("reinstall-all", "a", false, "Reinstall the specified packages and their dependencies")
currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation")
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Install the specified packages", os.Args[2:]) setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Install the specified packages", os.Args[2:])
installPackages() installPackages()
@@ -140,6 +142,7 @@ func main() {
currentFlagSet.BoolP("no-sync", "n", false, "Do not sync databases") currentFlagSet.BoolP("no-sync", "n", false, "Do not sync databases")
currentFlagSet.Bool("allow-downgrades", false, "Allow package downgrades") currentFlagSet.Bool("allow-downgrades", false, "Allow package downgrades")
currentFlagSet.BoolP("optional", "o", false, "Install all optional dependencies") currentFlagSet.BoolP("optional", "o", false, "Install all optional dependencies")
currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation")
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Update installed packages", os.Args[2:]) setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Update installed packages", os.Args[2:])
updatePackages() updatePackages()
@@ -162,6 +165,7 @@ func main() {
currentFlagSet.BoolP("keep", "k", false, "Keep compilation files after successful package compilation") currentFlagSet.BoolP("keep", "k", false, "Keep compilation files after successful package compilation")
currentFlagSet.BoolP("output-directory", "o", false, "Set the output directory for the binary packages") currentFlagSet.BoolP("output-directory", "o", false, "Set the output directory for the binary packages")
currentFlagSet.Int("output-fd", -1, "Set the file descriptor output package names will be written to") currentFlagSet.Int("output-fd", -1, "Set the file descriptor output package names will be written to")
currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation")
setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Compile source packages and convert them to binary ones", os.Args[2:]) setupFlagsAndHelp(currentFlagSet, fmt.Sprintf("bpm %s <options>", subcommand), "Compile source packages and convert them to binary ones", os.Args[2:])
compilePackage() compilePackage()
@@ -480,10 +484,12 @@ func installPackages() {
verbose, _ := currentFlagSet.GetBool("verbose") verbose, _ := currentFlagSet.GetBool("verbose")
force, _ := currentFlagSet.GetBool("force") force, _ := currentFlagSet.GetBool("force")
yesAll, _ := currentFlagSet.GetBool("yes") yesAll, _ := currentFlagSet.GetBool("yes")
installRuntime, _ := currentFlagSet.GetBool("runtime")
installOptional, _ := currentFlagSet.GetBool("optional") installOptional, _ := currentFlagSet.GetBool("optional")
installationReason, _ := currentFlagSet.GetString("installation-reason") installationReason, _ := currentFlagSet.GetString("installation-reason")
reinstall, _ := currentFlagSet.GetBool("reinstall") reinstall, _ := currentFlagSet.GetBool("reinstall")
reinstallAll, _ := currentFlagSet.GetBool("reinstall-all") reinstallAll, _ := currentFlagSet.GetBool("reinstall-all")
compilationJobs, _ := currentFlagSet.GetInt("jobs")
// Get packages // Get packages
packages := currentFlagSet.Args() packages := currentFlagSet.Args()
@@ -543,7 +549,7 @@ func installPackages() {
} }
// Create installation operation // Create installation operation
operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallMethod, installOptional, force, verbose, packages...) operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallMethod, installRuntime, installOptional, force, verbose, packages...)
if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) { if errors.As(err, &bpmlib.PackageNotFoundErr{}) || errors.As(err, &bpmlib.DependencyNotFoundErr{}) || errors.As(err, &bpmlib.PackageConflictErr{}) {
log.Printf("Error: %s", err) log.Printf("Error: %s", err)
exitCode = 1 exitCode = 1
@@ -554,6 +560,9 @@ func installPackages() {
return return
} }
// Set compilation job count
operation.CompilationJobs = compilationJobs
// Exit if operation contains no actions // Exit if operation contains no actions
if len(operation.Actions) == 0 { if len(operation.Actions) == 0 {
fmt.Println("No action needs to be taken") fmt.Println("No action needs to be taken")
@@ -898,6 +907,7 @@ func updatePackages() {
noSync, _ := currentFlagSet.GetBool("no-sync") noSync, _ := currentFlagSet.GetBool("no-sync")
allowDowngrades, _ := currentFlagSet.GetBool("allow-downgrades") allowDowngrades, _ := currentFlagSet.GetBool("allow-downgrades")
installOptional, _ := currentFlagSet.GetBool("optional") installOptional, _ := currentFlagSet.GetBool("optional")
compilationJobs, _ := currentFlagSet.GetInt("jobs")
// Check for required permissions // Check for required permissions
if os.Getuid() != 0 { if os.Getuid() != 0 {
@@ -946,6 +956,9 @@ func updatePackages() {
return return
} }
// Set compilation job count
operation.CompilationJobs = compilationJobs
// Exit if operation contains no actions // Exit if operation contains no actions
if len(operation.Actions) == 0 { if len(operation.Actions) == 0 {
fmt.Println("No action needs to be taken") fmt.Println("No action needs to be taken")
@@ -1124,6 +1137,7 @@ func compilePackage() {
skipChecks, _ := currentFlagSet.GetBool("skip-checks") skipChecks, _ := currentFlagSet.GetBool("skip-checks")
outputDirectory, _ := currentFlagSet.GetString("output-directory") outputDirectory, _ := currentFlagSet.GetString("output-directory")
outputFd, _ := currentFlagSet.GetInt("output-fd") outputFd, _ := currentFlagSet.GetInt("output-fd")
compilationJobs, _ := currentFlagSet.GetInt("jobs")
// Get files // Get files
sourcePackages := currentFlagSet.Args() sourcePackages := currentFlagSet.Args()
@@ -1163,9 +1177,9 @@ func compilePackage() {
return return
} }
// Get direct runtime and make dependencies // Get direct common and make dependencies
totalDepends := make([]string, 0) totalDepends := make([]string, 0)
for _, depend := range bpmpkg.PkgInfo.GetDependencies(true, false) { for _, depend := range bpmpkg.PkgInfo.GetDependencies(true, false, false) {
if !slices.Contains(totalDepends, depend.PkgName) { if !slices.Contains(totalDepends, depend.PkgName) {
totalDepends = append(totalDepends, depend.PkgName) totalDepends = append(totalDepends, depend.PkgName)
} }
@@ -1198,7 +1212,7 @@ func compilePackage() {
} }
// Run 'bpm install' using the set privilege escalator command // Run 'bpm install' using the set privilege escalator command
args := []string{executable, "install", "--installation-reason=make-dependency"} args := []string{executable, "install", "--runtime=false", "--installation-reason=make-dependency"}
args = append(args, unmetDepends...) args = append(args, unmetDepends...)
cmd := exec.Command(bpmlib.CompilationBPMConfig.PrivilegeEscalatorCmd, args...) cmd := exec.Command(bpmlib.CompilationBPMConfig.PrivilegeEscalatorCmd, args...)
if yesAll { if yesAll {
@@ -1317,7 +1331,7 @@ func compilePackage() {
return return
} }
outputBpmPackages, err := bpmlib.CompileSourcePackage(sourcePackage, outputDirectory, skipChecks, keepCompilationFiles, verbose) outputBpmPackages, err := bpmlib.CompileSourcePackage(sourcePackage, outputDirectory, compilationJobs, skipChecks, keepCompilationFiles, verbose)
if err != nil { if err != nil {
// Remove unused packages // Remove unused packages
cleanupFunc() cleanupFunc()
+26 -1
View File
@@ -11,6 +11,7 @@ import (
"os/exec" "os/exec"
"path" "path"
"path/filepath" "path/filepath"
"runtime"
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
@@ -23,7 +24,12 @@ import (
var rootCompilationUID = "65534" var rootCompilationUID = "65534"
var rootCompilationGID = "65534" var rootCompilationGID = "65534"
func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks, keepCompilationFiles, verbose bool) (outputBpmPackages map[string]string, err error) { func CompileSourcePackage(archiveFilename, outputDirectory string, compilationJobs int, skipChecks, keepCompilationFiles, verbose bool) (outputBpmPackages map[string]string, err error) {
// Set compilation jobs
if compilationJobs <= 0 || compilationJobs > runtime.NumCPU() {
compilationJobs = runtime.NumCPU()
}
// Initialize map // Initialize map
outputBpmPackages = make(map[string]string) outputBpmPackages = make(map[string]string)
@@ -139,8 +145,27 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks, k
env = append(env, "BPM_PKG_REVISION="+strconv.Itoa(bpmpkg.PkgInfo.Revision)) env = append(env, "BPM_PKG_REVISION="+strconv.Itoa(bpmpkg.PkgInfo.Revision))
env = append(env, "BPM_PKG_URL="+bpmpkg.PkgInfo.Url) env = append(env, "BPM_PKG_URL="+bpmpkg.PkgInfo.Url)
env = append(env, "BPM_PKG_ARCH="+bpmpkg.PkgInfo.OutputArch) env = append(env, "BPM_PKG_ARCH="+bpmpkg.PkgInfo.OutputArch)
env = append(env, "BPM_JOBS="+strconv.Itoa(compilationJobs))
env = append(env, CompilationBPMConfig.CompilationEnvironment...) env = append(env, CompilationBPMConfig.CompilationEnvironment...)
// Set common flags used for limiting job count
makeflags := ""
env = slices.DeleteFunc(env, func(s string) bool {
if strings.HasPrefix(s, "MAKEFLAGS=") {
makeflags = s + " "
return true
} else if strings.HasPrefix(s, "CMAKE_BUILD_PARALLEL_LEVEL=") {
return true
} else if strings.HasPrefix(s, "CARGO_BUILD_JOBS=") {
return true
}
return false
})
env = append(env, makeflags+"-j"+strconv.Itoa(compilationJobs))
env = append(env, "CMAKE_BUILD_PARALLEL_LEVEL="+strconv.Itoa(compilationJobs))
env = append(env, "CARGO_BUILD_JOBS="+strconv.Itoa(compilationJobs))
// Execute prepare and build functions in source.sh script // Execute prepare and build functions in source.sh script
cmd := exec.Command("bash", "-c", cmd := exec.Command("bash", "-c",
"set -a\n"+ // Source and export functions and variables in source.sh script "set -a\n"+ // Source and export functions and variables in source.sh script
+1
View File
@@ -21,6 +21,7 @@ type configDatabase struct {
type CompilationBPMConfigStruct struct { type CompilationBPMConfigStruct struct {
PrivilegeEscalatorCmd string `yaml:"privilege_escalator_cmd"` PrivilegeEscalatorCmd string `yaml:"privilege_escalator_cmd"`
CompilationJobs int `yaml:"compilation_jobs"`
CompilationEnvironment []string `yaml:"compilation_env"` CompilationEnvironment []string `yaml:"compilation_env"`
} }
+2
View File
@@ -347,6 +347,7 @@ func (entry *BPMDatabaseEntry) CreateReadableInfo(rootDir string, humanReadableS
if entry.Info.License != "" { if entry.Info.License != "" {
ret = append(ret, "License: "+entry.Info.License) ret = append(ret, "License: "+entry.Info.License)
} }
appendArray("Maintainers", entry.Info.Maintainers, false)
ret = append(ret, "Architecture: "+entry.Info.Arch) ret = append(ret, "Architecture: "+entry.Info.Arch)
if entry.Info.Type == "source" && entry.Info.OutputArch != "" && entry.Info.OutputArch != GetArch() { if entry.Info.Type == "source" && entry.Info.OutputArch != "" && entry.Info.OutputArch != GetArch() {
ret = append(ret, "Output architecture: "+entry.Info.OutputArch) ret = append(ret, "Output architecture: "+entry.Info.OutputArch)
@@ -356,6 +357,7 @@ func (entry *BPMDatabaseEntry) CreateReadableInfo(rootDir string, humanReadableS
if entry.Info.Type == "source" { if entry.Info.Type == "source" {
appendArray("Make Dependencies", entry.Info.MakeDepends, true) appendArray("Make Dependencies", entry.Info.MakeDepends, true)
} }
appendArray("Runtime dependencies", entry.Info.RuntimeDepends, true)
appendArray("Optional dependencies", entry.Info.OptionalDepends, true) appendArray("Optional dependencies", entry.Info.OptionalDepends, true)
dependants := entry.GetEntryDependants() dependants := entry.GetEntryDependants()
if len(dependants) > 0 { if len(dependants) > 0 {
+68 -13
View File
@@ -10,7 +10,7 @@ type pkgInstallationReason struct {
InstallationReason InstallationReason InstallationReason InstallationReason
} }
func (pkgInfo *PackageInfo) GetDependencies(includeMakeDepends, includeOptionalDepends bool) []pkgInstallationReason { func (pkgInfo *PackageInfo) GetDependencies(includeMakeDepends, includeRuntimeDepends, includeOptionalDepends bool) []pkgInstallationReason {
allDepends := make([]pkgInstallationReason, 0) allDepends := make([]pkgInstallationReason, 0)
for _, depend := range pkgInfo.Depends { for _, depend := range pkgInfo.Depends {
@@ -35,6 +35,18 @@ func (pkgInfo *PackageInfo) GetDependencies(includeMakeDepends, includeOptionalD
} }
} }
} }
if includeRuntimeDepends {
for _, depend := range pkgInfo.RuntimeDepends {
if !slices.ContainsFunc(allDepends, func(p pkgInstallationReason) bool {
return p.PkgName == depend
}) {
allDepends = append(allDepends, pkgInstallationReason{
PkgName: depend,
InstallationReason: InstallationReasonDependency,
})
}
}
}
if includeMakeDepends { if includeMakeDepends {
for _, depend := range pkgInfo.MakeDepends { for _, depend := range pkgInfo.MakeDepends {
if !slices.ContainsFunc(allDepends, func(p pkgInstallationReason) bool { if !slices.ContainsFunc(allDepends, func(p pkgInstallationReason) bool {
@@ -56,23 +68,23 @@ func (pkgInfo *PackageInfo) GetDependencies(includeMakeDepends, includeOptionalD
return allDepends return allDepends
} }
func (pkgInfo *PackageInfo) GetDependenciesRecursive(includeMakeDepends bool, rootDir string) (resolved []string) { func (pkgInfo *PackageInfo) GetDependenciesRecursive(includeRuntimeDepends, includeMakeDepends bool, rootDir string) (resolved []string) {
// Initialize slices // Initialize slices
resolved = make([]string, 0) resolved = make([]string, 0)
unresolved := make([]string, 0) unresolved := make([]string, 0)
// Call unexported function // Call unexported function
pkgInfo.getDependenciesRecursive(&resolved, &unresolved, includeMakeDepends, rootDir) pkgInfo.getDependenciesRecursive(&resolved, &unresolved, includeRuntimeDepends, includeMakeDepends, rootDir)
return resolved return resolved
} }
func (pkgInfo *PackageInfo) getDependenciesRecursive(resolved *[]string, unresolved *[]string, includeMakeDepends bool, rootDir string) { func (pkgInfo *PackageInfo) getDependenciesRecursive(resolved *[]string, unresolved *[]string, includeRuntimeDepends, includeMakeDepends bool, rootDir string) {
// Add current package name to unresolved slice // Add current package name to unresolved slice
*unresolved = append(*unresolved, pkgInfo.Name) *unresolved = append(*unresolved, pkgInfo.Name)
// Loop through all dependencies // Loop through all dependencies
for _, pkgIR := range pkgInfo.GetDependencies(includeMakeDepends, false) { for _, pkgIR := range pkgInfo.GetDependencies(includeMakeDepends, includeRuntimeDepends, false) {
depend := pkgIR.PkgName depend := pkgIR.PkgName
if isVirtual, p := IsVirtualPackage(depend, rootDir); isVirtual { if isVirtual, p := IsVirtualPackage(depend, rootDir); isVirtual {
@@ -91,7 +103,7 @@ func (pkgInfo *PackageInfo) getDependenciesRecursive(resolved *[]string, unresol
dependInfo := GetPackageInfo(depend, rootDir) dependInfo := GetPackageInfo(depend, rootDir)
if dependInfo != nil { if dependInfo != nil {
dependInfo.getDependenciesRecursive(resolved, unresolved, includeMakeDepends, rootDir) dependInfo.getDependenciesRecursive(resolved, unresolved, includeRuntimeDepends, includeMakeDepends, rootDir)
} }
} }
} }
@@ -101,13 +113,16 @@ func (pkgInfo *PackageInfo) getDependenciesRecursive(resolved *[]string, unresol
*unresolved = stringSliceRemove(*unresolved, pkgInfo.Name) *unresolved = stringSliceRemove(*unresolved, pkgInfo.Name)
} }
func ResolveAllPackageDependenciesFromDatabases(pkgInfo *PackageInfo, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) (resolved []pkgInstallationReason, unresolved []string) { func ResolveAllPackageDependenciesFromDatabases(pkgInfo *PackageInfo, resolvedVirtualPkgs map[string]string, checkMake, checkRuntime, checkOptional, ignoreInstalled, verbose bool, rootDir string) (resolved []pkgInstallationReason, unresolved []string) {
// Initialize slices // Initialize slices and maps
resolved = make([]pkgInstallationReason, 0) resolved = make([]pkgInstallationReason, 0)
unresolved = make([]string, 0) unresolved = make([]string, 0)
if resolvedVirtualPkgs == nil {
resolvedVirtualPkgs = make(map[string]string)
}
// Call unexported function // Call unexported function
resolvePackageDependenciesFromDatabase(&resolved, &unresolved, pkgInfo, checkMake, checkOptional, ignoreInstalled, verbose, rootDir) resolvePackageDependenciesFromDatabase(&resolved, &unresolved, resolvedVirtualPkgs, pkgInfo, checkMake, checkRuntime, checkOptional, ignoreInstalled, verbose, rootDir)
// Remove main package from unresolved slice // Remove main package from unresolved slice
unresolved = stringSliceRemove(unresolved, pkgInfo.Name) unresolved = stringSliceRemove(unresolved, pkgInfo.Name)
@@ -115,12 +130,18 @@ func ResolveAllPackageDependenciesFromDatabases(pkgInfo *PackageInfo, checkMake,
return resolved, unresolved return resolved, unresolved
} }
func resolvePackageDependenciesFromDatabase(resolved *[]pkgInstallationReason, unresolved *[]string, pkgInfo *PackageInfo, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) { func resolvePackageDependenciesFromDatabase(resolved *[]pkgInstallationReason, unresolved *[]string, resolvedVirtualPkgs map[string]string, pkgInfo *PackageInfo, checkMake, checkRuntime, checkOptional, ignoreInstalled, verbose bool, rootDir string) {
// Add current package name to unresolved slice // Add current package name to unresolved slice
*unresolved = append(*unresolved, pkgInfo.Name) *unresolved = append(*unresolved, pkgInfo.Name)
for _, vpkg := range pkgInfo.Provides {
if _, ok := resolvedVirtualPkgs[vpkg]; !ok {
resolvedVirtualPkgs[vpkg] = pkgInfo.Name
}
}
// Loop through all dependencies // Loop through all dependencies
for _, pkgIR := range pkgInfo.GetDependencies(pkgInfo.Type == "source", checkOptional) { for _, pkgIR := range pkgInfo.GetDependencies(pkgInfo.Type == "source", checkRuntime, checkOptional) {
// Skip dependency if it has already been resolved // Skip dependency if it has already been resolved
if slices.ContainsFunc(*resolved, func(p pkgInstallationReason) bool { if slices.ContainsFunc(*resolved, func(p pkgInstallationReason) bool {
return p.PkgName == pkgIR.PkgName return p.PkgName == pkgIR.PkgName
@@ -151,7 +172,25 @@ func resolvePackageDependenciesFromDatabase(resolved *[]pkgInstallationReason, u
var entry *BPMDatabaseEntry var entry *BPMDatabaseEntry
entry, _, err = GetDatabaseEntry(pkgIR.PkgName) entry, _, err = GetDatabaseEntry(pkgIR.PkgName)
if err != nil { if err != nil {
if entry = ResolveVirtualPackage(pkgIR.PkgName); entry == nil { if resolvedVirtualPkg, ok := resolvedVirtualPkgs[pkgIR.PkgName]; ok {
// Virtual package already resolved
// Move dependency from the unresolved slice to the resolved slice
if !slices.ContainsFunc(*resolved, func(p pkgInstallationReason) bool {
return p.PkgName == resolvedVirtualPkg
}) {
*resolved = append(*resolved, pkgInstallationReason{
PkgName: resolvedVirtualPkg,
InstallationReason: pkgIR.InstallationReason,
})
}
*unresolved = stringSliceRemove(*unresolved, resolvedVirtualPkg)
continue
} else if entry = ResolveVirtualPackage(pkgIR.PkgName); entry != nil {
// Virtual package found in database
} else {
// Virtual package not found
if !slices.Contains(*unresolved, pkgIR.PkgName) { if !slices.Contains(*unresolved, pkgIR.PkgName) {
*unresolved = append(*unresolved, pkgIR.PkgName) *unresolved = append(*unresolved, pkgIR.PkgName)
} }
@@ -160,7 +199,7 @@ func resolvePackageDependenciesFromDatabase(resolved *[]pkgInstallationReason, u
} }
// Resolve the dependencies of this dependency // Resolve the dependencies of this dependency
resolvePackageDependenciesFromDatabase(resolved, unresolved, entry.Info, checkMake, false, ignoreInstalled, verbose, rootDir) resolvePackageDependenciesFromDatabase(resolved, unresolved, resolvedVirtualPkgs, entry.Info, checkMake, checkRuntime, false, ignoreInstalled, verbose, rootDir)
// Move dependency from the unresolved slice to the resolved slice // Move dependency from the unresolved slice to the resolved slice
if !slices.ContainsFunc(*resolved, func(p pkgInstallationReason) bool { if !slices.ContainsFunc(*resolved, func(p pkgInstallationReason) bool {
@@ -197,6 +236,14 @@ func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string) (dependants []s
continue continue
} }
// Add installed package to list if its runtime dependencies include pkgName
if slices.ContainsFunc(installedPkg.RuntimeDepends, func(n string) bool {
return n == pkgInfo.Name
}) {
dependants = append(dependants, installedPkg.Name)
continue
}
// Loop through each virtual package // Loop through each virtual package
for _, vpkg := range pkgInfo.Provides { for _, vpkg := range pkgInfo.Provides {
// Add installed package to list if its dependencies contain a provided virtual package // Add installed package to list if its dependencies contain a provided virtual package
@@ -206,6 +253,14 @@ func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string) (dependants []s
dependants = append(dependants, installedPkg.Name) dependants = append(dependants, installedPkg.Name)
break break
} }
// Add installed package to list if its runtime dependencies contain a provided virtual package
if slices.ContainsFunc(installedPkg.RuntimeDepends, func(n string) bool {
return n == vpkg
}) {
dependants = append(dependants, installedPkg.Name)
break
}
} }
} }
+3 -3
View File
@@ -20,7 +20,7 @@ const (
) )
// InstallPackages installs the specified packages into the given root directory by fetching them from databases or directly from local bpm archives // InstallPackages installs the specified packages into the given root directory by fetching them from databases or directly from local bpm archives
func InstallPackages(rootDir string, forceInstallationReason InstallationReason, reinstallMethod ReinstallMethod, installOptionalDependencies, forceInstallation, verbose bool, packages ...string) (operation *BPMOperation, err error) { func InstallPackages(rootDir string, forceInstallationReason InstallationReason, reinstallMethod ReinstallMethod, installRuntimeDependencies, installOptionalDependencies, forceInstallation, verbose bool, packages ...string) (operation *BPMOperation, err error) {
// Setup operation struct // Setup operation struct
operation = &BPMOperation{ operation = &BPMOperation{
Actions: make([]OperationAction, 0), Actions: make([]OperationAction, 0),
@@ -131,7 +131,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
} }
// Resolve dependencies // Resolve dependencies
err = operation.ResolveDependencies(reinstallMethod == ReinstallMethodAll, installOptionalDependencies, verbose) err = operation.ResolveDependencies(reinstallMethod == ReinstallMethodAll, installRuntimeDependencies, installOptionalDependencies, verbose)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not resolve dependencies: %s", err) return nil, fmt.Errorf("could not resolve dependencies: %s", err)
} }
@@ -429,7 +429,7 @@ func UpdatePackages(rootDir string, syncDatabase bool, allowDowngrades bool, ins
} }
// Check for new dependencies in updated packages // Check for new dependencies in updated packages
err = operation.ResolveDependencies(false, installOptionalDependencies, verbose) err = operation.ResolveDependencies(false, true, installOptionalDependencies, verbose)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not resolve dependencies: %s", err) return nil, fmt.Errorf("could not resolve dependencies: %s", err)
} }
+6 -4
View File
@@ -15,6 +15,7 @@ type BPMOperation struct {
Actions []OperationAction Actions []OperationAction
UnresolvedDepends []string UnresolvedDepends []string
Changes map[string]string Changes map[string]string
CompilationJobs int
RootDir string RootDir string
compiledPackages map[string]string compiledPackages map[string]string
@@ -129,8 +130,9 @@ func (operation *BPMOperation) GetFinalActionSize(rootDir string) int64 {
return ret return ret
} }
func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, installOptionalDependencies, verbose bool) error { func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, installRuntimeDependencies, installOptionalDependencies, verbose bool) error {
pos := 0 pos := 0
resolvedVirtualPkgs := make(map[string]string, 0)
for _, value := range slices.Clone(operation.Actions) { for _, value := range slices.Clone(operation.Actions) {
var pkgInfo *PackageInfo var pkgInfo *PackageInfo
if value.GetActionType() == "install" { if value.GetActionType() == "install" {
@@ -144,7 +146,7 @@ func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, instal
continue continue
} }
resolved, unresolved := ResolveAllPackageDependenciesFromDatabases(pkgInfo, pkgInfo.Type == "source", installOptionalDependencies, !reinstallDependencies, verbose, operation.RootDir) resolved, unresolved := ResolveAllPackageDependenciesFromDatabases(pkgInfo, resolvedVirtualPkgs, pkgInfo.Type == "source", installRuntimeDependencies, installOptionalDependencies, !reinstallDependencies, verbose, operation.RootDir)
operation.UnresolvedDepends = append(operation.UnresolvedDepends, unresolved...) operation.UnresolvedDepends = append(operation.UnresolvedDepends, unresolved...)
@@ -230,7 +232,7 @@ func (operation *BPMOperation) Cleanup(cleanupMakeDepends bool) error {
} }
keepPackages = append(keepPackages, pkg.Name) keepPackages = append(keepPackages, pkg.Name)
resolved := pkg.GetDependenciesRecursive(!cleanupMakeDepends, operation.RootDir) resolved := pkg.GetDependenciesRecursive(true, !cleanupMakeDepends, operation.RootDir)
for _, value := range resolved { for _, value := range resolved {
if !slices.Contains(keepPackages, value) && !slices.Contains(MainBPMConfig.IgnorePackages, value) { if !slices.Contains(keepPackages, value) && !slices.Contains(MainBPMConfig.IgnorePackages, value) {
keepPackages = append(keepPackages, value) keepPackages = append(keepPackages, value)
@@ -670,7 +672,7 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
// Compile source package if not compiled already // Compile source package if not compiled already
if _, ok := operation.compiledPackages[pkgNameToInstall]; !ok { if _, ok := operation.compiledPackages[pkgNameToInstall]; !ok {
outputBpmPackages, err := CompileSourcePackage(value.File, compiledDir, false, false, verbose) outputBpmPackages, err := CompileSourcePackage(value.File, compiledDir, operation.CompilationJobs, false, false, verbose)
if err != nil { if err != nil {
return fmt.Errorf("could not compile source package (%s): %s\n", value.File, err) return fmt.Errorf("could not compile source package (%s): %s\n", value.File, err)
} }
+6
View File
@@ -32,11 +32,13 @@ type PackageInfo struct {
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"`
Maintainers []string `yaml:"maintainers,omitempty"`
Arch string `yaml:"architecture,omitempty"` Arch string `yaml:"architecture,omitempty"`
OutputArch string `yaml:"output_architecture,omitempty"` OutputArch string `yaml:"output_architecture,omitempty"`
Type string `yaml:"type,omitempty"` Type string `yaml:"type,omitempty"`
Keep []string `yaml:"keep,omitempty"` Keep []string `yaml:"keep,omitempty"`
Depends []string `yaml:"depends,omitempty"` Depends []string `yaml:"depends,omitempty"`
RuntimeDepends []string `yaml:"runtime_depends,omitempty"`
OptionalDepends []string `yaml:"optional_depends,omitempty"` OptionalDepends []string `yaml:"optional_depends,omitempty"`
MakeDepends []string `yaml:"make_depends,omitempty"` MakeDepends []string `yaml:"make_depends,omitempty"`
Conflicts []string `yaml:"conflicts,omitempty"` Conflicts []string `yaml:"conflicts,omitempty"`
@@ -457,6 +459,7 @@ func ReadPackageInfo(contents string) (*PackageInfo, error) {
OutputArch: GetArch(), OutputArch: GetArch(),
Keep: make([]string, 0), Keep: make([]string, 0),
Depends: make([]string, 0), Depends: make([]string, 0),
RuntimeDepends: make([]string, 0),
MakeDepends: make([]string, 0), MakeDepends: make([]string, 0),
OptionalDepends: make([]string, 0), OptionalDepends: make([]string, 0),
Conflicts: make([]string, 0), Conflicts: make([]string, 0),
@@ -555,6 +558,7 @@ func (pkgInfo *PackageInfo) CreateReadableInfo(rootDir string) string {
if pkgInfo.License != "" { if pkgInfo.License != "" {
ret = append(ret, "License: "+pkgInfo.License) ret = append(ret, "License: "+pkgInfo.License)
} }
appendArray("Maintainers", pkgInfo.Maintainers)
ret = append(ret, "Architecture: "+pkgInfo.Arch) ret = append(ret, "Architecture: "+pkgInfo.Arch)
if pkgInfo.Type == "source" && pkgInfo.OutputArch != "" && pkgInfo.OutputArch != GetArch() { if pkgInfo.Type == "source" && pkgInfo.OutputArch != "" && pkgInfo.OutputArch != GetArch() {
ret = append(ret, "Output architecture: "+pkgInfo.Arch) ret = append(ret, "Output architecture: "+pkgInfo.Arch)
@@ -562,8 +566,10 @@ func (pkgInfo *PackageInfo) CreateReadableInfo(rootDir string) string {
ret = append(ret, "Type: "+pkgInfo.Type) ret = append(ret, "Type: "+pkgInfo.Type)
appendArray("Dependencies", pkgInfo.Depends) appendArray("Dependencies", pkgInfo.Depends)
if pkgInfo.Type == "source" { if pkgInfo.Type == "source" {
appendArray("Runtime Dependencies", pkgInfo.RuntimeDepends)
appendArray("Make Dependencies", pkgInfo.MakeDepends) appendArray("Make Dependencies", pkgInfo.MakeDepends)
} }
appendArray("Runtime dependencies", pkgInfo.RuntimeDepends)
appendArray("Optional dependencies", pkgInfo.OptionalDepends) appendArray("Optional dependencies", pkgInfo.OptionalDepends)
dependants := pkgInfo.GetPackageDependants(rootDir) dependants := pkgInfo.GetPackageDependants(rootDir)
if len(dependants) > 0 { if len(dependants) > 0 {