Sync a declarative package list with the pacman package manager
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

162 lines
4.5 KiB

package pacman
import (
"fmt"
"os"
"time"
"github.com/Riyyi/declpac/pkg/fetch"
"github.com/Riyyi/declpac/pkg/log"
"github.com/Riyyi/declpac/pkg/output"
"github.com/Riyyi/declpac/pkg/pacman/read"
"github.com/Riyyi/declpac/pkg/pacman/sync"
)
func Sync(packages []string) (*output.Result, error) {
start := time.Now()
fmt.Fprintf(os.Stderr, "[debug] Sync: starting...\n")
list, err := read.List()
if err != nil {
return nil, err
}
before := len(list)
fresh, err := read.DBFreshness()
if err != nil {
return nil, err
}
if !fresh {
if err := sync.RefreshDB(log.GetLogWriter()); err != nil {
return nil, err
}
}
fmt.Fprintf(os.Stderr, "[debug] Sync: database fresh (%.2fs)\n", time.Since(start).Seconds())
f, err := fetch.New()
if err != nil {
return nil, err
}
defer f.Close()
fmt.Fprintf(os.Stderr, "[debug] Sync: initialized fetcher (%.2fs)\n", time.Since(start).Seconds())
fmt.Fprintf(os.Stderr, "[debug] Sync: categorizing packages...\n")
pacmanPkgs, aurPkgs, err := categorizePackages(f, packages)
if err != nil {
return nil, err
}
fmt.Fprintf(os.Stderr, "[debug] Sync: packages categorized (%.2fs)\n", time.Since(start).Seconds())
if len(pacmanPkgs) > 0 {
fmt.Fprintf(os.Stderr, "[debug] Sync: syncing %d pacman packages...\n", len(pacmanPkgs))
if err := sync.SyncPackages(pacmanPkgs, log.GetLogWriter()); err != nil {
return nil, err
}
fmt.Fprintf(os.Stderr, "[debug] Sync: pacman packages synced (%.2fs)\n", time.Since(start).Seconds())
}
for _, pkg := range aurPkgs {
fmt.Fprintf(os.Stderr, "[debug] Sync: installing AUR package %s...\n", pkg)
aurInfo, ok := f.GetAURPackage(pkg)
if !ok {
return nil, fmt.Errorf("AUR package not found in cache: %s", pkg)
}
if err := sync.InstallAUR(pkg, aurInfo.PackageBase, log.GetLogWriter()); err != nil {
return nil, err
}
fmt.Fprintf(os.Stderr, "[debug] Sync: AUR package %s installed (%.2fs)\n", pkg, time.Since(start).Seconds())
}
fmt.Fprintf(os.Stderr, "[debug] Sync: marking all as deps...\n")
markAllAsDeps()
fmt.Fprintf(os.Stderr, "[debug] Sync: all marked as deps (%.2fs)\n", time.Since(start).Seconds())
fmt.Fprintf(os.Stderr, "[debug] Sync: marking state packages as explicit...\n")
if err := sync.MarkAs(packages, "explicit", log.GetLogWriter()); err != nil {
fmt.Fprintf(os.Stderr, "warning: could not mark state packages as explicit: %v\n", err)
}
fmt.Fprintf(os.Stderr, "[debug] Sync: state packages marked as explicit (%.2fs)\n", time.Since(start).Seconds())
removed, err := cleanupOrphans()
if err != nil {
return nil, err
}
list, _ = read.List()
if err != nil {
return nil, err
}
after := len(list)
installedCount := max(after-before, 0)
fmt.Fprintf(os.Stderr, "[debug] Sync: done (%.2fs)\n", time.Since(start).Seconds())
return &output.Result{
Installed: installedCount,
Removed: removed,
}, nil
}
func categorizePackages(f *fetch.Fetcher, packages []string) (pacmanPkgs, aurPkgs []string, err error) {
start := time.Now()
fmt.Fprintf(os.Stderr, "[debug] categorizePackages: starting...\n")
resolved, err := f.Resolve(packages)
if err != nil {
return nil, nil, err
}
for _, pkg := range packages {
info := resolved[pkg]
if info == nil || (!info.Exists && !info.InAUR) {
fmt.Fprintf(os.Stderr, "error: package not found: %s\n", pkg)
continue
}
if info.InAUR {
aurPkgs = append(aurPkgs, pkg)
} else {
pacmanPkgs = append(pacmanPkgs, pkg)
}
}
fmt.Fprintf(os.Stderr, "[debug] categorizePackages: done (%.2fs)\n", time.Since(start).Seconds())
return pacmanPkgs, aurPkgs, nil
}
func markAllAsDeps() error {
start := time.Now()
fmt.Fprintf(os.Stderr, "[debug] markAllAsDeps: starting...\n")
packages, err := read.List()
if err != nil || len(packages) == 0 {
return fmt.Errorf("failed to list packages: %w", err)
}
if err := sync.MarkAs(packages, "deps", log.GetLogWriter()); err != nil {
log.Write([]byte(fmt.Sprintf("error: %v\n", err)))
return err
}
fmt.Fprintf(os.Stderr, "[debug] markAllAsDeps: done (%.2fs)\n", time.Since(start).Seconds())
return nil
}
func cleanupOrphans() (int, error) {
start := time.Now()
fmt.Fprintf(os.Stderr, "[debug] cleanupOrphans: starting...\n")
orphans, err := read.ListOrphans()
if err != nil {
log.Write([]byte(fmt.Sprintf("error: %v\n", err)))
return 0, err
}
removed, err := sync.RemoveOrphans(orphans, log.GetLogWriter())
if err != nil {
log.Write([]byte(fmt.Sprintf("error: %v\n", err)))
return 0, err
}
fmt.Fprintf(os.Stderr, "[debug] cleanupOrphans: done (%.2fs)\n", time.Since(start).Seconds())
return removed, nil
}