Files
bootstrap_dev_env/check.go
T
2026-05-27 15:26:34 -05:00

225 lines
5.8 KiB
Go

package main
import (
"fmt"
"strings"
"sync"
)
type systemCheckResult struct {
toInstallRegular []string
toInstallSpecial []string
alreadyInstalled []string
skipped []string
remapped []remap // for display only
}
type remap struct {
From string
To []string
}
type flatpakCheckResult struct {
toInstall []string
alreadyInstalled []string
}
type customCheckResult struct {
toInstall []*CustomPackage
alreadyInstalled []customStatus
}
type customStatus struct {
pkg *CustomPackage
path string
}
// parallelPartition runs check(item) over items concurrently (using the
// configured cpuWorkers pool) and returns the items where check returned
// true first, then those where it returned false — both in input order.
// We preserve input order so the displayed package lists stay stable.
func parallelPartition[T any](items []T, check func(T) bool) (truthy, falsy []T) {
if len(items) == 0 {
return nil, nil
}
results := make([]bool, len(items))
parallelDo(items, cpuWorkers(), func(i int, item T) {
results[i] = check(item)
})
for i, item := range items {
if results[i] {
truthy = append(truthy, item)
} else {
falsy = append(falsy, item)
}
}
return
}
func checkSystemPackages(names []string) systemCheckResult {
overrides := packageOverrides[pkgMgr]
resolved, skipped := resolveSystemPkgs(names)
var remapped []remap
for _, n := range names {
if ov, ok := overrides[n]; ok && !ov.Skip {
remapped = append(remapped, remap{From: n, To: ov.Replacement})
}
}
specials := specialPkgs()
var special, regular []string
for _, p := range resolved {
if specials[p] {
special = append(special, p)
} else {
regular = append(regular, p)
}
}
alreadyR, toR := parallelPartition(regular, isSystemPkgInstalled)
alreadyS, toS := parallelPartition(special, isSpecialPkgInstalled)
return systemCheckResult{
toInstallRegular: toR,
toInstallSpecial: toS,
alreadyInstalled: append(alreadyR, alreadyS...),
skipped: skipped,
remapped: remapped,
}
}
func checkFlatpakPackages(ids []string) flatpakCheckResult {
already, to := parallelPartition(ids, isFlatpakInstalled)
return flatpakCheckResult{toInstall: to, alreadyInstalled: already}
}
func checkCustomPackages(pkgs []*CustomPackage) customCheckResult {
type result struct {
installed bool
path string
}
results := make([]result, len(pkgs))
parallelDo(pkgs, cpuWorkers(), func(i int, p *CustomPackage) {
installed, path := isCustomPkgInstalled(p)
results[i] = result{installed: installed, path: path}
})
var to []*CustomPackage
var already []customStatus
for i, p := range pkgs {
if results[i].installed {
already = append(already, customStatus{pkg: p, path: results[i].path})
} else {
to = append(to, p)
}
}
return customCheckResult{toInstall: to, alreadyInstalled: already}
}
// checkAllInParallel runs the three check passes concurrently. The caller
// must still gate which checks to run via *only; we accept already-prepared
// inputs and skip when the corresponding slice/conditional indicates no work.
func checkAllInParallel(
runSys bool, sysPkgs []string,
runFlat bool, flatPkgs []string,
runCust bool, customPkgs []*CustomPackage,
) (systemCheckResult, flatpakCheckResult, customCheckResult) {
var sys systemCheckResult
var flat flatpakCheckResult
var cust customCheckResult
var wg sync.WaitGroup
if runSys {
wg.Add(1)
go func() {
defer wg.Done()
sys = checkSystemPackages(sysPkgs)
}()
}
if runFlat {
wg.Add(1)
go func() {
defer wg.Done()
flat = checkFlatpakPackages(flatPkgs)
}()
}
if runCust {
wg.Add(1)
go func() {
defer wg.Done()
cust = checkCustomPackages(customPkgs)
}()
}
wg.Wait()
return sys, flat, cust
}
func fmtList(items []string, limit int) string {
if len(items) <= limit {
return strings.Join(items, " ")
}
return strings.Join(items[:limit], " ") + fmt.Sprintf(" … +%d more", len(items)-limit)
}
func printCheckSummary(sys systemCheckResult, flat flatpakCheckResult, cust customCheckResult, only string) int {
total := 0
if only == "" || only == "system" {
toR := sys.toInstallRegular
toS := sys.toInstallSpecial
ok := sys.alreadyInstalled
fmt.Println("\nSystem packages:")
if len(ok) > 0 {
fmt.Printf(" [OK] %3d already installed\n", len(ok))
}
n := len(toR) + len(toS)
if n > 0 {
combined := append([]string{}, toR...)
combined = append(combined, toS...)
fmt.Printf(" [INSTALL] %3d to install: %s\n", n, fmtList(combined, 6))
}
if len(sys.skipped) > 0 {
fmt.Printf(" [SKIP] %3d overridden (→ skip): %s\n", len(sys.skipped), fmtList(sys.skipped, 6))
}
if len(sys.remapped) > 0 {
var parts []string
for _, r := range sys.remapped {
parts = append(parts, fmt.Sprintf("%s→%s", r.From, strings.Join(r.To, ",")))
}
fmt.Printf(" [REMAP] remapped: %s\n", strings.Join(parts, " "))
}
total += n
}
if (only == "" || only == "flatpak") && (len(flat.toInstall) > 0 || len(flat.alreadyInstalled) > 0) {
fmt.Println("\nFlatpak packages:")
if len(flat.alreadyInstalled) > 0 {
fmt.Printf(" [OK] %3d already installed\n", len(flat.alreadyInstalled))
}
if len(flat.toInstall) > 0 {
fmt.Printf(" [INSTALL] %3d to install: %s\n", len(flat.toInstall), fmtList(flat.toInstall, 6))
}
total += len(flat.toInstall)
}
if only == "" || only == "custom" {
fmt.Println("\nCustom packages:")
for _, s := range cust.alreadyInstalled {
suffix := ""
if s.path != "" {
suffix = fmt.Sprintf(" (%s)", s.path)
}
fmt.Printf(" [OK] %s%s\n", s.pkg.displayName(), suffix)
}
for _, p := range cust.toInstall {
_, path := isCustomPkgInstalled(p)
suffix := ""
if path != "" {
suffix = fmt.Sprintf(" → %s", path)
}
fmt.Printf(" [INSTALL] %s%s\n", p.displayName(), suffix)
}
total += len(cust.toInstall)
}
return total
}