mirror of
https://github.com/EnumeratedDev/bpm.git
synced 2026-09-16 02:26: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
|
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
|
// Resolve dependencies
|
||||||
err = operation.ResolveDependencies(reinstallMethod == ReinstallMethodAll, installRuntimeDependencies, installOptionalDependencies, verbose)
|
operation.ResolveDependencies(reinstallMethod == ReinstallMethodAll, installOptionalDependencies)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not resolve dependencies: %s", err)
|
|
||||||
}
|
|
||||||
if len(operation.UnresolvedDepends) != 0 {
|
if len(operation.UnresolvedDepends) != 0 {
|
||||||
if !forceInstallation {
|
if !forceInstallation {
|
||||||
return nil, DependencyNotFoundErr{operation.UnresolvedDepends}
|
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
|
// Check for new dependencies in updated packages
|
||||||
err = operation.ResolveDependencies(false, true, installOptionalDependencies, verbose)
|
operation.ResolveDependencies(false, installOptionalDependencies)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not resolve dependencies: %s", err)
|
|
||||||
}
|
|
||||||
if len(operation.UnresolvedDepends) != 0 {
|
if len(operation.UnresolvedDepends) != 0 {
|
||||||
if !forceInstallation {
|
if !forceInstallation {
|
||||||
return nil, DependencyNotFoundErr{operation.UnresolvedDepends}
|
return nil, DependencyNotFoundErr{operation.UnresolvedDepends}
|
||||||
|
|||||||
+39
-18
@@ -131,9 +131,9 @@ func (operation *BPMOperation) GetFinalActionSize(rootDir string) int64 {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, installRuntimeDependencies, installOptionalDependencies, verbose bool) error {
|
func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, installOptionalDependencies bool) {
|
||||||
pos := 0
|
// Discover resolved virtual packages
|
||||||
resolvedVirtualPkgs := make(map[string]string, 0)
|
resolvedVirtualPackages := make(map[string]string)
|
||||||
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" {
|
||||||
@@ -143,34 +143,55 @@ func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, instal
|
|||||||
action := value.(*FetchPackageAction)
|
action := value.(*FetchPackageAction)
|
||||||
pkgInfo = action.DatabaseEntry.Info
|
pkgInfo = action.DatabaseEntry.Info
|
||||||
} else {
|
} else {
|
||||||
pos++
|
|
||||||
continue
|
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 = append(operation.UnresolvedDepends, unresolved...)
|
||||||
|
operation.UnresolvedDepends = removeDuplicates(operation.UnresolvedDepends)
|
||||||
|
|
||||||
for _, resolvedPkg := range resolved {
|
for _, resolvedPkg := range resolved {
|
||||||
if !operation.ActionsContainPackage(resolvedPkg.PkgName) && resolvedPkg.PkgName != pkgInfo.Name {
|
if !operation.ActionsContainPackage(resolvedPkg.DatabaseEntry.Info.Name) && resolvedPkg.DatabaseEntry.Info.Name != 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 + ")")
|
|
||||||
}
|
|
||||||
operation.InsertActionAt(pos, &FetchPackageAction{
|
operation.InsertActionAt(pos, &FetchPackageAction{
|
||||||
InstallationReason: resolvedPkg.InstallationReason,
|
InstallationReason: resolvedPkg.InstallationReason,
|
||||||
DatabaseEntry: entry,
|
DatabaseEntry: resolvedPkg.DatabaseEntry,
|
||||||
})
|
})
|
||||||
pos++
|
|
||||||
|
for _, vpkg := range resolvedPkg.DatabaseEntry.Info.Provides {
|
||||||
|
if _, ok := resolvedVirtualPackages[vpkg]; !ok {
|
||||||
|
resolvedVirtualPackages[vpkg] = resolvedPkg.DatabaseEntry.Info.Name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pos++
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
pos++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) RemoveNeededPackages() error {
|
func (operation *BPMOperation) RemoveNeededPackages() error {
|
||||||
|
|||||||
Reference in New Issue
Block a user