mirror of
https://github.com/EnumeratedDev/bpm.git
synced 2026-09-21 04:56:12 +00:00
Compare commits
5
Commits
a03c9ad9ce
..
0.7.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3950c5f0d6
|
||
|
|
f3c2b9f0f6
|
||
|
|
dc8959c2f8
|
||
|
|
9122ffb9ca
|
||
|
|
a4e20b7d88
|
+72
-16
@@ -662,6 +662,9 @@ func installPackages() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get files that will be modifie during this operation
|
||||||
|
operation.GetModifiedFiles()
|
||||||
|
|
||||||
if bpmlib.MainBPMConfig.ShowSourcePackageContents == "always" || bpmlib.MainBPMConfig.ShowSourcePackageContents == "install-only" {
|
if bpmlib.MainBPMConfig.ShowSourcePackageContents == "always" || bpmlib.MainBPMConfig.ShowSourcePackageContents == "install-only" {
|
||||||
// Show source package contents
|
// Show source package contents
|
||||||
sourcePackagesShown, err := operation.ShowSourcePackageContent()
|
sourcePackagesShown, err := operation.ShowSourcePackageContent()
|
||||||
@@ -684,6 +687,15 @@ func installPackages() {
|
|||||||
// Get optional dependencies
|
// Get optional dependencies
|
||||||
optionalDepends := operation.GetOptionalDependencies()
|
optionalDepends := operation.GetOptionalDependencies()
|
||||||
|
|
||||||
|
// Executing pre-operation hooks
|
||||||
|
fmt.Println("Running pre-operation hooks...")
|
||||||
|
err = operation.RunPreHooks(verbose)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error: could not run pre-operation hooks: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Execute operation
|
// Execute operation
|
||||||
err = operation.Execute(verbose, force)
|
err = operation.Execute(verbose, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -692,15 +704,17 @@ func installPackages() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executing hooks
|
// Executing post-operation hooks
|
||||||
fmt.Println("Running hooks...")
|
fmt.Println("Running post-operation hooks...")
|
||||||
err = operation.RunHooks(verbose)
|
err = operation.RunPostHooks(verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error: could not run hooks: %s\n", err)
|
log.Printf("Error: could not run post-operation hooks: %s\n", err)
|
||||||
exitCode = 1
|
exitCode = 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("Operation complete!")
|
||||||
|
|
||||||
// Show optional dependencies
|
// Show optional dependencies
|
||||||
if len(optionalDepends) != 0 {
|
if len(optionalDepends) != 0 {
|
||||||
// List optional dependencies
|
// List optional dependencies
|
||||||
@@ -801,6 +815,18 @@ func removePackages() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get files that will be modifie during this operation
|
||||||
|
operation.GetModifiedFiles()
|
||||||
|
|
||||||
|
// Executing pre-operation hooks
|
||||||
|
fmt.Println("Running pre-operation hooks...")
|
||||||
|
err = operation.RunPreHooks(verbose)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error: could not run pre-operation hooks: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Execute operation
|
// Execute operation
|
||||||
err = operation.Execute(verbose, force)
|
err = operation.Execute(verbose, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -809,14 +835,16 @@ func removePackages() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executing hooks
|
// Executing post-operation hooks
|
||||||
fmt.Println("Running hooks...")
|
fmt.Println("Running post-operation hooks...")
|
||||||
err = operation.RunHooks(verbose)
|
err = operation.RunPostHooks(verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error: could not run hooks: %s\n", err)
|
log.Printf("Error: could not run post-operation hooks: %s\n", err)
|
||||||
exitCode = 1
|
exitCode = 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("Operation complete!")
|
||||||
}
|
}
|
||||||
|
|
||||||
func doCleanup() {
|
func doCleanup() {
|
||||||
@@ -922,6 +950,18 @@ func doCleanup() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get files that will be modifie during this operation
|
||||||
|
operation.GetModifiedFiles()
|
||||||
|
|
||||||
|
// Executing pre-operation hooks
|
||||||
|
fmt.Println("Running pre-operation hooks...")
|
||||||
|
err = operation.RunPreHooks(verbose)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error: could not run pre-operation hooks: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Execute operation
|
// Execute operation
|
||||||
err = operation.Execute(verbose, force)
|
err = operation.Execute(verbose, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -930,14 +970,16 @@ func doCleanup() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executing hooks
|
// Executing post-operation hooks
|
||||||
fmt.Println("Running hooks...")
|
fmt.Println("Running post-operation hooks...")
|
||||||
err = operation.RunHooks(verbose)
|
err = operation.RunPostHooks(verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error: could not run hooks: %s\n", err)
|
log.Printf("Error: could not run post-operation hooks: %s\n", err)
|
||||||
exitCode = 1
|
exitCode = 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("Operation complete!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,6 +1125,9 @@ func updatePackages() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get files that will be modifie during this operation
|
||||||
|
operation.GetModifiedFiles()
|
||||||
|
|
||||||
if bpmlib.MainBPMConfig.ShowSourcePackageContents == "always" {
|
if bpmlib.MainBPMConfig.ShowSourcePackageContents == "always" {
|
||||||
// Show source package contents
|
// Show source package contents
|
||||||
sourcePackagesShown, err := operation.ShowSourcePackageContent()
|
sourcePackagesShown, err := operation.ShowSourcePackageContent()
|
||||||
@@ -1105,6 +1150,15 @@ func updatePackages() {
|
|||||||
// Get optional dependencies
|
// Get optional dependencies
|
||||||
optionalDepends := operation.GetOptionalDependencies()
|
optionalDepends := operation.GetOptionalDependencies()
|
||||||
|
|
||||||
|
// Executing pre-operation hooks
|
||||||
|
fmt.Println("Running pre-operation hooks...")
|
||||||
|
err = operation.RunPreHooks(verbose)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error: could not run pre-operation hooks: %s\n", err)
|
||||||
|
exitCode = 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Execute operation
|
// Execute operation
|
||||||
err = operation.Execute(verbose, force)
|
err = operation.Execute(verbose, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1113,15 +1167,17 @@ func updatePackages() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executing hooks
|
// Executing post-operation hooks
|
||||||
fmt.Println("Running hooks...")
|
fmt.Println("Running post-operation hooks...")
|
||||||
err = operation.RunHooks(verbose)
|
err = operation.RunPostHooks(verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error: could not run hooks: %s\n", err)
|
log.Printf("Error: could not run post-operation hooks: %s\n", err)
|
||||||
exitCode = 1
|
exitCode = 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("Operation complete!")
|
||||||
|
|
||||||
// Show optional dependencies
|
// Show optional dependencies
|
||||||
if len(optionalDepends) != 0 {
|
if len(optionalDepends) != 0 {
|
||||||
// List optional dependencies
|
// List optional dependencies
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
type MainBPMConfigStruct struct {
|
type MainBPMConfigStruct struct {
|
||||||
IgnorePackages []string `yaml:"ignore_packages"`
|
IgnorePackages []string `yaml:"ignore_packages"`
|
||||||
|
IgnorePaths []string `yaml:"ignore_paths"`
|
||||||
ShowSourcePackageContents string `yaml:"show_source_package_contents"`
|
ShowSourcePackageContents string `yaml:"show_source_package_contents"`
|
||||||
CleanupMakeDependencies bool `yaml:"cleanup_make_dependencies"`
|
CleanupMakeDependencies bool `yaml:"cleanup_make_dependencies"`
|
||||||
Databases []configDatabase `yaml:"databases"`
|
Databases []configDatabase `yaml:"databases"`
|
||||||
|
|||||||
+15
-2
@@ -311,6 +311,7 @@ func (entry *BPMDatabaseEntry) GetEntryDependants() (dependants []string) {
|
|||||||
|
|
||||||
// Add installed package to list if its dependencies include pkgName
|
// Add installed package to list if its dependencies include pkgName
|
||||||
if slices.ContainsFunc(e.Info.Depends, func(n string) bool {
|
if slices.ContainsFunc(e.Info.Depends, func(n string) bool {
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
return n == entry.Info.Name
|
return n == entry.Info.Name
|
||||||
}) {
|
}) {
|
||||||
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], db.Name)
|
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], db.Name)
|
||||||
@@ -319,6 +320,7 @@ func (entry *BPMDatabaseEntry) GetEntryDependants() (dependants []string) {
|
|||||||
|
|
||||||
// Add installed package to list if its runtime dependencies include pkgName
|
// Add installed package to list if its runtime dependencies include pkgName
|
||||||
if slices.ContainsFunc(e.Info.RuntimeDepends, func(n string) bool {
|
if slices.ContainsFunc(e.Info.RuntimeDepends, func(n string) bool {
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
return n == entry.Info.Name
|
return n == entry.Info.Name
|
||||||
}) {
|
}) {
|
||||||
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], db.Name)
|
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], db.Name)
|
||||||
@@ -329,6 +331,7 @@ func (entry *BPMDatabaseEntry) GetEntryDependants() (dependants []string) {
|
|||||||
for _, vpkg := range entry.Info.Provides {
|
for _, vpkg := range entry.Info.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 slices.ContainsFunc(e.Info.Depends, func(n string) bool {
|
if slices.ContainsFunc(e.Info.Depends, func(n string) bool {
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
return n == vpkg
|
return n == vpkg
|
||||||
}) {
|
}) {
|
||||||
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], db.Name)
|
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], db.Name)
|
||||||
@@ -337,6 +340,7 @@ func (entry *BPMDatabaseEntry) GetEntryDependants() (dependants []string) {
|
|||||||
|
|
||||||
// Add installed package to list if its runtime dependencies contain a provided virtual package
|
// Add installed package to list if its runtime dependencies contain a provided virtual package
|
||||||
if slices.ContainsFunc(e.Info.RuntimeDepends, func(n string) bool {
|
if slices.ContainsFunc(e.Info.RuntimeDepends, func(n string) bool {
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
return n == vpkg
|
return n == vpkg
|
||||||
}) {
|
}) {
|
||||||
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], db.Name)
|
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], db.Name)
|
||||||
@@ -370,7 +374,13 @@ func (entry *BPMDatabaseEntry) GetEntryOptionalDependants() (dependants []string
|
|||||||
for _, db := range BPMDatabases {
|
for _, db := range BPMDatabases {
|
||||||
for _, e := range db.Entries {
|
for _, e := range db.Entries {
|
||||||
if slices.ContainsFunc(e.Info.OptionalDepends, func(n string) bool {
|
if slices.ContainsFunc(e.Info.OptionalDepends, func(n string) bool {
|
||||||
return strings.SplitN(n, ":", 2)[0] == entry.Info.Name
|
// Remove optional dependency comment
|
||||||
|
n = strings.SplitN(n, ":", 2)[0]
|
||||||
|
|
||||||
|
// Remove required version
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
|
|
||||||
|
return n == entry.Info.Name
|
||||||
}) {
|
}) {
|
||||||
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], e.Database.Name)
|
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], e.Database.Name)
|
||||||
}
|
}
|
||||||
@@ -400,7 +410,10 @@ func (entry *BPMDatabaseEntry) GetEntryMakeDependants() (dependants []string) {
|
|||||||
dependantsMap := make(map[string][]string)
|
dependantsMap := make(map[string][]string)
|
||||||
for _, db := range BPMDatabases {
|
for _, db := range BPMDatabases {
|
||||||
for _, e := range db.Entries {
|
for _, e := range db.Entries {
|
||||||
if slices.Contains(e.Info.MakeDepends, entry.Info.Name) {
|
if slices.ContainsFunc(e.Info.MakeDepends, func(n string) bool {
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
|
return n == entry.Info.Name
|
||||||
|
}) {
|
||||||
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], e.Database.Name)
|
dependantsMap[e.Info.Name] = append(dependantsMap[e.Info.Name], e.Database.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string, skipMultiplePro
|
|||||||
|
|
||||||
// Add installed package to list if its dependencies include pkgName
|
// Add installed package to list if its dependencies include pkgName
|
||||||
if slices.ContainsFunc(installedPkg.Depends, func(n string) bool {
|
if slices.ContainsFunc(installedPkg.Depends, func(n string) bool {
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
return n == pkgInfo.Name
|
return n == pkgInfo.Name
|
||||||
}) {
|
}) {
|
||||||
dependants = append(dependants, installedPkg.Name)
|
dependants = append(dependants, installedPkg.Name)
|
||||||
@@ -29,6 +30,7 @@ func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string, skipMultiplePro
|
|||||||
|
|
||||||
// Add installed package to list if its runtime dependencies include pkgName
|
// Add installed package to list if its runtime dependencies include pkgName
|
||||||
if slices.ContainsFunc(installedPkg.RuntimeDepends, func(n string) bool {
|
if slices.ContainsFunc(installedPkg.RuntimeDepends, func(n string) bool {
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
return n == pkgInfo.Name
|
return n == pkgInfo.Name
|
||||||
}) {
|
}) {
|
||||||
dependants = append(dependants, installedPkg.Name)
|
dependants = append(dependants, installedPkg.Name)
|
||||||
@@ -43,6 +45,7 @@ func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string, skipMultiplePro
|
|||||||
|
|
||||||
// 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 slices.ContainsFunc(installedPkg.Depends, func(n string) bool {
|
if slices.ContainsFunc(installedPkg.Depends, func(n string) bool {
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
return n == vpkg
|
return n == vpkg
|
||||||
}) {
|
}) {
|
||||||
dependants = append(dependants, installedPkg.Name)
|
dependants = append(dependants, installedPkg.Name)
|
||||||
@@ -51,6 +54,7 @@ func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string, skipMultiplePro
|
|||||||
|
|
||||||
// Add installed package to list if its runtime dependencies contain a provided virtual package
|
// Add installed package to list if its runtime dependencies contain a provided virtual package
|
||||||
if slices.ContainsFunc(installedPkg.RuntimeDepends, func(n string) bool {
|
if slices.ContainsFunc(installedPkg.RuntimeDepends, func(n string) bool {
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
return n == vpkg
|
return n == vpkg
|
||||||
}) {
|
}) {
|
||||||
dependants = append(dependants, installedPkg.Name)
|
dependants = append(dependants, installedPkg.Name)
|
||||||
@@ -78,7 +82,13 @@ func (pkgInfo *PackageInfo) GetPackageOptionalDependants(rootDir string) (depend
|
|||||||
|
|
||||||
// Add installed package to list if its optional dependencies include pkgName
|
// Add installed package to list if its optional dependencies include pkgName
|
||||||
if slices.ContainsFunc(installedPkg.OptionalDepends, func(n string) bool {
|
if slices.ContainsFunc(installedPkg.OptionalDepends, func(n string) bool {
|
||||||
return strings.SplitN(n, ":", 2)[0] == pkgInfo.Name
|
// Remove optional dependency comment
|
||||||
|
n = strings.SplitN(n, ":", 2)[0]
|
||||||
|
|
||||||
|
// Remove required version
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
|
|
||||||
|
return n == pkgInfo.Name
|
||||||
}) {
|
}) {
|
||||||
dependants = append(dependants, installedPkg.Name)
|
dependants = append(dependants, installedPkg.Name)
|
||||||
continue
|
continue
|
||||||
@@ -88,7 +98,13 @@ func (pkgInfo *PackageInfo) GetPackageOptionalDependants(rootDir string) (depend
|
|||||||
for _, vpkg := range pkgInfo.Provides {
|
for _, vpkg := range pkgInfo.Provides {
|
||||||
// Add installed package to list if its optional dependencies contain a provided virtual package
|
// Add installed package to list if its optional dependencies contain a provided virtual package
|
||||||
if slices.ContainsFunc(installedPkg.OptionalDepends, func(n string) bool {
|
if slices.ContainsFunc(installedPkg.OptionalDepends, func(n string) bool {
|
||||||
return strings.SplitN(n, ":", 2)[0] == vpkg
|
// Remove optional dependency comment
|
||||||
|
n = strings.SplitN(n, ":", 2)[0]
|
||||||
|
|
||||||
|
// Remove required version
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
|
|
||||||
|
return n == vpkg
|
||||||
}) {
|
}) {
|
||||||
dependants = append(dependants, installedPkg.Name)
|
dependants = append(dependants, installedPkg.Name)
|
||||||
break
|
break
|
||||||
@@ -111,20 +127,23 @@ func ResolveDependencies(pkgInfo *PackageInfo, resolvedVirtualPackages map[strin
|
|||||||
dfs = func(pkgInfo *PackageInfo) {
|
dfs = func(pkgInfo *PackageInfo) {
|
||||||
checkDependencies := func(dependencies []string, installationReason InstallationReason) {
|
checkDependencies := func(dependencies []string, installationReason InstallationReason) {
|
||||||
for _, depend := range dependencies {
|
for _, depend := range dependencies {
|
||||||
|
// Split dependency name and required version
|
||||||
|
dependName, _, _ := SplitPkgNameAndVersion(depend)
|
||||||
|
|
||||||
// Ignore if package is already installed
|
// Ignore if package is already installed
|
||||||
if IsPackageInstalled(depend, rootDir) {
|
if IsPackageInstalled(dependName, rootDir) && EvaluateDependency(depend, GetPackageInfo(dependName, rootDir).Version) {
|
||||||
continue
|
continue
|
||||||
} else if providers := GetVirtualPackageInfo(depend, rootDir); len(providers) > 0 {
|
} else if providers := GetVirtualPackageInfo(dependName, rootDir); len(providers) > 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find database entry for dependency
|
// Find database entry for dependency
|
||||||
var dependEntry *BPMDatabaseEntry
|
var dependEntry *BPMDatabaseEntry
|
||||||
if resolvedVpkg, ok := resolvedVirtualPackages[depend]; ok {
|
if resolvedVpkg, ok := resolvedVirtualPackages[dependName]; ok {
|
||||||
dependEntry, _, _ = GetDatabaseEntry(resolvedVpkg)
|
dependEntry, _, _ = GetDatabaseEntry(resolvedVpkg)
|
||||||
} else if entry, _, _ := GetDatabaseEntry(depend); entry != nil {
|
} else if entry, _, _ := GetDatabaseEntry(dependName); entry != nil {
|
||||||
dependEntry = entry
|
dependEntry = entry
|
||||||
} else if providers := GetDatabaseVirtualPackageEntry(depend); len(providers) > 0 {
|
} else if providers := GetDatabaseVirtualPackageEntry(dependName); len(providers) > 0 {
|
||||||
dependEntry = providers[0]
|
dependEntry = providers[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,8 +152,14 @@ func ResolveDependencies(pkgInfo *PackageInfo, resolvedVirtualPackages map[strin
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure entry has required version
|
||||||
|
if !EvaluateDependency(depend, dependEntry.Info.Version) {
|
||||||
|
unresolved = append(unresolved, depend)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Skip ignored packages in config
|
// Skip ignored packages in config
|
||||||
if slices.Contains(MainBPMConfig.IgnorePackages, dependEntry.Info.Name) {
|
if rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, dependEntry.Info.Name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,3 +186,62 @@ func ResolveDependencies(pkgInfo *PackageInfo, resolvedVirtualPackages map[strin
|
|||||||
|
|
||||||
return resolved, unresolved
|
return resolved, unresolved
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SplitPkgNameAndVersion(pkg string) (string, string, string) {
|
||||||
|
if strings.Contains(pkg, ">=") {
|
||||||
|
pkgSplit := strings.SplitN(pkg, ">=", 2)
|
||||||
|
pkgName := pkgSplit[0]
|
||||||
|
pkgVersion := pkgSplit[1]
|
||||||
|
|
||||||
|
return pkgName, ">=", pkgVersion
|
||||||
|
} else if strings.Contains(pkg, ">") {
|
||||||
|
pkgSplit := strings.SplitN(pkg, ">", 2)
|
||||||
|
pkgName := pkgSplit[0]
|
||||||
|
pkgVersion := pkgSplit[1]
|
||||||
|
|
||||||
|
return pkgName, ">", pkgVersion
|
||||||
|
} else if strings.Contains(pkg, "<=") {
|
||||||
|
pkgSplit := strings.SplitN(pkg, "<=", 2)
|
||||||
|
pkgName := pkgSplit[0]
|
||||||
|
pkgVersion := pkgSplit[1]
|
||||||
|
|
||||||
|
return pkgName, "<=", pkgVersion
|
||||||
|
} else if strings.Contains(pkg, "<") {
|
||||||
|
pkgSplit := strings.SplitN(pkg, "<", 2)
|
||||||
|
pkgName := pkgSplit[0]
|
||||||
|
pkgVersion := pkgSplit[1]
|
||||||
|
|
||||||
|
return pkgName, "<", pkgVersion
|
||||||
|
} else if strings.Contains(pkg, "=") {
|
||||||
|
pkgSplit := strings.SplitN(pkg, "=", 2)
|
||||||
|
pkgName := pkgSplit[0]
|
||||||
|
pkgVersion := pkgSplit[1]
|
||||||
|
|
||||||
|
return pkgName, "=", pkgVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkg, "", ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func EvaluateDependency(pkg, matchVersion string) bool {
|
||||||
|
_, comparisonSymbol, pkgVersion := SplitPkgNameAndVersion(pkg)
|
||||||
|
|
||||||
|
switch comparisonSymbol {
|
||||||
|
case ">=":
|
||||||
|
return CompareVersions(matchVersion, pkgVersion) >= 0
|
||||||
|
case ">":
|
||||||
|
return CompareVersions(matchVersion, pkgVersion) > 0
|
||||||
|
case "<=":
|
||||||
|
return CompareVersions(matchVersion, pkgVersion) <= 0
|
||||||
|
case "<":
|
||||||
|
return CompareVersions(matchVersion, pkgVersion) < 0
|
||||||
|
case "=":
|
||||||
|
if cutPkgVersion, ok := strings.CutSuffix(pkgVersion, "*"); ok {
|
||||||
|
return strings.HasPrefix(matchVersion, cutPkgVersion)
|
||||||
|
} else {
|
||||||
|
return CompareVersions(matchVersion, pkgVersion) == 0
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+64
-36
@@ -17,7 +17,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
operation = &BPMOperation{
|
operation = &BPMOperation{
|
||||||
Actions: make([]OperationAction, 0),
|
Actions: make([]OperationAction, 0),
|
||||||
UnresolvedDepends: make([]string, 0),
|
UnresolvedDepends: make([]string, 0),
|
||||||
Changes: make(map[string]string),
|
ModifiedFiles: make(map[string]string),
|
||||||
RunChecks: runChecks,
|
RunChecks: runChecks,
|
||||||
RootDir: rootDir,
|
RootDir: rootDir,
|
||||||
compiledPackages: make(map[string]string),
|
compiledPackages: make(map[string]string),
|
||||||
@@ -51,7 +51,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operation.AppendAction(&InstallPackageAction{
|
operation.Actions = append(operation.Actions, &InstallPackageAction{
|
||||||
File: pkg,
|
File: pkg,
|
||||||
InstallationReason: installationReason,
|
InstallationReason: installationReason,
|
||||||
BpmPackage: bpmpkg,
|
BpmPackage: bpmpkg,
|
||||||
@@ -75,28 +75,37 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operation.AppendAction(&InstallPackageAction{
|
operation.Actions = append(operation.Actions, &InstallPackageAction{
|
||||||
File: pkg,
|
File: pkg,
|
||||||
InstallationReason: installationReason,
|
InstallationReason: installationReason,
|
||||||
BpmPackage: bpmpkg,
|
BpmPackage: bpmpkg,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
// Split package name and required version
|
||||||
|
pkgName, _, _ := SplitPkgNameAndVersion(pkg)
|
||||||
|
|
||||||
var entry *BPMDatabaseEntry
|
var entry *BPMDatabaseEntry
|
||||||
|
|
||||||
if e, _, err := GetDatabaseEntry(pkg); err == nil {
|
if e, _, err := GetDatabaseEntry(pkgName); err == nil {
|
||||||
entry = e
|
entry = e
|
||||||
} else if providers := GetVirtualPackageInfo(pkg, rootDir); len(providers) > 0 {
|
} else if providers := GetVirtualPackageInfo(pkgName, rootDir); len(providers) > 0 {
|
||||||
entry, _, err = GetDatabaseEntry(providers[0].Name)
|
entry, _, err = GetDatabaseEntry(providers[0].Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pkgsNotFound = append(pkgsNotFound, pkg)
|
pkgsNotFound = append(pkgsNotFound, pkg)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else if providers := GetDatabaseVirtualPackageEntry(pkg); len(providers) > 0 {
|
} else if providers := GetDatabaseVirtualPackageEntry(pkgName); len(providers) > 0 {
|
||||||
entry = providers[0]
|
entry = providers[0]
|
||||||
} else {
|
} else {
|
||||||
pkgsNotFound = append(pkgsNotFound, pkg)
|
pkgsNotFound = append(pkgsNotFound, pkg)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !EvaluateDependency(pkg, entry.Info.Version) {
|
||||||
|
pkgsNotFound = append(pkgsNotFound, pkg)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if !reinstallPackages && 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
|
||||||
}
|
}
|
||||||
@@ -111,7 +120,7 @@ func InstallPackages(rootDir string, forceInstallationReason InstallationReason,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operation.AppendAction(&FetchPackageAction{
|
operation.Actions = append(operation.Actions, &FetchPackageAction{
|
||||||
InstallationReason: installationReason,
|
InstallationReason: installationReason,
|
||||||
DatabaseEntry: entry,
|
DatabaseEntry: entry,
|
||||||
})
|
})
|
||||||
@@ -180,7 +189,7 @@ func RemovePackages(rootDir string, force, cleanupDependencies bool, packages ..
|
|||||||
operation = &BPMOperation{
|
operation = &BPMOperation{
|
||||||
Actions: make([]OperationAction, 0),
|
Actions: make([]OperationAction, 0),
|
||||||
UnresolvedDepends: make([]string, 0),
|
UnresolvedDepends: make([]string, 0),
|
||||||
Changes: make(map[string]string),
|
ModifiedFiles: make(map[string]string),
|
||||||
RootDir: rootDir,
|
RootDir: rootDir,
|
||||||
compiledPackages: make(map[string]string),
|
compiledPackages: make(map[string]string),
|
||||||
}
|
}
|
||||||
@@ -197,7 +206,7 @@ func RemovePackages(rootDir string, force, cleanupDependencies bool, packages ..
|
|||||||
if bpmpkg == nil {
|
if bpmpkg == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
operation.AppendAction(&RemovePackageAction{BpmPackage: bpmpkg})
|
operation.Actions = append(operation.Actions, &RemovePackageAction{BpmPackage: bpmpkg})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do package cleanup
|
// Do package cleanup
|
||||||
@@ -214,7 +223,7 @@ func RemovePackages(rootDir string, force, cleanupDependencies bool, packages ..
|
|||||||
packageDepndants := make(map[string][]string, 0)
|
packageDepndants := make(map[string][]string, 0)
|
||||||
for _, action := range operation.Actions {
|
for _, action := range operation.Actions {
|
||||||
// Skip package if ignored in config
|
// Skip package if ignored in config
|
||||||
if slices.Contains(MainBPMConfig.IgnorePackages, action.(*RemovePackageAction).BpmPackage.PkgInfo.Name) {
|
if rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, action.(*RemovePackageAction).BpmPackage.PkgInfo.Name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +243,7 @@ func RemovePackages(rootDir string, force, cleanupDependencies bool, packages ..
|
|||||||
// Remove dependant packages if ignored
|
// Remove dependant packages if ignored
|
||||||
for pkg, required := range packageDepndants {
|
for pkg, required := range packageDepndants {
|
||||||
required = slices.DeleteFunc(required, func(pkgName string) bool {
|
required = slices.DeleteFunc(required, func(pkgName string) bool {
|
||||||
return slices.Contains(MainBPMConfig.IgnorePackages, pkgName)
|
return rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, pkgName)
|
||||||
})
|
})
|
||||||
packageDepndants[pkg] = required
|
packageDepndants[pkg] = required
|
||||||
}
|
}
|
||||||
@@ -258,7 +267,7 @@ func CleanupPackages(cleanupMakeDepends bool, rootDir string) (operation *BPMOpe
|
|||||||
operation = &BPMOperation{
|
operation = &BPMOperation{
|
||||||
Actions: make([]OperationAction, 0),
|
Actions: make([]OperationAction, 0),
|
||||||
UnresolvedDepends: make([]string, 0),
|
UnresolvedDepends: make([]string, 0),
|
||||||
Changes: make(map[string]string),
|
ModifiedFiles: make(map[string]string),
|
||||||
RootDir: rootDir,
|
RootDir: rootDir,
|
||||||
compiledPackages: make(map[string]string),
|
compiledPackages: make(map[string]string),
|
||||||
}
|
}
|
||||||
@@ -386,7 +395,7 @@ func UpdatePackages(rootDir string, syncDatabase, allowDowngrades, forceInstalla
|
|||||||
operation = &BPMOperation{
|
operation = &BPMOperation{
|
||||||
Actions: make([]OperationAction, 0),
|
Actions: make([]OperationAction, 0),
|
||||||
UnresolvedDepends: make([]string, 0),
|
UnresolvedDepends: make([]string, 0),
|
||||||
Changes: make(map[string]string),
|
ModifiedFiles: make(map[string]string),
|
||||||
RunChecks: runChecks,
|
RunChecks: runChecks,
|
||||||
RootDir: rootDir,
|
RootDir: rootDir,
|
||||||
compiledPackages: make(map[string]string),
|
compiledPackages: make(map[string]string),
|
||||||
@@ -395,7 +404,7 @@ func UpdatePackages(rootDir string, syncDatabase, allowDowngrades, forceInstalla
|
|||||||
// Search for packages
|
// Search for packages
|
||||||
pkgsNotFound := make([]string, 0)
|
pkgsNotFound := make([]string, 0)
|
||||||
for _, pkg := range pkgs {
|
for _, pkg := range pkgs {
|
||||||
if slices.Contains(MainBPMConfig.IgnorePackages, pkg) {
|
if rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, pkg) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var entry *BPMDatabaseEntry
|
var entry *BPMDatabaseEntry
|
||||||
@@ -412,79 +421,98 @@ func UpdatePackages(rootDir string, syncDatabase, allowDowngrades, forceInstalla
|
|||||||
} else {
|
} else {
|
||||||
comparison := CompareVersions(entry.Info.GetFullVersion(), installedInfo.GetFullVersion())
|
comparison := CompareVersions(entry.Info.GetFullVersion(), installedInfo.GetFullVersion())
|
||||||
if (!allowDowngrades && comparison > 0) || (allowDowngrades && comparison != 0) {
|
if (!allowDowngrades && comparison > 0) || (allowDowngrades && comparison != 0) {
|
||||||
operation.AppendAction(&FetchPackageAction{
|
operation.Actions = append(operation.Actions, &FetchPackageAction{
|
||||||
InstallationReason: GetPackage(pkg, rootDir).LocalInfo.GetInstallationReason(),
|
InstallationReason: GetPackage(pkg, rootDir).LocalInfo.GetInstallationReason(),
|
||||||
DatabaseEntry: entry,
|
DatabaseEntry: entry,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for missing dependencies
|
// Check for missing dependencies
|
||||||
for _, dep := range entry.Info.Depends {
|
for _, depend := range entry.Info.Depends {
|
||||||
if IsPackageInstalled(dep, rootDir) {
|
// Split package name and required version
|
||||||
|
dependName, _, _ := SplitPkgNameAndVersion(depend)
|
||||||
|
|
||||||
|
if IsPackageInstalled(dependName, rootDir) && EvaluateDependency(depend, GetPackageInfo(dependName, rootDir).Version) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(GetVirtualPackageInfo(dep, rootDir)) > 0 {
|
if len(GetVirtualPackageInfo(dependName, rootDir)) > 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find database entry for missing dependency
|
// Find database entry for missing dependency
|
||||||
depEntry, _, err := GetDatabaseEntry(dep)
|
dependEntry, _, err := GetDatabaseEntry(dependName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
providers := GetDatabaseVirtualPackageEntry(dep)
|
providers := GetDatabaseVirtualPackageEntry(dependName)
|
||||||
if len(providers) == 0 {
|
if len(providers) == 0 {
|
||||||
pkgsNotFound = append(pkgsNotFound, dep)
|
pkgsNotFound = append(pkgsNotFound, depend)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
depEntry = providers[0]
|
dependEntry = providers[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip dependency if action already exists
|
// Skip dependency if action already exists
|
||||||
if operation.ActionsContainPackage(depEntry.Info.Name) {
|
if ActionSliceIndex(operation.Actions, dependEntry.Info.Name) != -1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip dependency if ignored in config
|
// Skip dependency if ignored in config
|
||||||
if slices.Contains(MainBPMConfig.IgnorePackages, depEntry.Info.Name) {
|
if rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, dependEntry.Info.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure entry has required version
|
||||||
|
if !EvaluateDependency(depend, dependEntry.Info.Version) {
|
||||||
|
pkgsNotFound = append(pkgsNotFound, depend)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch dependency
|
// Fetch dependency
|
||||||
operation.AppendAction(&FetchPackageAction{
|
operation.Actions = append(operation.Actions, &FetchPackageAction{
|
||||||
InstallationReason: InstallationReasonDependency,
|
InstallationReason: InstallationReasonDependency,
|
||||||
DatabaseEntry: depEntry,
|
DatabaseEntry: dependEntry,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for missing runtime dependencies
|
// Check for missing runtime dependencies
|
||||||
for _, dep := range entry.Info.RuntimeDepends {
|
for _, depend := range entry.Info.RuntimeDepends {
|
||||||
if IsPackageInstalled(dep, rootDir) {
|
// Split package name and required version
|
||||||
|
dependName, _, _ := SplitPkgNameAndVersion(depend)
|
||||||
|
|
||||||
|
if IsPackageInstalled(dependName, rootDir) && EvaluateDependency(depend, GetPackageInfo(dependName, rootDir).Version) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(GetVirtualPackageInfo(dep, rootDir)) > 0 {
|
if len(GetVirtualPackageInfo(dependName, rootDir)) > 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find database entry for missing dependency
|
// Find database entry for missing dependency
|
||||||
depEntry, _, err := GetDatabaseEntry(dep)
|
dependEntry, _, err := GetDatabaseEntry(dependName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
providers := GetDatabaseVirtualPackageEntry(dep)
|
providers := GetDatabaseVirtualPackageEntry(dependName)
|
||||||
if len(providers) == 0 {
|
if len(providers) == 0 {
|
||||||
pkgsNotFound = append(pkgsNotFound, dep)
|
pkgsNotFound = append(pkgsNotFound, depend)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
depEntry = providers[0]
|
dependEntry = providers[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip dependency if ignored in config
|
// Skip dependency if ignored in config
|
||||||
if slices.Contains(MainBPMConfig.IgnorePackages, depEntry.Info.Name) {
|
if rootDir == "/" && slices.Contains(MainBPMConfig.IgnorePackages, dependEntry.Info.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure entry has required version
|
||||||
|
if !EvaluateDependency(depend, dependEntry.Info.Version) {
|
||||||
|
pkgsNotFound = append(pkgsNotFound, depend)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch dependency
|
// Fetch dependency
|
||||||
operation.AppendAction(&FetchPackageAction{
|
operation.Actions = append(operation.Actions, &FetchPackageAction{
|
||||||
InstallationReason: InstallationReasonDependency,
|
InstallationReason: InstallationReasonDependency,
|
||||||
DatabaseEntry: depEntry,
|
DatabaseEntry: dependEntry,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-67
@@ -1,26 +1,27 @@
|
|||||||
package bpmlib
|
package bpmlib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BPMHook struct {
|
type BPMHook struct {
|
||||||
SourcePath string
|
SourcePath string
|
||||||
SourceContent string
|
SourceContent string
|
||||||
TriggerOperations []string `yaml:"trigger_operations"`
|
TriggerActions []string `yaml:"trigger_actions"`
|
||||||
TargetType string `yaml:"target_type"`
|
TriggerPreOperation bool `yaml:"trigger_pre_operation"`
|
||||||
Targets []string `yaml:"targets"`
|
Targets []string `yaml:"targets"`
|
||||||
Depends []string `yaml:"depends"`
|
Run string `yaml:"run"`
|
||||||
Run string `yaml:"run"`
|
PassTargets bool `yaml:"pass_targets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// createHook returns a BPMHook instance based on the content of the given string
|
// createHook returns a BPMHook instance based on the content of the given string
|
||||||
@@ -33,13 +34,11 @@ func createHook(sourcePath string) (*BPMHook, error) {
|
|||||||
|
|
||||||
// Create base hook structure
|
// Create base hook structure
|
||||||
hook := &BPMHook{
|
hook := &BPMHook{
|
||||||
SourcePath: sourcePath,
|
SourcePath: sourcePath,
|
||||||
SourceContent: string(bytes),
|
SourceContent: string(bytes),
|
||||||
TriggerOperations: nil,
|
TriggerActions: nil,
|
||||||
TargetType: "",
|
Targets: nil,
|
||||||
Targets: nil,
|
Run: "",
|
||||||
Depends: nil,
|
|
||||||
Run: "",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal yaml string
|
// Unmarshal yaml string
|
||||||
@@ -61,19 +60,15 @@ func (hook *BPMHook) IsValid() error {
|
|||||||
ValidOperations := []string{"install", "upgrade", "remove"}
|
ValidOperations := []string{"install", "upgrade", "remove"}
|
||||||
|
|
||||||
// Return error if any trigger operation is not valid or none are given
|
// Return error if any trigger operation is not valid or none are given
|
||||||
if len(hook.TriggerOperations) == 0 {
|
if len(hook.TriggerActions) == 0 {
|
||||||
return errors.New("no trigger operations specified")
|
return errors.New("no trigger operations specified")
|
||||||
}
|
}
|
||||||
for _, operation := range hook.TriggerOperations {
|
for _, operation := range hook.TriggerActions {
|
||||||
if !slices.Contains(ValidOperations, operation) {
|
if !slices.Contains(ValidOperations, operation) {
|
||||||
return errors.New("trigger operation '" + operation + "' is not valid")
|
return errors.New("trigger operation '" + operation + "' is not valid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if hook.TargetType != "package" && hook.TargetType != "path" {
|
|
||||||
return errors.New("target type '" + hook.TargetType + "' is not valid")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(hook.Run) == 0 {
|
if len(hook.Run) == 0 {
|
||||||
return errors.New("command to run is empty")
|
return errors.New("command to run is empty")
|
||||||
}
|
}
|
||||||
@@ -83,55 +78,30 @@ func (hook *BPMHook) IsValid() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute hook if all conditions are met
|
// Execute hook if all conditions are met
|
||||||
func (hook *BPMHook) Execute(packageChanges map[string]string, verbose bool, rootDir string) error {
|
func (hook *BPMHook) Execute(modifiedFiles map[string]string, preOperation bool, verbose bool, rootDir string) error {
|
||||||
// Check if package dependencies are met
|
|
||||||
installedPackages, err := GetInstalledPackages(rootDir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, depend := range hook.Depends {
|
|
||||||
if !slices.Contains(installedPackages, depend) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get modified files slice
|
|
||||||
modifiedFiles := make([]*PackageFileEntry, 0)
|
|
||||||
for pkg := range packageChanges {
|
|
||||||
if GetPackage(pkg, rootDir) != nil {
|
|
||||||
modifiedFiles = append(modifiedFiles, GetPackage(pkg, rootDir).PkgFiles...)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if any targets are met
|
// Check if any targets are met
|
||||||
targetMet := false
|
targetsMet := make([]string, 0)
|
||||||
for _, target := range hook.Targets {
|
for _, target := range hook.Targets {
|
||||||
if targetMet {
|
for modifiedFile, action := range modifiedFiles {
|
||||||
break
|
// Check if this hook is triggered by this file's action
|
||||||
}
|
if !slices.Contains(hook.TriggerActions, action) {
|
||||||
if hook.TargetType == "package" {
|
continue
|
||||||
for change, operation := range packageChanges {
|
|
||||||
if target == change && slices.Contains(hook.TriggerOperations, operation) {
|
|
||||||
targetMet = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
glob, err := filepath.Glob(path.Join(rootDir, target))
|
// Check if file has already been checked
|
||||||
if err != nil {
|
if slices.Contains(targetsMet, modifiedFile) {
|
||||||
return err
|
continue
|
||||||
}
|
}
|
||||||
for _, change := range modifiedFiles {
|
|
||||||
if slices.Contains(glob, path.Join(rootDir, change.Path)) {
|
if matched, _ := filepath.Match(target, modifiedFile); !matched {
|
||||||
targetMet = true
|
continue
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
targetsMet = append(targetsMet, modifiedFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !targetMet {
|
|
||||||
|
if len(targetsMet) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,16 +110,25 @@ func (hook *BPMHook) Execute(packageChanges map[string]string, verbose bool, roo
|
|||||||
cmd := exec.Command(splitCommand[0], splitCommand[1:]...)
|
cmd := exec.Command(splitCommand[0], splitCommand[1:]...)
|
||||||
// Setup subprocess environment
|
// Setup subprocess environment
|
||||||
cmd.Dir = "/"
|
cmd.Dir = "/"
|
||||||
|
// Pass targets
|
||||||
|
if hook.PassTargets {
|
||||||
|
buffer := bytes.Buffer{}
|
||||||
|
buffer.WriteString(strings.Join(targetsMet, "\n") + "\n")
|
||||||
|
|
||||||
|
cmd.Stdin = &buffer
|
||||||
|
}
|
||||||
// Run hook in chroot if using the -R flag
|
// Run hook in chroot if using the -R flag
|
||||||
if rootDir != "/" {
|
if rootDir != "/" {
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{Chroot: rootDir}
|
cmd.SysProcAttr = &syscall.SysProcAttr{Chroot: rootDir}
|
||||||
}
|
}
|
||||||
|
|
||||||
if verbose {
|
if !verbose {
|
||||||
fmt.Printf("Running hook (%s) with run command: %s\n", hook.SourcePath, strings.Join(splitCommand, " "))
|
fmt.Printf("Running hook (%s)\n", filepath.Base(hook.SourcePath))
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Running hook (%s) with run command: %s\n", filepath.Base(hook.SourcePath), strings.Join(splitCommand, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+138
-83
@@ -14,7 +14,7 @@ import (
|
|||||||
type BPMOperation struct {
|
type BPMOperation struct {
|
||||||
Actions []OperationAction
|
Actions []OperationAction
|
||||||
UnresolvedDepends []string
|
UnresolvedDepends []string
|
||||||
Changes map[string]string
|
ModifiedFiles map[string]string
|
||||||
CompilationJobs int
|
CompilationJobs int
|
||||||
RunChecks bool
|
RunChecks bool
|
||||||
RootDir string
|
RootDir string
|
||||||
@@ -23,72 +23,6 @@ type BPMOperation struct {
|
|||||||
hasFetchedPackages bool
|
hasFetchedPackages bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) ActionsContainPackage(pkg string) bool {
|
|
||||||
for _, action := range operation.Actions {
|
|
||||||
if action.GetActionType() == "install" {
|
|
||||||
if action.(*InstallPackageAction).BpmPackage.PkgInfo.Name == pkg {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} else if action.GetActionType() == "fetch" {
|
|
||||||
if action.(*FetchPackageAction).DatabaseEntry.Info.Name == pkg {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} else if action.GetActionType() == "remove" {
|
|
||||||
if action.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (operation *BPMOperation) AppendAction(action OperationAction) {
|
|
||||||
operation.InsertActionAt(len(operation.Actions), action)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (operation *BPMOperation) InsertActionAt(index int, action OperationAction) {
|
|
||||||
if len(operation.Actions) == index { // nil or empty slice or after last element
|
|
||||||
operation.Actions = append(operation.Actions, action)
|
|
||||||
} else {
|
|
||||||
operation.Actions = append(operation.Actions[:index+1], operation.Actions[index:]...) // index < len(a)
|
|
||||||
operation.Actions[index] = action
|
|
||||||
}
|
|
||||||
|
|
||||||
if action.GetActionType() == "install" {
|
|
||||||
pkgInfo := action.(*InstallPackageAction).BpmPackage.PkgInfo
|
|
||||||
if !IsPackageInstalled(pkgInfo.Name, operation.RootDir) {
|
|
||||||
operation.Changes[pkgInfo.Name] = "install"
|
|
||||||
} else {
|
|
||||||
operation.Changes[pkgInfo.Name] = "upgrade"
|
|
||||||
}
|
|
||||||
} else if action.GetActionType() == "fetch" {
|
|
||||||
pkgInfo := action.(*FetchPackageAction).DatabaseEntry.Info
|
|
||||||
if !IsPackageInstalled(pkgInfo.Name, operation.RootDir) {
|
|
||||||
operation.Changes[pkgInfo.Name] = "install"
|
|
||||||
} else {
|
|
||||||
operation.Changes[pkgInfo.Name] = "upgrade"
|
|
||||||
}
|
|
||||||
} else if action.GetActionType() == "remove" {
|
|
||||||
operation.Changes[action.(*RemovePackageAction).BpmPackage.PkgInfo.Name] = "remove"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (operation *BPMOperation) RemoveAction(pkg, actionType string) {
|
|
||||||
operation.Actions = slices.DeleteFunc(operation.Actions, func(a OperationAction) bool {
|
|
||||||
if a.GetActionType() != actionType {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if a.GetActionType() == "install" {
|
|
||||||
return a.(*InstallPackageAction).BpmPackage.PkgInfo.Name == pkg
|
|
||||||
} else if a.GetActionType() == "fetch" {
|
|
||||||
return a.(*FetchPackageAction).DatabaseEntry.Info.Name == pkg
|
|
||||||
} else if a.GetActionType() == "remove" {
|
|
||||||
return a.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (operation *BPMOperation) GetTotalDownloadSize() int64 {
|
func (operation *BPMOperation) GetTotalDownloadSize() int64 {
|
||||||
var ret int64 = 0
|
var ret int64 = 0
|
||||||
for _, action := range operation.Actions {
|
for _, action := range operation.Actions {
|
||||||
@@ -154,8 +88,8 @@ func (operation *BPMOperation) ResolveDependencies(installRuntimeDepends bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Discover all dependencies
|
// Discover all dependencies
|
||||||
pos := 0
|
newActions := make([]OperationAction, 0)
|
||||||
for _, value := range slices.Clone(operation.Actions) {
|
for _, value := range operation.Actions {
|
||||||
var pkgInfo *PackageInfo
|
var pkgInfo *PackageInfo
|
||||||
if value.GetActionType() == "install" {
|
if value.GetActionType() == "install" {
|
||||||
action := value.(*InstallPackageAction)
|
action := value.(*InstallPackageAction)
|
||||||
@@ -174,11 +108,12 @@ func (operation *BPMOperation) ResolveDependencies(installRuntimeDepends bool) {
|
|||||||
operation.UnresolvedDepends = removeDuplicates(operation.UnresolvedDepends)
|
operation.UnresolvedDepends = removeDuplicates(operation.UnresolvedDepends)
|
||||||
|
|
||||||
for _, resolvedPkg := range resolved {
|
for _, resolvedPkg := range resolved {
|
||||||
if !operation.ActionsContainPackage(resolvedPkg.DatabaseEntry.Info.Name) && resolvedPkg.DatabaseEntry.Info.Name != pkgInfo.Name {
|
if ActionSliceIndex(newActions, resolvedPkg.DatabaseEntry.Info.Name) == -1 { // Dependency not in actions slice
|
||||||
operation.InsertActionAt(pos, &FetchPackageAction{
|
var action OperationAction = &FetchPackageAction{
|
||||||
InstallationReason: resolvedPkg.InstallationReason,
|
InstallationReason: resolvedPkg.InstallationReason,
|
||||||
DatabaseEntry: resolvedPkg.DatabaseEntry,
|
DatabaseEntry: resolvedPkg.DatabaseEntry,
|
||||||
})
|
}
|
||||||
|
newActions = append(newActions, action)
|
||||||
|
|
||||||
for _, vpkg := range resolvedPkg.DatabaseEntry.Info.Provides {
|
for _, vpkg := range resolvedPkg.DatabaseEntry.Info.Provides {
|
||||||
if _, ok := resolvedVirtualPackages[vpkg]; !ok {
|
if _, ok := resolvedVirtualPackages[vpkg]; !ok {
|
||||||
@@ -186,12 +121,19 @@ func (operation *BPMOperation) ResolveDependencies(installRuntimeDepends bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos++
|
// Check if can move original action
|
||||||
|
if i := ActionSliceIndex(operation.Actions, resolvedPkg.DatabaseEntry.Info.Name); i != -1 {
|
||||||
|
newActions[len(newActions)-1] = operation.Actions[i]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos++
|
if ActionSliceIndex(newActions, pkgInfo.Name) == -1 {
|
||||||
|
newActions = append(newActions, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operation.Actions = newActions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) Cleanup(cleanupMakeDepends bool) error {
|
func (operation *BPMOperation) Cleanup(cleanupMakeDepends bool) error {
|
||||||
@@ -250,6 +192,9 @@ func (operation *BPMOperation) Cleanup(cleanupMakeDepends bool) error {
|
|||||||
|
|
||||||
// Loop through all dependencies
|
// Loop through all dependencies
|
||||||
for _, depend := range depends {
|
for _, depend := range depends {
|
||||||
|
// Remove required version
|
||||||
|
depend, _, _ = SplitPkgNameAndVersion(depend)
|
||||||
|
|
||||||
// Resolve dependency
|
// Resolve dependency
|
||||||
var dependPkgInfo *PackageInfo
|
var dependPkgInfo *PackageInfo
|
||||||
if providers := GetVirtualPackageInfo(depend, operation.RootDir); len(providers) > 0 {
|
if providers := GetVirtualPackageInfo(depend, operation.RootDir); len(providers) > 0 {
|
||||||
@@ -304,10 +249,11 @@ func (operation *BPMOperation) ReplaceObsoletePackages() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range pkgInfo.Replaces {
|
for _, r := range pkgInfo.Replaces {
|
||||||
if bpmpkg := GetPackage(r, operation.RootDir); bpmpkg != nil && !operation.ActionsContainPackage(bpmpkg.PkgInfo.Name) {
|
if bpmpkg := GetPackage(r, operation.RootDir); bpmpkg != nil && ActionSliceIndex(operation.Actions, bpmpkg.PkgInfo.Name) == -1 {
|
||||||
operation.InsertActionAt(0, &RemovePackageAction{
|
var action OperationAction = &RemovePackageAction{
|
||||||
BpmPackage: bpmpkg,
|
BpmPackage: bpmpkg,
|
||||||
})
|
}
|
||||||
|
operation.Actions = slices.Insert(operation.Actions, 0, action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -516,16 +462,24 @@ func (operation *BPMOperation) GetOptionalDependencies() (optionalDepends map[st
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, depend := range pkgInfo.OptionalDepends {
|
for _, depend := range pkgInfo.OptionalDepends {
|
||||||
|
// Get optional dependency name
|
||||||
dependSplit := strings.SplitN(depend, ":", 2)
|
dependSplit := strings.SplitN(depend, ":", 2)
|
||||||
|
dependName, _, _ := SplitPkgNameAndVersion(dependSplit[0])
|
||||||
|
|
||||||
// Skip if dependency is already installed
|
// Skip if dependency is already installed
|
||||||
if IsPackageInstalled(dependSplit[0], operation.RootDir) {
|
if IsPackageInstalled(dependName, operation.RootDir) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if not a new dependency of the package
|
// Skip if not a new dependency of the package
|
||||||
if installedPkg := GetPackage(pkgInfo.Name, operation.RootDir); installedPkg != nil && slices.ContainsFunc(installedPkg.PkgInfo.OptionalDepends, func(n string) bool {
|
if installedPkg := GetPackage(pkgInfo.Name, operation.RootDir); installedPkg != nil && slices.ContainsFunc(installedPkg.PkgInfo.OptionalDepends, func(n string) bool {
|
||||||
return strings.SplitN(n, ":", 2)[0] == dependSplit[0]
|
// Remove optional dependency comment
|
||||||
|
n = strings.SplitN(n, ":", 2)[0]
|
||||||
|
|
||||||
|
// Remove required version
|
||||||
|
n, _, _ = SplitPkgNameAndVersion(n)
|
||||||
|
|
||||||
|
return n == dependName
|
||||||
}) {
|
}) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -533,7 +487,7 @@ func (operation *BPMOperation) GetOptionalDependencies() (optionalDepends map[st
|
|||||||
if len(dependSplit) == 2 {
|
if len(dependSplit) == 2 {
|
||||||
optionalDepends[pkgInfo.Name] = append(optionalDepends[pkgInfo.Name], fmt.Sprintf("%s (%s)", dependSplit[0], dependSplit[1]))
|
optionalDepends[pkgInfo.Name] = append(optionalDepends[pkgInfo.Name], fmt.Sprintf("%s (%s)", dependSplit[0], dependSplit[1]))
|
||||||
} else {
|
} else {
|
||||||
optionalDepends[pkgInfo.Name] = append(optionalDepends[pkgInfo.Name], dependSplit[0])
|
optionalDepends[pkgInfo.Name] = append(optionalDepends[pkgInfo.Name], dependName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -541,7 +495,7 @@ func (operation *BPMOperation) GetOptionalDependencies() (optionalDepends map[st
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) RunHooks(verbose bool) error {
|
func (operation *BPMOperation) RunPreHooks(verbose bool) error {
|
||||||
// Return if hooks directory does not exist
|
// Return if hooks directory does not exist
|
||||||
if stat, err := os.Stat(path.Join(operation.RootDir, "var/lib/bpm/hooks")); err != nil || !stat.IsDir() {
|
if stat, err := os.Stat(path.Join(operation.RootDir, "var/lib/bpm/hooks")); err != nil || !stat.IsDir() {
|
||||||
return nil
|
return nil
|
||||||
@@ -561,7 +515,46 @@ func (operation *BPMOperation) RunHooks(verbose bool) error {
|
|||||||
log.Printf("Error while reading hook (%s): %s", entry.Name(), err)
|
log.Printf("Error while reading hook (%s): %s", entry.Name(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = hook.Execute(operation.Changes, verbose, operation.RootDir)
|
if !hook.TriggerPreOperation {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = hook.Execute(operation.ModifiedFiles, false, verbose, operation.RootDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Warning: could not execute hook (%s): %s\n", entry.Name(), err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (operation *BPMOperation) RunPostHooks(verbose bool) error {
|
||||||
|
// Return if hooks directory does not exist
|
||||||
|
if stat, err := os.Stat(path.Join(operation.RootDir, "var/lib/bpm/hooks")); err != nil || !stat.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get directory entries in hooks directory
|
||||||
|
dirEntries, err := os.ReadDir(path.Join(operation.RootDir, "var/lib/bpm/hooks"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all hooks, validate and execute them
|
||||||
|
for _, entry := range dirEntries {
|
||||||
|
if entry.Type().IsRegular() && strings.HasSuffix(entry.Name(), ".bpmhook") {
|
||||||
|
hook, err := createHook(path.Join(operation.RootDir, "var/lib/bpm/hooks", entry.Name()))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error while reading hook (%s): %s", entry.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if hook.TriggerPreOperation {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = hook.Execute(operation.ModifiedFiles, false, verbose, operation.RootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Warning: could not execute hook (%s): %s\n", entry.Name(), err)
|
log.Printf("Warning: could not execute hook (%s): %s\n", entry.Name(), err)
|
||||||
continue
|
continue
|
||||||
@@ -645,9 +638,34 @@ func (operation *BPMOperation) FetchPackages() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
operation.hasFetchedPackages = true
|
operation.hasFetchedPackages = true
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (operation *BPMOperation) GetModifiedFiles() {
|
||||||
|
// Get modified files
|
||||||
|
for _, action := range operation.Actions {
|
||||||
|
if action.GetActionType() == "install" {
|
||||||
|
installAction := action.(*InstallPackageAction)
|
||||||
|
isUpgrade := IsPackageInstalled(installAction.BpmPackage.PkgInfo.Name, operation.RootDir)
|
||||||
|
|
||||||
|
for _, pkgFile := range installAction.BpmPackage.PkgFiles {
|
||||||
|
operation.ModifiedFiles[pkgFile.Path] = "install"
|
||||||
|
if isUpgrade {
|
||||||
|
operation.ModifiedFiles[pkgFile.Path] = "upgrade"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if action.GetActionType() == "remove" {
|
||||||
|
removeAction := action.(*RemovePackageAction)
|
||||||
|
|
||||||
|
for _, pkgFile := range removeAction.BpmPackage.PkgFiles {
|
||||||
|
operation.ModifiedFiles[pkgFile.Path] = "remove"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
|
func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
|
||||||
// Fetch packages
|
// Fetch packages
|
||||||
if !operation.hasFetchedPackages {
|
if !operation.hasFetchedPackages {
|
||||||
@@ -740,7 +758,6 @@ func (operation *BPMOperation) Execute(verbose, force bool) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("Operation complete!")
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -776,3 +793,41 @@ type RemovePackageAction struct {
|
|||||||
func (action *RemovePackageAction) GetActionType() string {
|
func (action *RemovePackageAction) GetActionType() string {
|
||||||
return "remove"
|
return "remove"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ActionSliceIndex(actions []OperationAction, pkg string) int {
|
||||||
|
for i, action := range actions {
|
||||||
|
if action.GetActionType() == "install" {
|
||||||
|
if action.(*InstallPackageAction).BpmPackage.PkgInfo.Name == pkg {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
} else if action.GetActionType() == "fetch" {
|
||||||
|
if action.(*FetchPackageAction).DatabaseEntry.Info.Name == pkg {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
} else if action.GetActionType() == "remove" {
|
||||||
|
if action.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func ActionSliceRemove(actions []OperationAction, pkg, actionType string) []OperationAction {
|
||||||
|
actions = slices.DeleteFunc(actions, func(a OperationAction) bool {
|
||||||
|
if a.GetActionType() != actionType {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if a.GetActionType() == "install" {
|
||||||
|
return a.(*InstallPackageAction).BpmPackage.PkgInfo.Name == pkg
|
||||||
|
} else if a.GetActionType() == "fetch" {
|
||||||
|
return a.(*FetchPackageAction).DatabaseEntry.Info.Name == pkg
|
||||||
|
} else if a.GetActionType() == "remove" {
|
||||||
|
return a.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
return actions
|
||||||
|
}
|
||||||
|
|||||||
+101
-30
@@ -10,6 +10,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -698,6 +699,17 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
|
|||||||
extractFilename := path.Join(rootDir, header.Name)
|
extractFilename := path.Join(rootDir, header.Name)
|
||||||
switch header.Typeflag {
|
switch header.Typeflag {
|
||||||
case tar.TypeDir:
|
case tar.TypeDir:
|
||||||
|
// Check if path is set to be ignored
|
||||||
|
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
|
||||||
|
matched, _ := filepath.Match(s, header.Name)
|
||||||
|
return matched
|
||||||
|
}); rootDir == "/" && ok {
|
||||||
|
if verbose {
|
||||||
|
fmt.Printf("Skipping Directory: %s (Path was ignored)\n", extractFilename)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(extractFilename); err == nil {
|
if _, err := os.Stat(extractFilename); err == nil {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Printf("Skipping Directory: %s (Directory already exists)\n", extractFilename)
|
fmt.Printf("Skipping Directory: %s (Directory already exists)\n", extractFilename)
|
||||||
@@ -725,6 +737,17 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
|
|||||||
}
|
}
|
||||||
bar.Add64(header.Size)
|
bar.Add64(header.Size)
|
||||||
case tar.TypeReg:
|
case tar.TypeReg:
|
||||||
|
// Check if path is set to be ignored
|
||||||
|
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
|
||||||
|
matched, _ := filepath.Match(s, header.Name)
|
||||||
|
return matched
|
||||||
|
}); rootDir == "/" && ok {
|
||||||
|
if verbose {
|
||||||
|
fmt.Printf("Skipping File: %s (Path was ignored)\n", extractFilename)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
skip := false
|
skip := false
|
||||||
if _, err := os.Stat(extractFilename); err == nil {
|
if _, err := os.Stat(extractFilename); err == nil {
|
||||||
for _, k := range bpmpkg.PkgInfo.Keep {
|
for _, k := range bpmpkg.PkgInfo.Keep {
|
||||||
@@ -782,6 +805,17 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
|
|||||||
}
|
}
|
||||||
bar.Add64(header.Size)
|
bar.Add64(header.Size)
|
||||||
case tar.TypeSymlink:
|
case tar.TypeSymlink:
|
||||||
|
// Check if path is set to be ignored
|
||||||
|
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
|
||||||
|
matched, _ := filepath.Match(s, header.Name)
|
||||||
|
return matched
|
||||||
|
}); rootDir == "/" && ok {
|
||||||
|
if verbose {
|
||||||
|
fmt.Printf("Skipping Symlink: %s (Path was ignored)\n", extractFilename)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
err := os.Remove(extractFilename)
|
err := os.Remove(extractFilename)
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
@@ -797,6 +831,17 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string)
|
|||||||
}
|
}
|
||||||
bar.Add64(header.Size)
|
bar.Add64(header.Size)
|
||||||
case tar.TypeLink:
|
case tar.TypeLink:
|
||||||
|
// Check if path is set to be ignored
|
||||||
|
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
|
||||||
|
matched, _ := filepath.Match(s, header.Name)
|
||||||
|
return matched
|
||||||
|
}); rootDir == "/" && ok {
|
||||||
|
if verbose {
|
||||||
|
fmt.Printf("Skipping Hard Link: %s (Path was ignored)\n", extractFilename)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Detected Hard Link: " + extractFilename + " -> " + path.Join(rootDir, strings.TrimPrefix(header.Linkname, "files/")))
|
fmt.Println("Detected Hard Link: " + extractFilename + " -> " + path.Join(rootDir, strings.TrimPrefix(header.Linkname, "files/")))
|
||||||
}
|
}
|
||||||
@@ -872,26 +917,39 @@ func installPackage(filename string, installationReason InstallationReason, root
|
|||||||
fmt.Printf("Removing old files for package (%s)...\n", bpmpkg.PkgInfo.Name)
|
fmt.Printf("Removing old files for package (%s)...\n", bpmpkg.PkgInfo.Name)
|
||||||
}
|
}
|
||||||
for _, entry := range fileEntries {
|
for _, entry := range fileEntries {
|
||||||
file := path.Join(rootDir, entry.Path)
|
finalPath := path.Join(rootDir, entry.Path)
|
||||||
stat, err := os.Lstat(file)
|
|
||||||
|
stat, err := os.Lstat(finalPath)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
continue
|
continue
|
||||||
}
|
} else if err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(files[entry.Path]) != 0 {
|
|
||||||
|
// Check if path is set to be ignored
|
||||||
|
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
|
||||||
|
matched, _ := filepath.Match(s, entry.Path)
|
||||||
|
return matched
|
||||||
|
}); rootDir == "/" && ok {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Skipping path: " + file + " (Path is managed by multiple packages)")
|
fmt.Printf("Skipping path: %s (Path was ignored)\n", finalPath)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(files[entry.Path]) != 0 {
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Skipping path: " + finalPath + " (Path is managed by multiple packages)")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
shouldContinue := false
|
shouldContinue := false
|
||||||
for _, value := range bpmpkg.PkgInfo.Keep {
|
for _, value := range bpmpkg.PkgInfo.Keep {
|
||||||
if strings.HasSuffix(value, "/") {
|
if strings.HasSuffix(value, "/") {
|
||||||
if strings.HasPrefix(entry.Path, value) || entry.Path == strings.TrimSuffix(value, "/") {
|
if strings.HasPrefix(entry.Path, value) || entry.Path == strings.TrimSuffix(value, "/") {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Skipping path: " + file + " (Path is set to be kept during reinstalls/updates)")
|
fmt.Println("Skipping path: " + finalPath + " (Path is set to be kept during reinstalls/updates)")
|
||||||
}
|
}
|
||||||
shouldContinue = true
|
shouldContinue = true
|
||||||
continue
|
continue
|
||||||
@@ -899,7 +957,7 @@ func installPackage(filename string, installationReason InstallationReason, root
|
|||||||
} else {
|
} else {
|
||||||
if entry.Path == value {
|
if entry.Path == value {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Skipping path: " + file + " (Path is set to be kept during reinstalls/updates)")
|
fmt.Println("Skipping path: " + finalPath + " (Path is set to be kept during reinstalls/updates)")
|
||||||
}
|
}
|
||||||
shouldContinue = true
|
shouldContinue = true
|
||||||
continue
|
continue
|
||||||
@@ -911,37 +969,37 @@ func installPackage(filename string, installationReason InstallationReason, root
|
|||||||
}
|
}
|
||||||
if stat.Mode()&os.ModeSymlink != 0 {
|
if stat.Mode()&os.ModeSymlink != 0 {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Removing: " + file)
|
fmt.Println("Removing: " + finalPath)
|
||||||
}
|
}
|
||||||
err := os.Remove(file)
|
err := os.Remove(finalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if stat.IsDir() {
|
if stat.IsDir() {
|
||||||
dir, err := os.ReadDir(file)
|
dir, err := os.ReadDir(finalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(dir) != 0 {
|
if len(dir) != 0 {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Skipping non-empty directory: " + file)
|
fmt.Println("Skipping non-empty directory: " + finalPath)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Removing: " + file)
|
fmt.Println("Removing: " + finalPath)
|
||||||
}
|
}
|
||||||
err = os.Remove(file)
|
err = os.Remove(finalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Removing: " + file)
|
fmt.Println("Removing: " + finalPath)
|
||||||
}
|
}
|
||||||
err := os.Remove(file)
|
err := os.Remove(finalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1111,31 +1169,44 @@ func removePackage(pkg string, verbose bool, rootDir string) error {
|
|||||||
// Removing package files
|
// Removing package files
|
||||||
for _, entry := range fileEntries {
|
for _, entry := range fileEntries {
|
||||||
bar.Add64(entry.SizeInBytes)
|
bar.Add64(entry.SizeInBytes)
|
||||||
file := path.Join(rootDir, entry.Path)
|
|
||||||
lstat, err := os.Lstat(file)
|
finalPath := path.Join(rootDir, entry.Path)
|
||||||
|
|
||||||
|
lstat, err := os.Lstat(finalPath)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
continue
|
continue
|
||||||
}
|
} else if err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if path is set to be ignored
|
||||||
|
if ok := slices.ContainsFunc(MainBPMConfig.IgnorePaths, func(s string) bool {
|
||||||
|
matched, _ := filepath.Match(s, entry.Path)
|
||||||
|
return matched
|
||||||
|
}); rootDir == "/" && ok {
|
||||||
|
if verbose {
|
||||||
|
fmt.Printf("Skipping path: %s (Path was ignored)\n", finalPath)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if len(files[entry.Path]) != 0 {
|
if len(files[entry.Path]) != 0 {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Skipping path: " + file + "(Path is managed by multiple packages)")
|
fmt.Println("Skipping path: " + finalPath + "(Path is managed by multiple packages)")
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if lstat.Mode()&os.ModeSymlink != 0 {
|
if lstat.Mode()&os.ModeSymlink != 0 {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Removing: " + file)
|
fmt.Println("Removing: " + finalPath)
|
||||||
}
|
}
|
||||||
err := os.Remove(file)
|
err := os.Remove(finalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stat, err := os.Stat(file)
|
stat, err := os.Stat(finalPath)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1143,28 +1214,28 @@ func removePackage(pkg string, verbose bool, rootDir string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if stat.IsDir() {
|
if stat.IsDir() {
|
||||||
dir, err := os.ReadDir(file)
|
dir, err := os.ReadDir(finalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(dir) != 0 {
|
if len(dir) != 0 {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Skipping non-empty directory: " + file)
|
fmt.Println("Skipping non-empty directory: " + finalPath)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Removing: " + file)
|
fmt.Println("Removing: " + finalPath)
|
||||||
}
|
}
|
||||||
err = os.Remove(file)
|
err = os.Remove(finalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if verbose {
|
if verbose {
|
||||||
fmt.Println("Removing: " + file)
|
fmt.Println("Removing: " + finalPath)
|
||||||
}
|
}
|
||||||
err := os.Remove(file)
|
err := os.Remove(finalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user