mirror of
https://github.com/EnumeratedDev/bpm.git
synced 2026-09-24 14:36:12 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2aceb9efe8
|
||
|
|
bc3df83936
|
||
|
|
f18c837bc2
|
||
|
|
76ad8e77c5
|
||
|
|
9ae2d3f893
|
+7
-19
@@ -92,7 +92,6 @@ func main() {
|
|||||||
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.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation")
|
currentFlagSet.IntP("jobs", "j", bpmlib.CompilationBPMConfig.CompilationJobs, "Set the amount of concurrent processes to use for source package compilation")
|
||||||
currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in source.sh scripts")
|
currentFlagSet.BoolP("skip-checks", "s", false, "Skip the check function in source.sh scripts")
|
||||||
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:])
|
||||||
@@ -545,8 +544,7 @@ func installPackages() {
|
|||||||
installRuntime, _ := currentFlagSet.GetBool("runtime")
|
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")
|
reinstallPackages, _ := currentFlagSet.GetBool("reinstall")
|
||||||
reinstallAll, _ := currentFlagSet.GetBool("reinstall-all")
|
|
||||||
skipChecks, _ := currentFlagSet.GetBool("skip-checks")
|
skipChecks, _ := currentFlagSet.GetBool("skip-checks")
|
||||||
compilationJobs, _ := currentFlagSet.GetInt("jobs")
|
compilationJobs, _ := currentFlagSet.GetInt("jobs")
|
||||||
|
|
||||||
@@ -580,16 +578,6 @@ func installPackages() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get reinstall method
|
|
||||||
var reinstallMethod bpmlib.ReinstallMethod
|
|
||||||
if reinstallAll {
|
|
||||||
reinstallMethod = bpmlib.ReinstallMethodAll
|
|
||||||
} else if reinstall {
|
|
||||||
reinstallMethod = bpmlib.ReinstallMethodSpecified
|
|
||||||
} else {
|
|
||||||
reinstallMethod = bpmlib.ReinstallMethodNone
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create BPM Lock file
|
// Create BPM Lock file
|
||||||
fileLock, err := bpmlib.LockBPM(rootDir)
|
fileLock, err := bpmlib.LockBPM(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -616,7 +604,7 @@ func installPackages() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create installation operation
|
// Create installation operation
|
||||||
operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallMethod, installRuntime, installOptional, force, !skipChecks, verbose, packages...)
|
operation, err := bpmlib.InstallPackages(rootDir, ir, reinstallPackages, installRuntime, installOptional, force, !skipChecks, 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
|
||||||
@@ -1285,12 +1273,12 @@ func compilePackage() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get direct common and make dependencies
|
// Get common, make and check dependencies
|
||||||
totalDepends := make([]string, 0)
|
totalDepends := make([]string, 0)
|
||||||
for _, depend := range bpmpkg.PkgInfo.GetDependencies(true, !skipChecks, false, false) {
|
totalDepends = append(totalDepends, bpmpkg.PkgInfo.Depends...)
|
||||||
if !slices.Contains(totalDepends, depend.PkgName) {
|
totalDepends = append(totalDepends, bpmpkg.PkgInfo.MakeDepends...)
|
||||||
totalDepends = append(totalDepends, depend.PkgName)
|
if !skipChecks {
|
||||||
}
|
totalDepends = append(totalDepends, bpmpkg.PkgInfo.CheckDepends...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get unmet dependencies
|
// Get unmet dependencies
|
||||||
|
|||||||
@@ -236,6 +236,10 @@ func GetDatabaseVirtualPackageEntry(vpkg string) (providers []*BPMDatabaseEntry)
|
|||||||
providers = append(providers, db.VirtualPackages[vpkg]...)
|
providers = append(providers, db.VirtualPackages[vpkg]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slices.SortFunc(providers, func(a, b *BPMDatabaseEntry) int {
|
||||||
|
return strings.Compare(a.Info.Name, b.Info.Name)
|
||||||
|
})
|
||||||
|
|
||||||
return providers
|
return providers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+61
-224
@@ -1,234 +1,10 @@
|
|||||||
package bpmlib
|
package bpmlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type pkgInstallationReason struct {
|
|
||||||
PkgName string
|
|
||||||
InstallationReason InstallationReason
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pkgInfo *PackageInfo) GetDependencies(includeMakeDepends, includeCheckDepends, includeRuntimeDepends, includeOptionalDepends bool) []pkgInstallationReason {
|
|
||||||
allDepends := make([]pkgInstallationReason, 0)
|
|
||||||
|
|
||||||
for _, depend := range pkgInfo.Depends {
|
|
||||||
if !slices.ContainsFunc(allDepends, func(p pkgInstallationReason) bool {
|
|
||||||
return p.PkgName == depend
|
|
||||||
}) {
|
|
||||||
allDepends = append(allDepends, pkgInstallationReason{
|
|
||||||
PkgName: depend,
|
|
||||||
InstallationReason: InstallationReasonDependency,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if includeOptionalDepends {
|
|
||||||
for _, depend := range pkgInfo.OptionalDepends {
|
|
||||||
depend = strings.SplitN(depend, ":", 2)[0]
|
|
||||||
if !slices.ContainsFunc(allDepends, func(p pkgInstallationReason) bool {
|
|
||||||
return p.PkgName == depend
|
|
||||||
}) {
|
|
||||||
allDepends = append(allDepends, pkgInstallationReason{
|
|
||||||
PkgName: depend,
|
|
||||||
InstallationReason: InstallationReasonManual,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
for _, depend := range pkgInfo.MakeDepends {
|
|
||||||
if !slices.ContainsFunc(allDepends, func(p pkgInstallationReason) bool {
|
|
||||||
return p.PkgName == depend
|
|
||||||
}) {
|
|
||||||
allDepends = append(allDepends, pkgInstallationReason{
|
|
||||||
PkgName: depend,
|
|
||||||
InstallationReason: InstallationReasonMakeDependency,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if includeCheckDepends {
|
|
||||||
for _, depend := range pkgInfo.CheckDepends {
|
|
||||||
if !slices.ContainsFunc(allDepends, func(p pkgInstallationReason) bool {
|
|
||||||
return p.PkgName == depend
|
|
||||||
}) {
|
|
||||||
allDepends = append(allDepends, pkgInstallationReason{
|
|
||||||
PkgName: depend,
|
|
||||||
InstallationReason: InstallationReasonMakeDependency,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip ignored packages
|
|
||||||
allDepends = slices.DeleteFunc(allDepends, func(depend pkgInstallationReason) bool {
|
|
||||||
return slices.Contains(MainBPMConfig.IgnorePackages, depend.PkgName)
|
|
||||||
})
|
|
||||||
|
|
||||||
return allDepends
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pkgInfo *PackageInfo) GetDependenciesRecursive(includeRuntimeDepends, includeCheckDepends, includeMakeDepends bool, rootDir string) (resolved []string) {
|
|
||||||
// Initialize slices
|
|
||||||
resolved = make([]string, 0)
|
|
||||||
unresolved := make([]string, 0)
|
|
||||||
|
|
||||||
// Call unexported function
|
|
||||||
pkgInfo.getDependenciesRecursive(&resolved, &unresolved, includeRuntimeDepends, includeMakeDepends, includeCheckDepends, rootDir)
|
|
||||||
|
|
||||||
return resolved
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pkgInfo *PackageInfo) getDependenciesRecursive(resolved *[]string, unresolved *[]string, includeRuntimeDepends, includeMakeDepends, includeCheckDepends bool, rootDir string) {
|
|
||||||
// Add current package name to unresolved slice
|
|
||||||
*unresolved = append(*unresolved, pkgInfo.Name)
|
|
||||||
|
|
||||||
// Loop through all dependencies
|
|
||||||
for _, pkgIR := range pkgInfo.GetDependencies(includeMakeDepends, includeCheckDepends, includeRuntimeDepends, false) {
|
|
||||||
depend := pkgIR.PkgName
|
|
||||||
|
|
||||||
if providers := GetVirtualPackageInfo(depend, rootDir); len(providers) > 0 {
|
|
||||||
depend = providers[0].Name
|
|
||||||
}
|
|
||||||
|
|
||||||
if !slices.Contains(*resolved, depend) {
|
|
||||||
// Add current dependency to resolved slice when circular dependency is detected
|
|
||||||
if slices.Contains(*unresolved, depend) {
|
|
||||||
if !slices.Contains(*resolved, depend) {
|
|
||||||
*resolved = append(*resolved, depend)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
dependInfo := GetPackageInfo(depend, rootDir)
|
|
||||||
|
|
||||||
if dependInfo != nil {
|
|
||||||
dependInfo.getDependenciesRecursive(resolved, unresolved, includeRuntimeDepends, includeMakeDepends, includeCheckDepends, rootDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !slices.Contains(*resolved, pkgInfo.Name) {
|
|
||||||
*resolved = append(*resolved, pkgInfo.Name)
|
|
||||||
}
|
|
||||||
*unresolved = stringSliceRemove(*unresolved, pkgInfo.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ResolveAllPackageDependenciesFromDatabases(pkgInfo *PackageInfo, resolvedVirtualPkgs map[string]string, checkMake, checkCheck, checkRuntime, checkOptional, ignoreInstalled, verbose bool, rootDir string) (resolved []pkgInstallationReason, unresolved []string) {
|
|
||||||
// Initialize slices and maps
|
|
||||||
resolved = make([]pkgInstallationReason, 0)
|
|
||||||
unresolved = make([]string, 0)
|
|
||||||
if resolvedVirtualPkgs == nil {
|
|
||||||
resolvedVirtualPkgs = make(map[string]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call unexported function
|
|
||||||
resolvePackageDependenciesFromDatabase(&resolved, &unresolved, resolvedVirtualPkgs, pkgInfo, checkMake, checkCheck, checkRuntime, checkOptional, ignoreInstalled, verbose, rootDir)
|
|
||||||
|
|
||||||
// Remove main package from unresolved slice
|
|
||||||
unresolved = stringSliceRemove(unresolved, pkgInfo.Name)
|
|
||||||
|
|
||||||
return resolved, unresolved
|
|
||||||
}
|
|
||||||
|
|
||||||
func resolvePackageDependenciesFromDatabase(resolved *[]pkgInstallationReason, unresolved *[]string, resolvedVirtualPkgs map[string]string, pkgInfo *PackageInfo, checkMake, checkCheck, checkRuntime, checkOptional, ignoreInstalled, verbose bool, rootDir string) {
|
|
||||||
// Add current package name to unresolved slice
|
|
||||||
*unresolved = append(*unresolved, pkgInfo.Name)
|
|
||||||
|
|
||||||
for _, vpkg := range pkgInfo.Provides {
|
|
||||||
if _, ok := resolvedVirtualPkgs[vpkg]; !ok {
|
|
||||||
resolvedVirtualPkgs[vpkg] = pkgInfo.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through all dependencies
|
|
||||||
for _, pkgIR := range pkgInfo.GetDependencies(pkgInfo.Type == "source", pkgInfo.Type == "source" && checkCheck, checkRuntime, checkOptional) {
|
|
||||||
// Skip dependency if it has already been resolved
|
|
||||||
if slices.ContainsFunc(*resolved, func(p pkgInstallationReason) bool {
|
|
||||||
return p.PkgName == pkgIR.PkgName
|
|
||||||
}) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add current dependency to resolved slice when circular dependency is detected
|
|
||||||
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 providers := GetVirtualPackageInfo(pkgIR.PkgName, rootDir); ignoreInstalled && len(providers) > 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get database entry for dependency
|
|
||||||
var err error
|
|
||||||
var entry *BPMDatabaseEntry
|
|
||||||
entry, _, err = GetDatabaseEntry(pkgIR.PkgName)
|
|
||||||
if err != 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 providers := GetDatabaseVirtualPackageEntry(pkgIR.PkgName); len(providers) > 0 {
|
|
||||||
// Virtual package found in database
|
|
||||||
entry = providers[0]
|
|
||||||
} else {
|
|
||||||
// Virtual package not found
|
|
||||||
if !slices.Contains(*unresolved, pkgIR.PkgName) {
|
|
||||||
*unresolved = append(*unresolved, pkgIR.PkgName)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve the dependencies of this dependency
|
|
||||||
resolvePackageDependenciesFromDatabase(resolved, unresolved, resolvedVirtualPkgs, entry.Info, checkMake, checkCheck, checkRuntime, false, 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string) (dependants []string) {
|
func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string) (dependants []string) {
|
||||||
// Get installed package names
|
// Get installed package names
|
||||||
pkgs, ok := localPackageInformation[rootDir]
|
pkgs, ok := localPackageInformation[rootDir]
|
||||||
@@ -318,3 +94,64 @@ 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, includeRuntimeDepends, 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 includeRuntimeDepends {
|
||||||
|
checkDependencies(pkgInfo.RuntimeDepends, InstallationReasonDependency)
|
||||||
|
}
|
||||||
|
if pkgInfo.Type == "source" {
|
||||||
|
checkDependencies(pkgInfo.MakeDepends, InstallationReasonMakeDependency)
|
||||||
|
checkDependencies(pkgInfo.CheckDepends, InstallationReasonMakeDependency)
|
||||||
|
}
|
||||||
|
if includeOptionalDepends {
|
||||||
|
checkDependencies(pkgInfo.OptionalDepends, InstallationReasonManual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dfs(pkgInfo)
|
||||||
|
|
||||||
|
return resolved, unresolved
|
||||||
|
}
|
||||||
|
|||||||
+6
-20
@@ -11,16 +11,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ReinstallMethod uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
ReinstallMethodNone ReinstallMethod = iota
|
|
||||||
ReinstallMethodSpecified ReinstallMethod = iota
|
|
||||||
ReinstallMethodAll ReinstallMethod = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
// 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, installRuntimeDependencies, installOptionalDependencies, forceInstallation, runChecks bool, verbose bool, packages ...string) (operation *BPMOperation, err error) {
|
func InstallPackages(rootDir string, forceInstallationReason InstallationReason, reinstallPackages bool, installRuntimeDependencies, installOptionalDependencies, forceInstallation, runChecks bool, 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),
|
||||||
@@ -45,7 +37,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
|
|
||||||
if bpmpkg.PkgInfo.Type == "source" && bpmpkg.PkgInfo.IsSplitPackage() {
|
if bpmpkg.PkgInfo.Type == "source" && bpmpkg.PkgInfo.IsSplitPackage() {
|
||||||
for _, splitPkg := range bpmpkg.PkgInfo.SplitPackages {
|
for _, splitPkg := range bpmpkg.PkgInfo.SplitPackages {
|
||||||
if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(splitPkg.Name, rootDir) && GetPackageInfo(splitPkg.Name, rootDir).GetFullVersion() == splitPkg.GetFullVersion() {
|
if !reinstallPackages && IsPackageInstalled(splitPkg.Name, rootDir) && GetPackageInfo(splitPkg.Name, rootDir).GetFullVersion() == splitPkg.GetFullVersion() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +61,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) && GetPackageInfo(bpmpkg.PkgInfo.Name, rootDir).GetFullVersion() == bpmpkg.PkgInfo.GetFullVersion() {
|
if !reinstallPackages && IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) && GetPackageInfo(bpmpkg.PkgInfo.Name, rootDir).GetFullVersion() == bpmpkg.PkgInfo.GetFullVersion() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +97,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
pkgsNotFound = append(pkgsNotFound, pkg)
|
pkgsNotFound = append(pkgsNotFound, pkg)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if reinstallMethod == ReinstallMethodNone && IsPackageInstalled(entry.Info.Name, rootDir) && GetPackageInfo(entry.Info.Name, rootDir).GetFullVersion() == entry.Info.GetFullVersion() {
|
if !reinstallPackages && IsPackageInstalled(entry.Info.Name, rootDir) && GetPackageInfo(entry.Info.Name, rootDir).GetFullVersion() == entry.Info.GetFullVersion() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,10 +124,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve dependencies
|
// Resolve dependencies
|
||||||
err = operation.ResolveDependencies(reinstallMethod == ReinstallMethodAll, installRuntimeDependencies, installOptionalDependencies, verbose)
|
operation.ResolveDependencies(installRuntimeDependencies, 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 +420,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(true, 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}
|
||||||
|
|||||||
@@ -122,7 +122,12 @@ func GetVirtualPackageInfo(vpkg, rootDir string) []*PackageInfo {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return installedVirtualPackages[rootDir][vpkg]
|
providers := installedVirtualPackages[rootDir][vpkg]
|
||||||
|
slices.SortFunc(providers, func(a, b *PackageInfo) int {
|
||||||
|
return strings.Compare(a.Name, b.Name)
|
||||||
|
})
|
||||||
|
|
||||||
|
return providers
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPackageInfo(pkg string, rootDir string) *PackageInfo {
|
func GetPackageInfo(pkg string, rootDir string) *PackageInfo {
|
||||||
|
|||||||
+37
-16
@@ -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(installRuntimeDepends, 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, installRuntimeDepends, 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,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
for _, vpkg := range resolvedPkg.DatabaseEntry.Info.Provides {
|
||||||
|
if _, ok := resolvedVirtualPackages[vpkg]; !ok {
|
||||||
|
resolvedVirtualPackages[vpkg] = resolvedPkg.DatabaseEntry.Info.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pos++
|
pos++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos++
|
pos++
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) RemoveNeededPackages() error {
|
func (operation *BPMOperation) RemoveNeededPackages() error {
|
||||||
|
|||||||
Reference in New Issue
Block a user