mirror of
https://github.com/EnumeratedDev/bpm.git
synced 2026-09-16 10:36:12 +00:00
Fix dependency installation order
This commit is contained in:
+3
-3
@@ -598,9 +598,9 @@ func resolveCommand() {
|
|||||||
|
|
||||||
// Get direct runtime and make dependencies
|
// Get direct runtime 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) {
|
||||||
if !slices.Contains(totalDepends, depend) {
|
if !slices.Contains(totalDepends, depend.PkgName) {
|
||||||
totalDepends = append(totalDepends, depend)
|
totalDepends = append(totalDepends, depend.PkgName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+96
-44
@@ -6,23 +6,45 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (pkgInfo *PackageInfo) GetDependencies(includeMakeDepends, includeOptionalDepends bool) map[string]InstallationReason {
|
type pkgInstallationReason struct {
|
||||||
allDepends := make(map[string]InstallationReason)
|
PkgName string
|
||||||
|
InstallationReason InstallationReason
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pkgInfo *PackageInfo) GetDependencies(includeMakeDepends, includeOptionalDepends bool) []pkgInstallationReason {
|
||||||
|
allDepends := make([]pkgInstallationReason, 0)
|
||||||
|
|
||||||
for _, depend := range pkgInfo.Depends {
|
for _, depend := range pkgInfo.Depends {
|
||||||
allDepends[depend] = InstallationReasonDependency
|
if !slices.ContainsFunc(allDepends, func(p pkgInstallationReason) bool {
|
||||||
|
return p.PkgName == depend
|
||||||
|
}) {
|
||||||
|
allDepends = append(allDepends, pkgInstallationReason{
|
||||||
|
PkgName: depend,
|
||||||
|
InstallationReason: InstallationReasonDependency,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if includeOptionalDepends {
|
if includeOptionalDepends {
|
||||||
for _, depend := range pkgInfo.OptionalDepends {
|
for _, depend := range pkgInfo.OptionalDepends {
|
||||||
if _, ok := allDepends[depend]; !ok {
|
if !slices.ContainsFunc(allDepends, func(p pkgInstallationReason) bool {
|
||||||
allDepends[depend] = InstallationReasonDependency
|
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 _, ok := allDepends[depend]; !ok {
|
if !slices.ContainsFunc(allDepends, func(p pkgInstallationReason) bool {
|
||||||
allDepends[depend] = InstallationReasonMakeDependency
|
return p.PkgName == depend
|
||||||
|
}) {
|
||||||
|
allDepends = append(allDepends, pkgInstallationReason{
|
||||||
|
PkgName: depend,
|
||||||
|
InstallationReason: InstallationReasonMakeDependency,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,10 +67,13 @@ func (pkgInfo *PackageInfo) getAllDependencies(resolved *[]string, unresolved *[
|
|||||||
*unresolved = append(*unresolved, pkgInfo.Name)
|
*unresolved = append(*unresolved, pkgInfo.Name)
|
||||||
|
|
||||||
// Loop through all dependencies
|
// Loop through all dependencies
|
||||||
for depend := range pkgInfo.GetDependencies(includeMakeDepends, includeOptionalDepends) {
|
for _, pkgIR := range pkgInfo.GetDependencies(includeMakeDepends, includeOptionalDepends) {
|
||||||
|
depend := pkgIR.PkgName
|
||||||
|
|
||||||
if isVirtual, p := IsVirtualPackage(depend, rootDir); isVirtual {
|
if isVirtual, p := IsVirtualPackage(depend, rootDir); isVirtual {
|
||||||
depend = p
|
depend = p
|
||||||
}
|
}
|
||||||
|
|
||||||
if !slices.Contains(*resolved, depend) {
|
if !slices.Contains(*resolved, depend) {
|
||||||
// Add current dependency to resolved slice when circular dependency is detected
|
// Add current dependency to resolved slice when circular dependency is detected
|
||||||
if slices.Contains(*unresolved, depend) {
|
if slices.Contains(*unresolved, depend) {
|
||||||
@@ -71,55 +96,78 @@ func (pkgInfo *PackageInfo) getAllDependencies(resolved *[]string, unresolved *[
|
|||||||
*unresolved = stringSliceRemove(*unresolved, pkgInfo.Name)
|
*unresolved = stringSliceRemove(*unresolved, pkgInfo.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ResolveAllPackageDependenciesFromDatabases(pkgInfo *PackageInfo, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) (resolved map[string]InstallationReason, unresolved []string) {
|
func ResolveAllPackageDependenciesFromDatabases(pkgInfo *PackageInfo, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) (resolved []pkgInstallationReason, unresolved []string) {
|
||||||
// Initialize slices
|
// Initialize slices
|
||||||
resolved = make(map[string]InstallationReason)
|
resolved = make([]pkgInstallationReason, 0)
|
||||||
unresolved = make([]string, 0)
|
unresolved = make([]string, 0)
|
||||||
|
|
||||||
// Call unexported function
|
// Call unexported function
|
||||||
resolvePackageDependenciesFromDatabase(resolved, &unresolved, pkgInfo, InstallationReasonDependency, checkMake, checkOptional, ignoreInstalled, verbose, rootDir)
|
resolvePackageDependenciesFromDatabase(&resolved, &unresolved, pkgInfo, checkMake, checkOptional, ignoreInstalled, verbose, rootDir)
|
||||||
|
|
||||||
|
// Remove main package from unresolved slice
|
||||||
|
unresolved = stringSliceRemove(unresolved, pkgInfo.Name)
|
||||||
|
|
||||||
return resolved, unresolved
|
return resolved, unresolved
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolvePackageDependenciesFromDatabase(resolved map[string]InstallationReason, unresolved *[]string, pkgInfo *PackageInfo, installationReason InstallationReason, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) {
|
func resolvePackageDependenciesFromDatabase(resolved *[]pkgInstallationReason, unresolved *[]string, pkgInfo *PackageInfo, checkMake, 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 depend, ir := range pkgInfo.GetDependencies(pkgInfo.Type == "source", checkOptional) {
|
for _, pkgIR := range pkgInfo.GetDependencies(pkgInfo.Type == "source", checkOptional) {
|
||||||
if _, ok := resolved[depend]; !ok {
|
// Skip dependency if it has already been resolved
|
||||||
// Add current dependency to resolved slice when circular dependency is detected
|
if slices.ContainsFunc(*resolved, func(p pkgInstallationReason) bool {
|
||||||
if slices.Contains(*unresolved, depend) {
|
return p.PkgName == pkgIR.PkgName
|
||||||
if verbose {
|
}) {
|
||||||
fmt.Printf("Circular dependency was detected (%s -> %s). Installing %s first\n", pkgInfo.Name, depend, depend)
|
continue
|
||||||
}
|
|
||||||
if _, ok := resolved[depend]; !ok {
|
|
||||||
resolved[depend] = ir
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
} else if ignoreInstalled && IsPackageProvided(depend, rootDir) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
var entry *BPMDatabaseEntry
|
|
||||||
entry, _, err = GetDatabaseEntry(depend)
|
|
||||||
if err != nil {
|
|
||||||
if entry = ResolveVirtualPackage(depend); entry == nil {
|
|
||||||
if !slices.Contains(*unresolved, depend) {
|
|
||||||
*unresolved = append(*unresolved, depend)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resolvePackageDependenciesFromDatabase(resolved, unresolved, entry.Info, ir, checkMake, checkOptional, ignoreInstalled, verbose, rootDir)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := resolved[pkgInfo.Name]; !ok {
|
// Add current dependency to resolved slice when circular dependency is detected
|
||||||
resolved[pkgInfo.Name] = installationReason
|
if slices.Contains(*unresolved, pkgIR.PkgName) {
|
||||||
|
if verbose {
|
||||||
|
fmt.Printf("Circular dependency was detected (%s -> %s). Installing %s first\n", pkgInfo.Name, pkgIR.PkgName, pkgIR.PkgName)
|
||||||
|
}
|
||||||
|
|
||||||
|
*resolved = append(*resolved, pkgInstallationReason{
|
||||||
|
PkgName: pkgIR.PkgName,
|
||||||
|
InstallationReason: pkgIR.InstallationReason,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip dependency if it is already installed or provided
|
||||||
|
if ignoreInstalled && IsPackageProvided(pkgIR.PkgName, rootDir) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get database entry for dependency
|
||||||
|
var err error
|
||||||
|
var entry *BPMDatabaseEntry
|
||||||
|
entry, _, err = GetDatabaseEntry(pkgIR.PkgName)
|
||||||
|
if err != nil {
|
||||||
|
if entry = ResolveVirtualPackage(pkgIR.PkgName); entry == nil {
|
||||||
|
if !slices.Contains(*unresolved, pkgIR.PkgName) {
|
||||||
|
*unresolved = append(*unresolved, pkgIR.PkgName)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve the dependencies of this dependency
|
||||||
|
resolvePackageDependenciesFromDatabase(resolved, unresolved, entry.Info, checkMake, checkOptional, ignoreInstalled, verbose, rootDir)
|
||||||
|
|
||||||
|
// Move dependency from the unresolved slice to the resolved slice
|
||||||
|
if !slices.ContainsFunc(*resolved, func(p pkgInstallationReason) bool {
|
||||||
|
return p.PkgName == entry.Info.Name
|
||||||
|
}) {
|
||||||
|
*resolved = append(*resolved, pkgInstallationReason{
|
||||||
|
PkgName: entry.Info.Name,
|
||||||
|
InstallationReason: pkgIR.InstallationReason,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
*unresolved = stringSliceRemove(*unresolved, entry.Info.Name)
|
||||||
}
|
}
|
||||||
*unresolved = stringSliceRemove(*unresolved, pkgInfo.Name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPackageDependants(pkgName string, rootDir string) ([]string, error) {
|
func GetPackageDependants(pkgName string, rootDir string) ([]string, error) {
|
||||||
@@ -154,7 +202,9 @@ func GetPackageDependants(pkgName string, rootDir string) ([]string, error) {
|
|||||||
dependencies := installedPkg.PkgInfo.GetDependencies(false, true)
|
dependencies := installedPkg.PkgInfo.GetDependencies(false, true)
|
||||||
|
|
||||||
// Add installed package to list if its dependencies include pkgName
|
// Add installed package to list if its dependencies include pkgName
|
||||||
if _, ok := dependencies[pkgName]; ok {
|
if slices.ContainsFunc(dependencies, func(p pkgInstallationReason) bool {
|
||||||
|
return p.PkgName == pkgName
|
||||||
|
}) {
|
||||||
ret = append(ret, installedPkgName)
|
ret = append(ret, installedPkgName)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -162,7 +212,9 @@ func GetPackageDependants(pkgName string, rootDir string) ([]string, error) {
|
|||||||
// Loop through each virtual package
|
// Loop through each virtual package
|
||||||
for _, vpkg := range pkg.PkgInfo.Provides {
|
for _, vpkg := range pkg.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
|
||||||
if _, ok := dependencies[vpkg]; ok {
|
if slices.ContainsFunc(dependencies, func(p pkgInstallationReason) bool {
|
||||||
|
return p.PkgName == vpkg
|
||||||
|
}) {
|
||||||
ret = append(ret, installedPkgName)
|
ret = append(ret, installedPkgName)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,17 +142,17 @@ func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, instal
|
|||||||
|
|
||||||
operation.UnresolvedDepends = append(operation.UnresolvedDepends, unresolved...)
|
operation.UnresolvedDepends = append(operation.UnresolvedDepends, unresolved...)
|
||||||
|
|
||||||
for depend, installationReason := range resolved {
|
for _, resolvedPkg := range resolved {
|
||||||
if !operation.ActionsContainPackage(depend) && depend != pkgInfo.Name {
|
if !operation.ActionsContainPackage(resolvedPkg.PkgName) && resolvedPkg.PkgName != pkgInfo.Name {
|
||||||
if !reinstallDependencies && IsPackageInstalled(depend, operation.RootDir) {
|
if !reinstallDependencies && IsPackageInstalled(resolvedPkg.PkgName, operation.RootDir) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
entry, _, err := GetDatabaseEntry(depend)
|
entry, _, err := GetDatabaseEntry(resolvedPkg.PkgName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("could not get database entry for package (" + depend + ")")
|
return errors.New("could not get database entry for package (" + resolvedPkg.PkgName + ")")
|
||||||
}
|
}
|
||||||
operation.InsertActionAt(pos, &FetchPackageAction{
|
operation.InsertActionAt(pos, &FetchPackageAction{
|
||||||
InstallationReason: installationReason,
|
InstallationReason: resolvedPkg.InstallationReason,
|
||||||
DatabaseEntry: entry,
|
DatabaseEntry: entry,
|
||||||
})
|
})
|
||||||
pos++
|
pos++
|
||||||
|
|||||||
Reference in New Issue
Block a user