mirror of
https://github.com/EnumeratedDev/bpm.git
synced 2026-09-16 10:36:12 +00:00
Greatly simplify dependency resolution
This commit is contained in:
@@ -318,3 +318,63 @@ func (pkgInfo *PackageInfo) GetPackageOptionalDependants(rootDir string) (depend
|
||||
|
||||
return dependants
|
||||
}
|
||||
|
||||
type ResolvedPackage struct {
|
||||
DatabaseEntry *BPMDatabaseEntry
|
||||
InstallationReason InstallationReason
|
||||
}
|
||||
|
||||
func ResolveDependencies(pkgInfo *PackageInfo, resolvedVirtualPackages map[string]string, includeOptionalDepends bool, rootDir string) (resolved []ResolvedPackage, unresolved []string) {
|
||||
visited := make([]string, 0)
|
||||
|
||||
var dfs func(resolvedPkg *PackageInfo)
|
||||
dfs = func(pkgInfo *PackageInfo) {
|
||||
checkDependencies := func(dependencies []string, installationReason InstallationReason) {
|
||||
for _, depend := range dependencies {
|
||||
// Ignore if package is already installed
|
||||
if IsPackageInstalled(depend, rootDir) {
|
||||
continue
|
||||
} else if providers := GetVirtualPackageInfo(depend, rootDir); len(providers) > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find database entry for dependency
|
||||
var dependEntry *BPMDatabaseEntry
|
||||
if resolvedVpkg, ok := resolvedVirtualPackages[depend]; ok {
|
||||
dependEntry, _, _ = GetDatabaseEntry(resolvedVpkg)
|
||||
} else if entry, _, _ := GetDatabaseEntry(depend); entry != nil {
|
||||
dependEntry = entry
|
||||
} else if providers := GetDatabaseVirtualPackageEntry(depend); len(providers) > 0 {
|
||||
dependEntry = providers[0]
|
||||
}
|
||||
|
||||
if dependEntry == nil {
|
||||
unresolved = append(unresolved, depend)
|
||||
continue
|
||||
}
|
||||
|
||||
if !slices.Contains(visited, dependEntry.Info.Name) {
|
||||
dfs(dependEntry.Info)
|
||||
resolved = append(resolved, ResolvedPackage{DatabaseEntry: dependEntry, InstallationReason: installationReason})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visited = append(visited, pkgInfo.Name)
|
||||
|
||||
checkDependencies(pkgInfo.Depends, InstallationReasonDependency)
|
||||
if pkgInfo.Type == "binary" {
|
||||
checkDependencies(pkgInfo.RuntimeDepends, InstallationReasonDependency)
|
||||
} else if pkgInfo.Type == "source" {
|
||||
checkDependencies(pkgInfo.MakeDepends, InstallationReasonMakeDependency)
|
||||
checkDependencies(pkgInfo.CheckDepends, InstallationReasonMakeDependency)
|
||||
}
|
||||
if includeOptionalDepends {
|
||||
checkDependencies(pkgInfo.OptionalDepends, InstallationReasonManual)
|
||||
}
|
||||
}
|
||||
|
||||
dfs(pkgInfo)
|
||||
|
||||
return resolved, unresolved
|
||||
}
|
||||
|
||||
@@ -132,10 +132,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
||||
}
|
||||
|
||||
// Resolve dependencies
|
||||
err = operation.ResolveDependencies(reinstallMethod == ReinstallMethodAll, installRuntimeDependencies, installOptionalDependencies, verbose)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not resolve dependencies: %s", err)
|
||||
}
|
||||
operation.ResolveDependencies(reinstallMethod == ReinstallMethodAll, installOptionalDependencies)
|
||||
if len(operation.UnresolvedDepends) != 0 {
|
||||
if !forceInstallation {
|
||||
return nil, DependencyNotFoundErr{operation.UnresolvedDepends}
|
||||
@@ -431,10 +428,7 @@ func UpdatePackages(rootDir string, syncDatabase bool, allowDowngrades bool, ins
|
||||
}
|
||||
|
||||
// Check for new dependencies in updated packages
|
||||
err = operation.ResolveDependencies(false, true, installOptionalDependencies, verbose)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not resolve dependencies: %s", err)
|
||||
}
|
||||
operation.ResolveDependencies(false, installOptionalDependencies)
|
||||
if len(operation.UnresolvedDepends) != 0 {
|
||||
if !forceInstallation {
|
||||
return nil, DependencyNotFoundErr{operation.UnresolvedDepends}
|
||||
|
||||
+37
-16
@@ -131,9 +131,9 @@ func (operation *BPMOperation) GetFinalActionSize(rootDir string) int64 {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, installRuntimeDependencies, installOptionalDependencies, verbose bool) error {
|
||||
pos := 0
|
||||
resolvedVirtualPkgs := make(map[string]string, 0)
|
||||
func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, installOptionalDependencies bool) {
|
||||
// Discover resolved virtual packages
|
||||
resolvedVirtualPackages := make(map[string]string)
|
||||
for _, value := range slices.Clone(operation.Actions) {
|
||||
var pkgInfo *PackageInfo
|
||||
if value.GetActionType() == "install" {
|
||||
@@ -143,34 +143,55 @@ func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, instal
|
||||
action := value.(*FetchPackageAction)
|
||||
pkgInfo = action.DatabaseEntry.Info
|
||||
} else {
|
||||
pos++
|
||||
continue
|
||||
}
|
||||
|
||||
resolved, unresolved := ResolveAllPackageDependenciesFromDatabases(pkgInfo, resolvedVirtualPkgs, pkgInfo.Type == "source", pkgInfo.Type == "source" && operation.RunChecks, installRuntimeDependencies, installOptionalDependencies, !reinstallDependencies, verbose, operation.RootDir)
|
||||
for _, vpkg := range pkgInfo.Provides {
|
||||
if _, ok := resolvedVirtualPackages[vpkg]; !ok {
|
||||
resolvedVirtualPackages[vpkg] = pkgInfo.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Discover all dependencies
|
||||
pos := 0
|
||||
for _, value := range slices.Clone(operation.Actions) {
|
||||
var pkgInfo *PackageInfo
|
||||
if value.GetActionType() == "install" {
|
||||
action := value.(*InstallPackageAction)
|
||||
pkgInfo = action.BpmPackage.PkgInfo
|
||||
} else if value.GetActionType() == "fetch" {
|
||||
action := value.(*FetchPackageAction)
|
||||
pkgInfo = action.DatabaseEntry.Info
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
resolved, unresolved := ResolveDependencies(pkgInfo, resolvedVirtualPackages, installOptionalDependencies, operation.RootDir)
|
||||
|
||||
// Append unresolved dependencies
|
||||
operation.UnresolvedDepends = append(operation.UnresolvedDepends, unresolved...)
|
||||
operation.UnresolvedDepends = removeDuplicates(operation.UnresolvedDepends)
|
||||
|
||||
for _, resolvedPkg := range resolved {
|
||||
if !operation.ActionsContainPackage(resolvedPkg.PkgName) && resolvedPkg.PkgName != pkgInfo.Name {
|
||||
if !reinstallDependencies && IsPackageInstalled(resolvedPkg.PkgName, operation.RootDir) {
|
||||
continue
|
||||
}
|
||||
entry, _, err := GetDatabaseEntry(resolvedPkg.PkgName)
|
||||
if err != nil {
|
||||
return errors.New("could not get database entry for package (" + resolvedPkg.PkgName + ")")
|
||||
}
|
||||
if !operation.ActionsContainPackage(resolvedPkg.DatabaseEntry.Info.Name) && resolvedPkg.DatabaseEntry.Info.Name != pkgInfo.Name {
|
||||
operation.InsertActionAt(pos, &FetchPackageAction{
|
||||
InstallationReason: resolvedPkg.InstallationReason,
|
||||
DatabaseEntry: entry,
|
||||
DatabaseEntry: resolvedPkg.DatabaseEntry,
|
||||
})
|
||||
|
||||
for _, vpkg := range resolvedPkg.DatabaseEntry.Info.Provides {
|
||||
if _, ok := resolvedVirtualPackages[vpkg]; !ok {
|
||||
resolvedVirtualPackages[vpkg] = resolvedPkg.DatabaseEntry.Info.Name
|
||||
}
|
||||
}
|
||||
|
||||
pos++
|
||||
}
|
||||
}
|
||||
|
||||
pos++
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (operation *BPMOperation) RemoveNeededPackages() error {
|
||||
|
||||
Reference in New Issue
Block a user