From e30a32c56875ca30f323fb8403890d064a7a50ea Mon Sep 17 00:00:00 2001 From: EnumDev Date: Wed, 30 Oct 2024 16:35:52 +0200 Subject: [PATCH] Added an --unused flag for the remove subcommand and remove will no longer display errors if a package does not exist --- main.go | 15 +++++++++++++-- utils/operations.go | 43 ++++++++++++++++++++++++++++++++++++++++++ utils/package_utils.go | 20 ++++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index fde2acd..e4c4827 100644 --- a/main.go +++ b/main.go @@ -36,6 +36,7 @@ var reinstall = false var reinstallAll = false var noOptional = false var nosync = true +var removeUnused = false func main() { utils.ReadConfig() @@ -392,11 +393,19 @@ func resolveCommand() { for _, pkg := range packages { bpmpkg := utils.GetPackage(pkg, rootDir) if bpmpkg == nil { - log.Fatalf("Error: package (%s) could not be found\n", pkg) + continue } operation.Actions = append(operation.Actions, &utils.RemovePackageAction{BpmPackage: bpmpkg}) } + // Skip needed packages if the --unused flag is on + if removeUnused { + err := operation.RemoveNeededPackages() + if err != nil { + log.Fatalf("Error: could not skip needed packages: %s\n", err) + } + } + // Show operation summary operation.ShowOperationSummary() @@ -576,10 +585,11 @@ func printHelp() { fmt.Println(" -R= lets you define the root path which will be used") fmt.Println(" -v Show additional information about what BPM is doing") fmt.Println(" -y skips the confirmation prompt") - fmt.Println("-> bpm remove [-R, -v, -y] | removes the following packages") + fmt.Println("-> bpm remove [-R, -v, -y, --unused] | removes the following packages") fmt.Println(" -v Show additional information about what BPM is doing") fmt.Println(" -R= lets you define the root path which will be used") fmt.Println(" -y skips the confirmation prompt") + fmt.Println(" -unused removes only packages that aren't required as dependencies by other packages") fmt.Println("-> bpm cleanup [-R, -v, -y] | remove all unused dependency packages") fmt.Println(" -v Show additional information about what BPM is doing") fmt.Println(" -R= lets you define the root path which will be used") @@ -635,6 +645,7 @@ func resolveFlags() { removeFlagSet.StringVar(&rootDir, "R", "/", "Set the destination root") removeFlagSet.BoolVar(&verbose, "v", false, "Show additional information about what BPM is doing") removeFlagSet.BoolVar(&yesAll, "y", false, "Skip confirmation prompts") + removeFlagSet.BoolVar(&removeUnused, "unused", false, "Removes only packages that aren't required as dependencies by other packages") removeFlagSet.Usage = printHelp // Cleanup flags cleanupFlagSet := flag.NewFlagSet("Cleanup flags", flag.ExitOnError) diff --git a/utils/operations.go b/utils/operations.go index 2035fad..31e0c67 100644 --- a/utils/operations.go +++ b/utils/operations.go @@ -42,6 +42,22 @@ func (operation *BPMOperation) InsertActionAt(index int, action OperationAction) operation.Actions[index] = action } +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).RepositoryEntry.Info.Name == pkg + } else if a.GetActionType() == "remove" { + return a.(*RemovePackageAction).BpmPackage.PkgInfo.Name == pkg + } + return false + }) +} + func (operation *BPMOperation) GetTotalDownloadSize() uint64 { var ret uint64 = 0 for _, action := range operation.Actions { @@ -122,6 +138,33 @@ func (operation *BPMOperation) ResolveDependencies(reinstallDependencies, instal return nil } +func (operation *BPMOperation) RemoveNeededPackages() error { + removeActions := make(map[string]*RemovePackageAction) + for _, action := range slices.Clone(operation.Actions) { + if action.GetActionType() == "remove" { + removeActions[action.(*RemovePackageAction).BpmPackage.PkgInfo.Name] = action.(*RemovePackageAction) + } + } + + for pkg, action := range removeActions { + dependants, err := action.BpmPackage.PkgInfo.GetDependants(operation.RootDir) + if err != nil { + return errors.New("could not get dependant packages for package (" + pkg + ")") + } + dependants = slices.DeleteFunc(dependants, func(d string) bool { + if _, ok := removeActions[d]; ok { + return true + } + return false + }) + if len(dependants) != 0 { + operation.RemoveAction(pkg, action.GetActionType()) + } + } + + return nil +} + func (operation *BPMOperation) CheckForConflicts() (map[string][]string, error) { conflicts := make(map[string][]string) installedPackages, err := GetInstalledPackages(operation.RootDir) diff --git a/utils/package_utils.go b/utils/package_utils.go index d4e23c9..3d2f00c 100644 --- a/utils/package_utils.go +++ b/utils/package_utils.go @@ -1293,6 +1293,26 @@ func (pkgInfo *PackageInfo) CheckDependencies(checkMake, checkOptional bool, roo return ret } +func (pkgInfo *PackageInfo) GetDependants(rootDir string) ([]string, error) { + ret := make([]string, 0) + + pkgs, err := GetInstalledPackages(rootDir) + if err != nil { + return nil, errors.New("could not get installed packages") + } + for _, pkg := range pkgs { + bpmpkg := GetPackage(pkg, rootDir) + if bpmpkg == nil { + return nil, errors.New("package not found: " + pkg) + } + if bpmpkg.PkgInfo.Name != pkgInfo.Name && slices.Contains(bpmpkg.PkgInfo.GetAllDependencies(false, true), pkgInfo.Name) { + ret = append(ret, pkg) + } + } + + return ret, nil +} + func (pkgInfo *PackageInfo) CheckConflicts(rootDir string) []string { var ret []string for _, conflict := range pkgInfo.Conflicts {