Rework runtime dependency system

This commit is contained in:
2026-01-06 19:35:42 +02:00
parent fd646a820d
commit 72f17f8954
7 changed files with 53 additions and 25 deletions
+6 -4
View File
@@ -87,6 +87,7 @@ 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")
@@ -480,6 +481,7 @@ 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")
@@ -543,7 +545,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
@@ -1163,9 +1165,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 +1200,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 {
-4
View File
@@ -344,10 +344,6 @@ func CompileSourcePackage(archiveFilename, outputDirectory string, skipChecks, k
pkgInfo.Arch = pkg.OutputArch pkgInfo.Arch = pkg.OutputArch
pkgInfo.OutputArch = "" pkgInfo.OutputArch = ""
// Add runtime dependencies to common dependencies
pkgInfo.Depends = removeDuplicates(append(pkgInfo.Depends, pkgInfo.RuntimeDepends...))
pkgInfo.RuntimeDepends = nil
// Remove split package and downloads fields // Remove split package and downloads fields
pkgInfo.SplitPackages = nil pkgInfo.SplitPackages = nil
pkgInfo.Downloads = nil pkgInfo.Downloads = nil
+1
View File
@@ -356,6 +356,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 {
+39 -11
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,13 @@ 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, checkMake, checkRuntime, checkOptional, ignoreInstalled, verbose bool, rootDir string) (resolved []pkgInstallationReason, unresolved []string) {
// Initialize slices // Initialize slices
resolved = make([]pkgInstallationReason, 0) resolved = make([]pkgInstallationReason, 0)
unresolved = make([]string, 0) unresolved = make([]string, 0)
// Call unexported function // Call unexported function
resolvePackageDependenciesFromDatabase(&resolved, &unresolved, pkgInfo, checkMake, checkOptional, ignoreInstalled, verbose, rootDir) resolvePackageDependenciesFromDatabase(&resolved, &unresolved, 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 +127,12 @@ 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, 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)
// 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
@@ -160,7 +172,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, 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 +209,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 +226,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)
} }
+3 -3
View File
@@ -129,7 +129,7 @@ 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
for _, value := range slices.Clone(operation.Actions) { for _, value := range slices.Clone(operation.Actions) {
var pkgInfo *PackageInfo var pkgInfo *PackageInfo
@@ -144,7 +144,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, pkgInfo.Type == "source", installRuntimeDependencies, installOptionalDependencies, !reinstallDependencies, verbose, operation.RootDir)
operation.UnresolvedDepends = append(operation.UnresolvedDepends, unresolved...) operation.UnresolvedDepends = append(operation.UnresolvedDepends, unresolved...)
@@ -230,7 +230,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)
+1
View File
@@ -567,6 +567,7 @@ func (pkgInfo *PackageInfo) CreateReadableInfo(rootDir string) string {
appendArray("Runtime Dependencies", pkgInfo.RuntimeDepends) 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 {