From 918ff984ca350c28dfd3d8ab6b6619d071006ed6 Mon Sep 17 00:00:00 2001 From: EnumDev Date: Thu, 17 Oct 2024 11:54:32 +0300 Subject: [PATCH] Moved package fetching, installation and removal functionality to operations.go --- main.go | 357 ++++++++++------------------------------- utils/general_utils.go | 13 +- utils/operations.go | 201 ++++++++++++++++++++++- utils/package_utils.go | 17 +- 4 files changed, 294 insertions(+), 294 deletions(-) diff --git a/main.go b/main.go index 4ce677b..471ccf0 100644 --- a/main.go +++ b/main.go @@ -4,7 +4,6 @@ import ( "bufio" "flag" "fmt" - "github.com/elliotchance/orderedmap/v2" "gitlab.com/bubble-package-manager/bpm/utils" "log" "os" @@ -174,8 +173,11 @@ func resolveCommand() { return } - operation := utils.BPMOperation{Actions: make([]utils.OperationAction, 0)} - unresolvedDepends := make([]string, 0) + operation := utils.BPMOperation{ + Actions: make([]utils.OperationAction, 0), + UnresolvedDepends: make([]string, 0), + RootDir: rootDir, + } // Search for packages for _, pkg := range pkgs { @@ -206,99 +208,24 @@ func resolveCommand() { }) } } - pos := 0 - for _, value := range slices.Clone(operation.Actions) { - var resolved, unresolved []string - var pkgInfo *utils.PackageInfo - if value.GetActionType() == "install" { - action := value.(*utils.InstallPackageAction) - pkgInfo = action.BpmPackage.PkgInfo - } else if value.GetActionType() == "fetch" { - action := value.(*utils.FetchPackageAction) - pkgInfo = action.RepositoryEntry.Info - } - resolved, unresolved = pkgInfo.ResolveAll(&[]string{}, &[]string{}, pkgInfo.Type == "source", !noOptional, !reinstallAll, verbose, rootDir) - - unresolvedDepends = append(unresolvedDepends, unresolved...) - for _, depend := range resolved { - if !operation.ActionsContainPackage(depend) && depend != pkgInfo.Name { - if !reinstallAll && utils.IsPackageInstalled(depend, rootDir) { - continue - } - entry, _, err := utils.GetRepositoryEntry(depend) - if err != nil { - log.Fatalf("Error: could not find package (%s) in any repository\n", pkgInfo.Name) - } - operation.InsertActionAt(pos, &utils.FetchPackageAction{ - IsDependency: true, - RepositoryEntry: entry, - }) - pos++ - } - } - pos++ + // Resolve dependencies + err := operation.ResolveDependencies(reinstallAll, !noOptional, verbose) + if err != nil { + log.Fatalf("Error: could not resolve dependencies: %s\n", err) } - - // Show summary - if len(unresolvedDepends) != 0 { + if len(operation.UnresolvedDepends) != 0 { if !force { - log.Fatalf("Error: the following dependencies could not be found in any repositories: %s\n", strings.Join(unresolvedDepends, ", ")) + log.Fatalf("Error: the following dependencies could not be found in any repositories: %s\n", strings.Join(operation.UnresolvedDepends, ", ")) } else { - log.Println("Warning: The following dependencies could not be found in any repositories: " + strings.Join(unresolvedDepends, ", ")) - } - } - if len(operation.Actions) == 0 { - fmt.Println("All packages are up to date!") - os.Exit(0) - } - - for _, value := range operation.Actions { - var pkgInfo *utils.PackageInfo - if value.GetActionType() == "install" { - pkgInfo = value.(*utils.InstallPackageAction).BpmPackage.PkgInfo - } else if value.GetActionType() == "fetch" { - pkgInfo = value.(*utils.FetchPackageAction).RepositoryEntry.Info - } else { - pkgInfo = value.(*utils.RemovePackageAction).BpmPackage.PkgInfo - fmt.Printf("%s: %s (Remove)\n", pkgInfo.Name, pkgInfo.GetFullVersion()) - } - - installedInfo := utils.GetPackageInfo(pkgInfo.Name, rootDir) - sourceInfo := "" - if pkgInfo.Type == "source" { - if rootDir != "/" && !force { - log.Fatalf("Error: cannot compile and install source packages to a different root directory") - } - sourceInfo = "(From Source)" - } - - if installedInfo == nil { - fmt.Printf("%s: %s (Install) %s\n", pkgInfo.Name, pkgInfo.GetFullVersion(), sourceInfo) - } else { - comparison := utils.ComparePackageVersions(*pkgInfo, *installedInfo) - if comparison < 0 { - fmt.Printf("%s: %s -> %s (Downgrade) %s\n", pkgInfo.Name, installedInfo.GetFullVersion(), pkgInfo.GetFullVersion(), sourceInfo) - } else if comparison > 0 { - fmt.Printf("%s: %s -> %s (Upgrade) %s\n", pkgInfo.Name, installedInfo.GetFullVersion(), pkgInfo.GetFullVersion(), sourceInfo) - } else { - fmt.Printf("%s: %s (Reinstall) %s\n", pkgInfo.Name, pkgInfo.GetFullVersion(), sourceInfo) - } + log.Println("Warning: The following dependencies could not be found in any repositories: " + strings.Join(operation.UnresolvedDepends, ", ")) } } - if rootDir != "/" { - fmt.Println("Warning: Operating in " + rootDir) - } - if operation.GetTotalDownloadSize() > 0 { - fmt.Printf("%s will be downloaded to complete this operation\n", utils.BytesToHumanReadable(operation.GetTotalDownloadSize())) - } - if operation.GetFinalActionSize(rootDir) > 0 { - fmt.Printf("A total of %s will be installed after the operation finishes\n", utils.BytesToHumanReadable(operation.GetFinalActionSize(rootDir))) - } else if operation.GetFinalActionSize(rootDir) < 0 { - fmt.Printf("A total of %s will be freed after the operation finishes\n", utils.BytesToHumanReadable(operation.GetFinalActionSize(rootDir))) - } + // Show operation summary + operation.ShowOperationSummary() + // Confirmation Prompt if !yesAll { reader := bufio.NewReader(os.Stdin) if len(operation.Actions) == 1 { @@ -309,64 +236,15 @@ func resolveCommand() { text, _ := reader.ReadString('\n') if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" { - fmt.Println("Cancelling...") + fmt.Println("Cancelling package installation...") os.Exit(1) } } - // Fetch packages from repositories - fmt.Println("Fetching packages from available repositories...") - for i, action := range operation.Actions { - if action.GetActionType() != "fetch" { - continue - } - entry := action.(*utils.FetchPackageAction).RepositoryEntry - fetchedPackage, err := entry.Repository.FetchPackage(entry.Info.Name) - if err != nil { - log.Fatalf("Error: could not fetch package (%s): %s\n", entry.Info.Name, err) - } - bpmpkg, err := utils.ReadPackage(fetchedPackage) - if err != nil { - log.Fatalf("Error: could not fetch package (%s): %s\n", entry.Info.Name, err) - } - fmt.Printf("Package (%s) was successfully fetched!\n", bpmpkg.PkgInfo.Name) - operation.Actions[i] = &utils.InstallPackageAction{ - File: fetchedPackage, - IsDependency: action.(*utils.FetchPackageAction).IsDependency, - BpmPackage: bpmpkg, - } - } - - // Install fetched packages - for _, action := range operation.Actions { - if action.GetActionType() != "install" { - continue - } - value := action.(*utils.InstallPackageAction) - bpmpkg := value.BpmPackage - var err error - if value.IsDependency { - err = utils.InstallPackage(value.File, rootDir, verbose, true, buildSource, skipCheck, keepTempDir) - } else { - err = utils.InstallPackage(value.File, rootDir, verbose, force, buildSource, skipCheck, keepTempDir) - } - - if err != nil { - if bpmpkg.PkgInfo.Type == "source" && keepTempDir { - fmt.Println("BPM temp directory was created at /var/tmp/bpm_source-" + bpmpkg.PkgInfo.Name) - } - log.Fatalf("Error: could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err) - } - fmt.Printf("Package (%s) was successfully installed\n", bpmpkg.PkgInfo.Name) - if value.IsDependency { - err := utils.SetInstallationReason(bpmpkg.PkgInfo.Name, utils.Dependency, rootDir) - if err != nil { - log.Fatalf("Error: could not set installation reason for package: %s\n", err) - } - } - if bpmpkg.PkgInfo.Type == "source" && keepTempDir { - fmt.Println("** It is recommended you delete the temporary bpm folder in /var/tmp **") - } + // Execute operation + err = operation.Execute(verbose, force) + if err != nil { + log.Fatalf("Error: could not complete operation: %s\n", err) } case update: if os.Getuid() != 0 { @@ -392,10 +270,14 @@ func resolveCommand() { if err != nil { log.Fatalf("Error: could not get installed packages: %s\n", err) } - toUpdate := orderedmap.NewOrderedMap[string, *struct { - isDependency bool - entry *utils.RepositoryEntry - }]() + + operation := utils.BPMOperation{ + Actions: make([]utils.OperationAction, 0), + UnresolvedDepends: make([]string, 0), + RootDir: rootDir, + } + + // Search for packages for _, pkg := range pkgs { entry, _, err := utils.GetRepositoryEntry(pkg) if err != nil { @@ -406,131 +288,46 @@ func resolveCommand() { log.Fatalf("Error: could not get package info for (%s)\n", pkg) } else { comparison := utils.ComparePackageVersions(*entry.Info, *installedInfo) - if comparison > 0 { - toUpdate.Set(entry.Info.Name, &struct { - isDependency bool - entry *utils.RepositoryEntry - }{isDependency: false, entry: entry}) - } else if reinstall { - toUpdate.Set(entry.Info.Name, &struct { - isDependency bool - entry *utils.RepositoryEntry - }{isDependency: false, entry: entry}) + if comparison > 0 || reinstall { + operation.Actions = append(operation.Actions, &utils.FetchPackageAction{ + IsDependency: false, + RepositoryEntry: entry, + }) } } } - if toUpdate.Len() == 0 { - fmt.Println("All packages are up to date!") - os.Exit(0) - } // Check for new dependencies in updated packages - unresolved := make([]string, 0) - clone := toUpdate.Copy() - for _, key := range clone.Keys() { - pkg, _ := clone.Get(key) - r, u := pkg.entry.Info.ResolveAll(&[]string{}, &[]string{}, pkg.entry.Info.Type == "source", !noOptional, true, verbose, rootDir) - unresolved = append(unresolved, u...) - for _, depend := range r { - if _, ok := toUpdate.Get(depend); !ok { - entry, _, err := utils.GetRepositoryEntry(depend) - if err != nil { - log.Fatalf("Error: could not find package (%s) in any repository\n", depend) - } - toUpdate.Set(depend, &struct { - isDependency bool - entry *utils.RepositoryEntry - }{isDependency: true, entry: entry}) - } - } + err = operation.ResolveDependencies(reinstallAll, !noOptional, verbose) + if err != nil { + log.Fatalf("Error: could not resolve dependencies: %s\n", err) } - - if len(unresolved) != 0 { + if len(operation.UnresolvedDepends) != 0 { if !force { - log.Fatalf("Error: the following dependencies could not be found in any repositories: %s\n", strings.Join(unresolved, ", ")) + log.Fatalf("Error: the following dependencies could not be found in any repositories: %s\n", strings.Join(operation.UnresolvedDepends, ", ")) } else { - log.Printf("Warning: the following dependencies could not be found in any repositories: %s\n", strings.Join(unresolved, ", ")) + log.Println("Warning: The following dependencies could not be found in any repositories: " + strings.Join(operation.UnresolvedDepends, ", ")) } } - for _, key := range toUpdate.Keys() { - value, _ := toUpdate.Get(key) - installedInfo := utils.GetPackageInfo(value.entry.Info.Name, rootDir) - sourceInfo := "" - if value.entry.Info.Type == "source" { - sourceInfo = "(From Source)" - } - if installedInfo == nil { - fmt.Printf("%s: %s (Install) %s\n", value.entry.Info.Name, value.entry.Info.GetFullVersion(), sourceInfo) - continue - } else { - comparison := utils.ComparePackageVersions(*value.entry.Info, *installedInfo) - if comparison > 0 { - fmt.Printf("%s: %s -> %s (Upgrade) %s\n", value.entry.Info.Name, installedInfo.GetFullVersion(), value.entry.Info.GetFullVersion(), sourceInfo) - } else if reinstall { - fmt.Printf("%s: %s -> %s (Reinstall) %s\n", value.entry.Info.Name, installedInfo.GetFullVersion(), value.entry.Info.GetFullVersion(), sourceInfo) - } - } - } + // Show operation summary + operation.ShowOperationSummary() - // Update confirmation prompt + // Confirmation Prompt if !yesAll { - fmt.Printf("Are you sure you wish to update all %d packages? [y\\N] ", toUpdate.Len()) + fmt.Printf("Are you sure you wish to update all %d packages? [y\\N] ", len(operation.Actions)) reader := bufio.NewReader(os.Stdin) text, _ := reader.ReadString('\n') if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" { - fmt.Println("Cancelling update...") + fmt.Println("Cancelling package update...") os.Exit(1) } } - // Fetch packages - pkgsToInstall := orderedmap.NewOrderedMap[string, *struct { - isDependency bool - entry *utils.RepositoryEntry - }]() - fmt.Println("Fetching packages from available repositories...") - for _, pkg := range toUpdate.Keys() { - value, _ := toUpdate.Get(pkg) - entry, repo, err := utils.GetRepositoryEntry(pkg) - if err != nil { - log.Fatalf("Error: could not find package (%s) in any repository\n", pkg) - } - fetchedPackage, err := repo.FetchPackage(entry.Info.Name) - if err != nil { - log.Fatalf("Error: could not fetch package (%s): %s\n", pkg, err) - } - fmt.Printf("Package (%s) was successfully fetched!\n", value.entry.Info.Name) - pkgsToInstall.Set(fetchedPackage, value) - } - - // Install fetched packages - for _, pkg := range pkgsToInstall.Keys() { - value, _ := pkgsToInstall.Get(pkg) - pkgInfo := value.entry.Info - var err error - if value.isDependency { - err = utils.InstallPackage(pkg, rootDir, verbose, true, buildSource, skipCheck, keepTempDir) - } else { - err = utils.InstallPackage(pkg, rootDir, verbose, force, buildSource, skipCheck, keepTempDir) - } - - if err != nil { - if pkgInfo.Type == "source" && keepTempDir { - fmt.Println("BPM temp directory was created at /var/tmp/bpm_source-" + pkgInfo.Name) - } - log.Fatalf("Error: could not install package (%s): %s\n", pkg, err) - } - fmt.Printf("Package (%s) was successfully installed!\n", pkgInfo.Name) - if value.isDependency { - err := utils.SetInstallationReason(pkgInfo.Name, utils.Dependency, rootDir) - if err != nil { - log.Fatalf("Error: could not set installation reason for package: %s\n", err) - } - } - if pkgInfo.Type == "source" && keepTempDir { - fmt.Println("** It is recommended you delete the temporary bpm folder in /var/tmp **") - } + // Execute operation + err = operation.Execute(verbose, force) + if err != nil { + log.Fatalf("Error: could not complete operation: %s\n", err) } case sync: if os.Getuid() != 0 { @@ -541,7 +338,7 @@ func resolveCommand() { reader := bufio.NewReader(os.Stdin) text, _ := reader.ReadString('\n') if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" { - fmt.Println("Cancelling sync...") + fmt.Println("Cancelling database synchronization...") os.Exit(1) } } @@ -562,32 +359,40 @@ func resolveCommand() { fmt.Println("No packages were given") return } - for _, pkg := range packages { - pkgInfo := utils.GetPackageInfo(pkg, rootDir) - if pkgInfo == nil { - fmt.Printf("Package (%s) could not be found\n", pkg) - continue - } - fmt.Println("----------------\n" + utils.CreateReadableInfo(false, false, false, pkgInfo, rootDir)) - fmt.Println("----------------") - if rootDir != "/" { - fmt.Println("Warning: Operating in " + rootDir) - } - if !yesAll { - reader := bufio.NewReader(os.Stdin) - fmt.Print("Do you wish to remove this package? [y\\N] ") - text, _ := reader.ReadString('\n') - if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" { - fmt.Printf("Skipping package (%s)...\n", pkgInfo.Name) - continue - } - } - err := utils.RemovePackage(pkg, verbose, rootDir) - if err != nil { - log.Fatalf("Error: could not remove package: %s\n", err) + operation := &utils.BPMOperation{ + Actions: make([]utils.OperationAction, 0), + UnresolvedDepends: make([]string, 0), + RootDir: rootDir, + } + + // Search for packages + for _, pkg := range packages { + bpmpkg := utils.GetPackage(pkg, rootDir) + if bpmpkg == nil { + log.Fatalf("Error: package (%s) could not be found\n", pkg) } - fmt.Printf("Package (%s) was successfully removed!\n", pkgInfo.Name) + operation.Actions = append(operation.Actions, &utils.RemovePackageAction{BpmPackage: bpmpkg}) + } + + // Show operation summary + operation.ShowOperationSummary() + + // Confirmation Prompt + if !yesAll { + fmt.Printf("Are you sure you wish to remove all %d packages? [y\\N] ", len(operation.Actions)) + reader := bufio.NewReader(os.Stdin) + text, _ := reader.ReadString('\n') + if strings.TrimSpace(strings.ToLower(text)) != "y" && strings.TrimSpace(strings.ToLower(text)) != "yes" { + fmt.Println("Cancelling package removal...") + os.Exit(1) + } + } + + // Execute operation + err := operation.Execute(verbose, force) + if err != nil { + log.Fatalf("Error: could not complete operation: %s\n", err) } case file: files := subcommandArgs diff --git a/utils/general_utils.go b/utils/general_utils.go index 51ce30b..18fd718 100644 --- a/utils/general_utils.go +++ b/utils/general_utils.go @@ -49,7 +49,18 @@ func stringSliceRemove(s []string, r string) []string { return s } -func BytesToHumanReadable(b uint64) string { +func UnsignedBytesToHumanReadable(b uint64) string { + bf := float64(b) + for _, unit := range []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"} { + if math.Abs(bf) < 1024.0 { + return fmt.Sprintf("%3.1f%sB", bf, unit) + } + bf /= 1024.0 + } + return fmt.Sprintf("%.1fYiB", bf) +} + +func BytesToHumanReadable(b int64) string { bf := float64(b) for _, unit := range []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"} { if math.Abs(bf) < 1024.0 { diff --git a/utils/operations.go b/utils/operations.go index 7a00ad1..021c060 100644 --- a/utils/operations.go +++ b/utils/operations.go @@ -1,7 +1,18 @@ package utils +import ( + "errors" + "fmt" + "log" + "os" + "slices" + "strings" +) + type BPMOperation struct { - Actions []OperationAction + Actions []OperationAction + UnresolvedDepends []string + RootDir string } func (operation *BPMOperation) ActionsContainPackage(pkg string) bool { @@ -47,23 +58,199 @@ func (operation *BPMOperation) GetTotalInstalledSize() uint64 { return ret } -func (operation *BPMOperation) GetFinalActionSize(rootDir string) uint64 { - var ret uint64 = 0 +func (operation *BPMOperation) GetFinalActionSize(rootDir string) int64 { + var ret int64 = 0 for _, action := range operation.Actions { if action.GetActionType() == "install" { - ret += action.(*InstallPackageAction).BpmPackage.GetInstalledSize() + ret += int64(action.(*InstallPackageAction).BpmPackage.GetInstalledSize()) if IsPackageInstalled(action.(*InstallPackageAction).BpmPackage.PkgInfo.Name, rootDir) { - ret -= GetPackage(action.(*InstallPackageAction).BpmPackage.PkgInfo.Name, rootDir).GetInstalledSize() + ret -= int64(GetPackage(action.(*InstallPackageAction).BpmPackage.PkgInfo.Name, rootDir).GetInstalledSize()) } } else if action.GetActionType() == "fetch" { - ret += action.(*FetchPackageAction).RepositoryEntry.InstalledSize + ret += int64(action.(*FetchPackageAction).RepositoryEntry.InstalledSize) } else if action.GetActionType() == "remove" { - ret -= action.(*RemovePackageAction).BpmPackage.GetInstalledSize() + ret -= int64(action.(*RemovePackageAction).BpmPackage.GetInstalledSize()) } } return ret } +func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, installOptionalDependencies, verbose bool) error { + 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.RepositoryEntry.Info + } else { + pos++ + continue + } + + resolved, unresolved := pkgInfo.ResolveDependencies(&[]string{}, &[]string{}, pkgInfo.Type == "source", installOptionalDependencies, !reinstallDependencies, verbose, operation.RootDir) + + operation.UnresolvedDepends = append(operation.UnresolvedDepends, unresolved...) + + for _, depend := range resolved { + if !operation.ActionsContainPackage(depend) && depend != pkgInfo.Name { + if !reinstallDependencies && IsPackageInstalled(depend, operation.RootDir) { + continue + } + entry, _, err := GetRepositoryEntry(depend) + if err != nil { + return errors.New("could not get repository entry for package (" + depend + ")") + } + operation.InsertActionAt(pos, &FetchPackageAction{ + IsDependency: true, + RepositoryEntry: entry, + }) + pos++ + } + } + pos++ + } + + return nil +} + +func (operation *BPMOperation) ShowOperationSummary() { + if len(operation.Actions) == 0 { + fmt.Println("All packages are up to date!") + os.Exit(0) + } + + for _, value := range operation.Actions { + var pkgInfo *PackageInfo + if value.GetActionType() == "install" { + pkgInfo = value.(*InstallPackageAction).BpmPackage.PkgInfo + } else if value.GetActionType() == "fetch" { + pkgInfo = value.(*FetchPackageAction).RepositoryEntry.Info + } else { + pkgInfo = value.(*RemovePackageAction).BpmPackage.PkgInfo + fmt.Printf("%s: %s (Remove)\n", pkgInfo.Name, pkgInfo.GetFullVersion()) + continue + } + + installedInfo := GetPackageInfo(pkgInfo.Name, operation.RootDir) + sourceInfo := "" + if pkgInfo.Type == "source" { + if operation.RootDir != "/" { + log.Fatalf("cannot compile and install source packages to a different root directory") + } + sourceInfo = "(From Source)" + } + + if installedInfo == nil { + fmt.Printf("%s: %s (Install) %s\n", pkgInfo.Name, pkgInfo.GetFullVersion(), sourceInfo) + } else { + comparison := ComparePackageVersions(*pkgInfo, *installedInfo) + if comparison < 0 { + fmt.Printf("%s: %s -> %s (Downgrade) %s\n", pkgInfo.Name, installedInfo.GetFullVersion(), pkgInfo.GetFullVersion(), sourceInfo) + } else if comparison > 0 { + fmt.Printf("%s: %s -> %s (Upgrade) %s\n", pkgInfo.Name, installedInfo.GetFullVersion(), pkgInfo.GetFullVersion(), sourceInfo) + } else { + fmt.Printf("%s: %s (Reinstall) %s\n", pkgInfo.Name, pkgInfo.GetFullVersion(), sourceInfo) + } + } + } + + if operation.RootDir != "/" { + fmt.Println("Warning: Operating in " + operation.RootDir) + } + if operation.GetTotalDownloadSize() > 0 { + fmt.Printf("%s will be downloaded to complete this operation\n", UnsignedBytesToHumanReadable(operation.GetTotalDownloadSize())) + } + if operation.GetFinalActionSize(operation.RootDir) > 0 { + fmt.Printf("A total of %s will be installed after the operation finishes\n", BytesToHumanReadable(operation.GetFinalActionSize(operation.RootDir))) + } else if operation.GetFinalActionSize(operation.RootDir) < 0 { + fmt.Printf("A total of %s will be freed after the operation finishes\n", strings.TrimPrefix(BytesToHumanReadable(operation.GetFinalActionSize(operation.RootDir)), "-")) + } +} + +func (operation *BPMOperation) Execute(verbose, force bool) error { + // Fetch packages from repositories + if slices.ContainsFunc(operation.Actions, func(action OperationAction) bool { + return action.GetActionType() == "fetch" + }) { + fmt.Println("Fetching packages from available repositories...") + for i, action := range operation.Actions { + if action.GetActionType() != "fetch" { + continue + } + entry := action.(*FetchPackageAction).RepositoryEntry + fetchedPackage, err := entry.Repository.FetchPackage(entry.Info.Name) + if err != nil { + return errors.New(fmt.Sprintf("could not fetch package (%s): %s\n", entry.Info.Name, err)) + } + bpmpkg, err := ReadPackage(fetchedPackage) + if err != nil { + return errors.New(fmt.Sprintf("could not fetch package (%s): %s\n", entry.Info.Name, err)) + } + fmt.Printf("Package (%s) was successfully fetched!\n", bpmpkg.PkgInfo.Name) + operation.Actions[i] = &InstallPackageAction{ + File: fetchedPackage, + IsDependency: action.(*FetchPackageAction).IsDependency, + BpmPackage: bpmpkg, + } + } + } + + // Determine words to be used for the following message + words := make([]string, 0) + if slices.ContainsFunc(operation.Actions, func(action OperationAction) bool { + return action.GetActionType() == "install" + }) { + words = append(words, "Installing") + } + + if slices.ContainsFunc(operation.Actions, func(action OperationAction) bool { + return action.GetActionType() == "remove" + }) { + words = append(words, "Removing") + } + + if len(words) == 0 { + return nil + } + fmt.Printf("%s packages...\n", strings.Join(words, "/")) + + // Installing/Removing packages from system + for _, action := range operation.Actions { + if action.GetActionType() == "remove" { + pkgInfo := action.(*RemovePackageAction).BpmPackage.PkgInfo + err := RemovePackage(pkgInfo.Name, verbose, operation.RootDir) + if err != nil { + return errors.New(fmt.Sprintf("could not remove package (%s): %s\n", pkgInfo.Name, err)) + } + } else if action.GetActionType() == "install" { + value := action.(*InstallPackageAction) + bpmpkg := value.BpmPackage + var err error + if value.IsDependency { + err = InstallPackage(value.File, operation.RootDir, verbose, true, false, false, false) + } else { + err = InstallPackage(value.File, operation.RootDir, verbose, force, false, false, false) + } + if err != nil { + return errors.New(fmt.Sprintf("could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err)) + } + fmt.Printf("Package (%s) was successfully installed\n", bpmpkg.PkgInfo.Name) + if value.IsDependency { + err := SetInstallationReason(bpmpkg.PkgInfo.Name, Dependency, operation.RootDir) + if err != nil { + return errors.New(fmt.Sprintf("could not set installation reason for package (%s): %s\n", value.BpmPackage.PkgInfo.Name, err)) + } + } + } + } + fmt.Println("Operation complete!") + + return nil +} + type OperationAction interface { GetActionType() string } diff --git a/utils/package_utils.go b/utils/package_utils.go index 4ec43f6..f9f811d 100644 --- a/utils/package_utils.go +++ b/utils/package_utils.go @@ -238,31 +238,31 @@ func ReadPackageScripts(filename string) (map[string]string, error) { return nil, err } if header.Name == "pre_install.sh" { - bs, _ := io.ReadAll(tr) + bs, err := io.ReadAll(tr) if err != nil { return nil, err } ret[header.Name] = string(bs) } else if header.Name == "post_install.sh" { - bs, _ := io.ReadAll(tr) + bs, err := io.ReadAll(tr) if err != nil { return nil, err } ret[header.Name] = string(bs) } else if header.Name == "pre_update.sh" { - bs, _ := io.ReadAll(tr) + bs, err := io.ReadAll(tr) if err != nil { return nil, err } ret[header.Name] = string(bs) } else if header.Name == "post_update.sh" { - bs, _ := io.ReadAll(tr) + bs, err := io.ReadAll(tr) if err != nil { return nil, err } ret[header.Name] = string(bs) } else if header.Name == "post_remove.sh" { - bs, _ := io.ReadAll(tr) + bs, err := io.ReadAll(tr) if err != nil { return nil, err } @@ -744,9 +744,6 @@ func compilePackage(bpmpkg *BPMPackage, filename, rootDir string, verbose, binar if _, err := os.Stat(path.Join(temp, "source.sh")); os.IsNotExist(err) { return errors.New("source.sh file could not be found in the temporary build directory"), nil } - if err != nil { - return err, nil - } fmt.Println("Running source.sh file...") if !IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) { err = ExecutePackageScripts(filename, rootDir, Install, false) @@ -1301,7 +1298,7 @@ func (pkgInfo *PackageInfo) CheckConflicts(rootDir string) []string { return ret } -func (pkgInfo *PackageInfo) ResolveAll(resolved, unresolved *[]string, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) ([]string, []string) { +func (pkgInfo *PackageInfo) ResolveDependencies(resolved, unresolved *[]string, checkMake, checkOptional, ignoreInstalled, verbose bool, rootDir string) ([]string, []string) { *unresolved = append(*unresolved, pkgInfo.Name) for _, depend := range pkgInfo.GetAllDependencies(checkMake, checkOptional) { depend = strings.TrimSpace(depend) @@ -1325,7 +1322,7 @@ func (pkgInfo *PackageInfo) ResolveAll(resolved, unresolved *[]string, checkMake } continue } - entry.Info.ResolveAll(resolved, unresolved, checkMake, checkOptional, ignoreInstalled, verbose, rootDir) + entry.Info.ResolveDependencies(resolved, unresolved, checkMake, checkOptional, ignoreInstalled, verbose, rootDir) } } if !slices.Contains(*resolved, pkgInfo.Name) {