Reduce memory usage for the 'list' subcommand

This commit is contained in:
2025-12-26 12:34:08 +02:00
parent a660039be1
commit 548b2476bd
6 changed files with 88 additions and 87 deletions
+40 -15
View File
@@ -254,7 +254,14 @@ func showPackageInfo() {
} }
fmt.Println("File: " + abs) fmt.Println("File: " + abs)
} }
fmt.Println(bpmpkg.CreateReadableInfo(rootDir, showHumanReadableSize)) fmt.Println(bpmpkg.PkgInfo.CreateReadableInfo(rootDir))
if bpmpkg.PkgInfo.Type == "binary" {
if !showHumanReadableSize {
fmt.Printf("Installed size: %d\n", bpmpkg.GetInstalledSize())
} else {
fmt.Printf("Installed size: %s\n", bpmlib.BytesToHumanReadable(bpmpkg.GetInstalledSize()))
}
}
} }
} }
@@ -292,9 +299,21 @@ func showPackageList() {
return return
} }
installedPackages := make([]*bpmlib.BPMPackage, len(installedPackageNames)) installedPackages := make([]struct {
pkgInfo bpmlib.PackageInfo
installedSize int64
}, len(installedPackageNames))
for i, pkgName := range installedPackageNames { for i, pkgName := range installedPackageNames {
installedPackages[i] = bpmlib.GetPackage(pkgName, rootDir) pkgInfo := *bpmlib.GetPackageInfo(pkgName, rootDir)
installedSize := bpmlib.GetPackage(pkgName, rootDir).GetInstalledSize()
installedPackages[i] = struct {
pkgInfo bpmlib.PackageInfo
installedSize int64
}{
pkgInfo: pkgInfo,
installedSize: installedSize,
}
} }
databaseEntries := make([]*bpmlib.BPMDatabaseEntry, 0) databaseEntries := make([]*bpmlib.BPMDatabaseEntry, 0)
@@ -305,8 +324,11 @@ func showPackageList() {
switch sortPackages { switch sortPackages {
case "", "name": case "", "name":
case "size": case "size":
slices.SortFunc(installedPackages, func(a, b *bpmlib.BPMPackage) int { slices.SortFunc(installedPackages, func(a, b struct {
return int(b.GetInstalledSize() - a.GetInstalledSize()) pkgInfo bpmlib.PackageInfo
installedSize int64
}) int {
return int(b.installedSize - a.installedSize)
}) })
slices.SortFunc(databaseEntries, func(a, b *bpmlib.BPMDatabaseEntry) int { slices.SortFunc(databaseEntries, func(a, b *bpmlib.BPMDatabaseEntry) int {
return int(b.InstalledSize - a.InstalledSize) return int(b.InstalledSize - a.InstalledSize)
@@ -335,7 +357,7 @@ func showPackageList() {
} }
} else { } else {
for _, pkg := range installedPackages { for _, pkg := range installedPackages {
installationReason := bpmlib.GetInstallationReason(pkg.PkgInfo.Name, rootDir) installationReason := bpmlib.GetInstallationReason(pkg.pkgInfo.Name, rootDir)
if installationReason == bpmlib.InstallationReasonManual && !showManual { if installationReason == bpmlib.InstallationReasonManual && !showManual {
continue continue
} else if installationReason == bpmlib.InstallationReasonDependency && !showDepends { } else if installationReason == bpmlib.InstallationReasonDependency && !showDepends {
@@ -346,7 +368,7 @@ func showPackageList() {
continue continue
} }
fmt.Println(pkg.PkgInfo.Name) fmt.Println(pkg.pkgInfo.Name)
} }
} }
} else { } else {
@@ -366,13 +388,8 @@ func showPackageList() {
fmt.Println("No packages have been installed") fmt.Println("No packages have been installed")
return return
} }
for n, bpmpkg := range installedPackages { for n, pkg := range installedPackages {
if bpmpkg == nil { installationReason := bpmlib.GetInstallationReason(pkg.pkgInfo.Name, rootDir)
fmt.Printf("Package (%s) could not be found\n", installedPackageNames[n])
continue
}
installationReason := bpmlib.GetInstallationReason(bpmpkg.PkgInfo.Name, rootDir)
if installationReason == bpmlib.InstallationReasonManual && !showManual { if installationReason == bpmlib.InstallationReasonManual && !showManual {
continue continue
} else if installationReason == bpmlib.InstallationReasonDependency && !showDepends { } else if installationReason == bpmlib.InstallationReasonDependency && !showDepends {
@@ -386,7 +403,15 @@ func showPackageList() {
if n != 0 { if n != 0 {
fmt.Println() fmt.Println()
} }
fmt.Println(bpmpkg.CreateReadableInfo(rootDir, showHumanReadableSize))
fmt.Println(pkg.pkgInfo.CreateReadableInfo(rootDir))
if pkg.pkgInfo.Type == "binary" {
if !showHumanReadableSize {
fmt.Printf("Installed size: %d\n", pkg.installedSize)
} else {
fmt.Printf("Installed size: %s\n", bpmlib.BytesToHumanReadable(pkg.installedSize))
}
}
} }
} }
} }
+1 -1
View File
@@ -403,7 +403,7 @@ func (entry *BPMDatabaseEntry) CreateReadableInfo(rootDir string, humanReadableS
installedSize := entry.InstalledSize installedSize := entry.InstalledSize
var installedSizeStr string var installedSizeStr string
if humanReadableSize { if humanReadableSize {
installedSizeStr = bytesToHumanReadable(installedSize) installedSizeStr = BytesToHumanReadable(installedSize)
} else { } else {
installedSizeStr = strconv.FormatInt(installedSize, 10) installedSizeStr = strconv.FormatInt(installedSize, 10)
} }
+16 -28
View File
@@ -177,39 +177,33 @@ func resolvePackageDependenciesFromDatabase(resolved *[]pkgInstallationReason, u
func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string) (dependants []string) { func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string) (dependants []string) {
// Get installed package names // Get installed package names
pkgs, err := GetInstalledPackages(rootDir) pkgs, ok := localPackageInformation[rootDir]
if err != nil { if !ok {
return nil return nil
} }
// Loop through all installed packages // Loop through all installed packages
for _, installedPkgName := range pkgs { for _, installedPkg := range pkgs {
// Get installed BPM package
installedPkg := GetPackage(installedPkgName, rootDir)
if installedPkg == nil {
return nil
}
// Skip iteration if comparing the same packages // Skip iteration if comparing the same packages
if installedPkg.PkgInfo.Name == pkgInfo.Name { if installedPkg.Name == pkgInfo.Name {
continue continue
} }
// Add installed package to list if its dependencies include pkgName // Add installed package to list if its dependencies include pkgName
if slices.ContainsFunc(installedPkg.PkgInfo.Depends, func(n string) bool { if slices.ContainsFunc(installedPkg.Depends, func(n string) bool {
return n == pkgInfo.Name return n == pkgInfo.Name
}) { }) {
dependants = append(dependants, installedPkgName) dependants = append(dependants, installedPkg.Name)
continue continue
} }
// Loop through each virtual package // Loop through each virtual package
for _, vpkg := range pkgInfo.Provides { for _, vpkg := range pkgInfo.Provides {
// Add installed package to list if its dependencies contain a provided virtual package // Add installed package to list if its dependencies contain a provided virtual package
if slices.ContainsFunc(installedPkg.PkgInfo.Depends, func(n string) bool { if slices.ContainsFunc(installedPkg.Depends, func(n string) bool {
return n == vpkg return n == vpkg
}) { }) {
dependants = append(dependants, installedPkgName) dependants = append(dependants, installedPkg.Name)
break break
} }
} }
@@ -220,39 +214,33 @@ func (pkgInfo *PackageInfo) GetPackageDependants(rootDir string) (dependants []s
func (pkgInfo *PackageInfo) GetPackageOptionalDependants(rootDir string) (dependants []string) { func (pkgInfo *PackageInfo) GetPackageOptionalDependants(rootDir string) (dependants []string) {
// Get installed package names // Get installed package names
pkgs, err := GetInstalledPackages(rootDir) pkgs, ok := localPackageInformation[rootDir]
if err != nil { if !ok {
return nil return nil
} }
// Loop through all installed packages // Loop through all installed packages
for _, installedPkgName := range pkgs { for _, installedPkg := range pkgs {
// Get installed BPM package
installedPkg := GetPackage(installedPkgName, rootDir)
if installedPkg == nil {
return nil
}
// Skip iteration if comparing the same packages // Skip iteration if comparing the same packages
if installedPkg.PkgInfo.Name == pkgInfo.Name { if installedPkg.Name == pkgInfo.Name {
continue continue
} }
// 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.PkgInfo.OptionalDepends, func(n string) bool { if slices.ContainsFunc(installedPkg.OptionalDepends, func(n string) bool {
return n == pkgInfo.Name return n == pkgInfo.Name
}) { }) {
dependants = append(dependants, installedPkgName) dependants = append(dependants, installedPkg.Name)
continue continue
} }
// Loop through each virtual package // Loop through each virtual package
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.PkgInfo.OptionalDepends, func(n string) bool { if slices.ContainsFunc(installedPkg.OptionalDepends, func(n string) bool {
return n == vpkg return n == vpkg
}) { }) {
dependants = append(dependants, installedPkgName) dependants = append(dependants, installedPkg.Name)
break break
} }
} }
+3 -3
View File
@@ -429,12 +429,12 @@ func (operation *BPMOperation) ShowOperationSummary() {
fmt.Println("Warning: Operating in " + operation.RootDir) fmt.Println("Warning: Operating in " + operation.RootDir)
} }
if operation.GetTotalDownloadSize() > 0 { if operation.GetTotalDownloadSize() > 0 {
fmt.Printf("%s will be downloaded to complete this operation\n", bytesToHumanReadable(operation.GetTotalDownloadSize())) fmt.Printf("%s will be downloaded to complete this operation\n", BytesToHumanReadable(operation.GetTotalDownloadSize()))
} }
if operation.GetFinalActionSize(operation.RootDir) > 0 { 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))) 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 { } 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)), "-")) fmt.Printf("A total of %s will be freed after the operation finishes\n", strings.TrimPrefix(BytesToHumanReadable(operation.GetFinalActionSize(operation.RootDir)), "-"))
} }
} }
+27 -39
View File
@@ -536,60 +536,57 @@ func ReadPackageInfo(contents string) (*PackageInfo, error) {
return pkgInfo, nil return pkgInfo, nil
} }
func (bpmpkg *BPMPackage) CreateReadableInfo(rootDir string, humanReadableSize bool) string { func (pkgInfo *PackageInfo) CreateReadableInfo(rootDir string) string {
ret := make([]string, 0) ret := make([]string, 0)
appendArray := func(label string, array []string) { appendArray := func(label string, array []string) {
if len(array) == 0 { if len(array) == 0 {
return return
} }
// Sort array
slices.Sort(array)
ret = append(ret, fmt.Sprintf("%s: %s", label, strings.Join(array, ", "))) ret = append(ret, fmt.Sprintf("%s: %s", label, strings.Join(array, ", ")))
} }
ret = append(ret, "Name: "+bpmpkg.PkgInfo.Name) ret = append(ret, "Name: "+pkgInfo.Name)
ret = append(ret, "Description: "+bpmpkg.PkgInfo.Description) ret = append(ret, "Description: "+pkgInfo.Description)
ret = append(ret, "Version: "+bpmpkg.PkgInfo.GetFullVersion()) ret = append(ret, "Version: "+pkgInfo.GetFullVersion())
if bpmpkg.PkgInfo.Url != "" { if pkgInfo.Url != "" {
ret = append(ret, "URL: "+bpmpkg.PkgInfo.Url) ret = append(ret, "URL: "+pkgInfo.Url)
} }
if bpmpkg.PkgInfo.License != "" { if pkgInfo.License != "" {
ret = append(ret, "License: "+bpmpkg.PkgInfo.License) ret = append(ret, "License: "+pkgInfo.License)
} }
ret = append(ret, "Architecture: "+bpmpkg.PkgInfo.Arch) ret = append(ret, "Architecture: "+pkgInfo.Arch)
if bpmpkg.PkgInfo.Type == "source" && bpmpkg.PkgInfo.OutputArch != "" && bpmpkg.PkgInfo.OutputArch != GetArch() { if pkgInfo.Type == "source" && pkgInfo.OutputArch != "" && pkgInfo.OutputArch != GetArch() {
ret = append(ret, "Output architecture: "+bpmpkg.PkgInfo.Arch) ret = append(ret, "Output architecture: "+pkgInfo.Arch)
} }
ret = append(ret, "Type: "+bpmpkg.PkgInfo.Type) ret = append(ret, "Type: "+pkgInfo.Type)
appendArray("Dependencies", bpmpkg.PkgInfo.Depends) appendArray("Dependencies", pkgInfo.Depends)
if bpmpkg.PkgInfo.Type == "source" { if pkgInfo.Type == "source" {
appendArray("Make Dependencies", bpmpkg.PkgInfo.MakeDepends) appendArray("Make Dependencies", pkgInfo.MakeDepends)
} }
appendArray("Optional dependencies", bpmpkg.PkgInfo.OptionalDepends) appendArray("Optional dependencies", pkgInfo.OptionalDepends)
dependants := bpmpkg.PkgInfo.GetPackageDependants(rootDir) dependants := pkgInfo.GetPackageDependants(rootDir)
if len(dependants) > 0 { if len(dependants) > 0 {
appendArray("Dependant packages", dependants) appendArray("Dependant packages", dependants)
} }
optionalDependants := bpmpkg.PkgInfo.GetPackageOptionalDependants(rootDir) optionalDependants := pkgInfo.GetPackageOptionalDependants(rootDir)
if len(optionalDependants) > 0 { if len(optionalDependants) > 0 {
appendArray("Optionally dependant packages", optionalDependants) appendArray("Optionally dependant packages", optionalDependants)
} }
appendArray("Conflicting packages", bpmpkg.PkgInfo.Conflicts) appendArray("Conflicting packages", pkgInfo.Conflicts)
appendArray("Provided packages", bpmpkg.PkgInfo.Provides) appendArray("Provided packages", pkgInfo.Provides)
appendArray("Replaces packages", bpmpkg.PkgInfo.Replaces) appendArray("Replaces packages", pkgInfo.Replaces)
if bpmpkg.PkgInfo.Type == "source" && len(bpmpkg.PkgInfo.SplitPackages) != 0 { if pkgInfo.Type == "source" && len(pkgInfo.SplitPackages) != 0 {
splitPkgs := make([]string, len(bpmpkg.PkgInfo.SplitPackages)) splitPkgs := make([]string, len(pkgInfo.SplitPackages))
for i, splitPkgInfo := range bpmpkg.PkgInfo.SplitPackages { for i, splitPkgInfo := range pkgInfo.SplitPackages {
splitPkgs[i] = splitPkgInfo.Name splitPkgs[i] = splitPkgInfo.Name
} }
appendArray("Split Packages", splitPkgs) appendArray("Split Packages", splitPkgs)
} }
if rootDir != "" && IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir) { if rootDir != "" && IsPackageInstalled(pkgInfo.Name, rootDir) {
installationReason := GetInstallationReason(bpmpkg.PkgInfo.Name, rootDir) installationReason := GetInstallationReason(pkgInfo.Name, rootDir)
var installationReasonString string var installationReasonString string
switch installationReason { switch installationReason {
case InstallationReasonManual: case InstallationReasonManual:
@@ -603,16 +600,7 @@ func (bpmpkg *BPMPackage) CreateReadableInfo(rootDir string, humanReadableSize b
} }
ret = append(ret, "Installation Reason: "+installationReasonString) ret = append(ret, "Installation Reason: "+installationReasonString)
} }
if bpmpkg.PkgInfo.Type == "binary" {
installedSize := bpmpkg.GetInstalledSize()
var installedSizeStr string
if humanReadableSize {
installedSizeStr = bytesToHumanReadable(installedSize)
} else {
installedSizeStr = strconv.FormatInt(installedSize, 10)
}
ret = append(ret, "Installed size: "+installedSizeStr)
}
return strings.Join(ret, "\n") return strings.Join(ret, "\n")
} }
+1 -1
View File
@@ -119,7 +119,7 @@ func stringSliceRemove(s []string, r string) []string {
return s return s
} }
func bytesToHumanReadable(b int64) string { func BytesToHumanReadable(b int64) string {
bf := float64(b) bf := float64(b)
for _, unit := range []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"} { for _, unit := range []string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"} {
if math.Abs(bf) < 1024.0 { if math.Abs(bf) < 1024.0 {