Refactor fetch and pacman packages into subpackages
Split fetch into alpm and aur subpackages for better organization. Rename state to log. Split pacman into read and sync subpackages. Remove validation in favor of read.DBFreshness.
This commit is contained in:
+45
-249
@@ -3,80 +3,34 @@ package pacman
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Riyyi/declpac/pkg/fetch"
|
||||
"github.com/Riyyi/declpac/pkg/log"
|
||||
"github.com/Riyyi/declpac/pkg/output"
|
||||
"github.com/Riyyi/declpac/pkg/state"
|
||||
"github.com/Riyyi/declpac/pkg/validation"
|
||||
"github.com/Riyyi/declpac/pkg/pacman/read"
|
||||
"github.com/Riyyi/declpac/pkg/pacman/sync"
|
||||
)
|
||||
|
||||
func MarkAllAsDeps() error {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] MarkAllAsDeps: starting...\n")
|
||||
|
||||
listCmd := exec.Command("pacman", "-Qq")
|
||||
output, err := listCmd.Output()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list packages: %w", err)
|
||||
}
|
||||
|
||||
packages := strings.Split(strings.TrimSpace(string(output)), "\n")
|
||||
if len(packages) == 0 || packages[0] == "" {
|
||||
fmt.Fprintf(os.Stderr, "[debug] MarkAllAsDeps: no packages to mark (%.2fs)\n", time.Since(start).Seconds())
|
||||
return nil
|
||||
}
|
||||
|
||||
args := append([]string{"-D", "--asdeps"}, packages...)
|
||||
cmd := exec.Command("pacman", args...)
|
||||
state.Write([]byte("pacman " + strings.Join(args, " ") + "\n"))
|
||||
cmd.Stdout = state.GetLogWriter()
|
||||
cmd.Stderr = state.GetLogWriter()
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
state.Write([]byte(fmt.Sprintf("error: %v\n", err)))
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] MarkAllAsDeps: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return err
|
||||
}
|
||||
|
||||
func MarkAsExplicit(packages []string) error {
|
||||
if len(packages) == 0 {
|
||||
return nil
|
||||
}
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] MarkAsExplicit: starting...\n")
|
||||
|
||||
args := append([]string{"-D", "--asexplicit"}, packages...)
|
||||
cmd := exec.Command("pacman", args...)
|
||||
state.Write([]byte("pacman " + strings.Join(args, " ") + "\n"))
|
||||
cmd.Stdout = state.GetLogWriter()
|
||||
cmd.Stderr = state.GetLogWriter()
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
state.Write([]byte(fmt.Sprintf("error: %v\n", err)))
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] MarkAsExplicit: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return err
|
||||
}
|
||||
|
||||
func Sync(packages []string) (*output.Result, error) {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] Sync: starting...\n")
|
||||
|
||||
before, err := getInstalledCount()
|
||||
list, err := read.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
before := len(list)
|
||||
|
||||
if err := validation.CheckDBFreshness(); err != nil {
|
||||
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()
|
||||
@@ -95,8 +49,7 @@ func Sync(packages []string) (*output.Result, error) {
|
||||
|
||||
if len(pacmanPkgs) > 0 {
|
||||
fmt.Fprintf(os.Stderr, "[debug] Sync: syncing %d pacman packages...\n", len(pacmanPkgs))
|
||||
err = SyncPackages(pacmanPkgs)
|
||||
if err != nil {
|
||||
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())
|
||||
@@ -104,30 +57,37 @@ func Sync(packages []string) (*output.Result, error) {
|
||||
|
||||
for _, pkg := range aurPkgs {
|
||||
fmt.Fprintf(os.Stderr, "[debug] Sync: installing AUR package %s...\n", pkg)
|
||||
if err := InstallAUR(f, pkg); err != nil {
|
||||
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")
|
||||
if err := MarkAllAsDeps(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "warning: could not mark all as deps: %v\n", err)
|
||||
}
|
||||
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 := MarkAsExplicit(packages); err != nil {
|
||||
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()
|
||||
removed, err := cleanupOrphans()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
after, _ := getInstalledCount()
|
||||
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())
|
||||
@@ -163,204 +123,40 @@ func categorizePackages(f *fetch.Fetcher, packages []string) (pacmanPkgs, aurPkg
|
||||
return pacmanPkgs, aurPkgs, nil
|
||||
}
|
||||
|
||||
func InstallAUR(f *fetch.Fetcher, pkgName string) error {
|
||||
func markAllAsDeps() error {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: starting...\n")
|
||||
fmt.Fprintf(os.Stderr, "[debug] markAllAsDeps: starting...\n")
|
||||
|
||||
aurInfo, ok := f.GetAURPackage(pkgName)
|
||||
if !ok {
|
||||
return fmt.Errorf("AUR package not found in cache: %s", pkgName)
|
||||
packages, err := read.List()
|
||||
if err != nil || len(packages) == 0 {
|
||||
return fmt.Errorf("failed to list packages: %w", err)
|
||||
}
|
||||
|
||||
sudoUser := os.Getenv("SUDO_USER")
|
||||
if sudoUser == "" {
|
||||
sudoUser = os.Getenv("USER")
|
||||
if sudoUser == "" {
|
||||
sudoUser = "root"
|
||||
}
|
||||
if err := sync.MarkAs(packages, "deps", log.GetLogWriter()); err != nil {
|
||||
log.Write([]byte(fmt.Sprintf("error: %v\n", err)))
|
||||
return err
|
||||
}
|
||||
|
||||
tmpDir := "/tmp/declpac-aur-" + pkgName
|
||||
mkdirCmd := exec.Command("su", "-", sudoUser, "-c", "rm -rf "+tmpDir+" && mkdir -p "+tmpDir)
|
||||
if err := mkdirCmd.Run(); err != nil {
|
||||
return fmt.Errorf("failed to create temp directory: %w", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
cloneURL := "https://aur.archlinux.org/" + aurInfo.PackageBase + ".git"
|
||||
cloneCmd := exec.Command("su", "-", sudoUser, "-c", "git clone "+cloneURL+" "+tmpDir)
|
||||
state.Write([]byte("git clone " + cloneURL + " " + tmpDir + "\n"))
|
||||
cloneCmd.Stdout = state.GetLogWriter()
|
||||
cloneCmd.Stderr = state.GetLogWriter()
|
||||
if err := cloneCmd.Run(); err != nil {
|
||||
errMsg := fmt.Sprintf("failed to clone AUR repo: %v\n", err)
|
||||
state.Write([]byte("error: " + errMsg))
|
||||
return fmt.Errorf("failed to clone AUR repo: %w", err)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: cloned (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
state.Write([]byte("makepkg -s --noconfirm\n"))
|
||||
makepkgCmd := exec.Command("su", "-", sudoUser, "-c", "cd "+tmpDir+" && makepkg -s --noconfirm")
|
||||
makepkgCmd.Stdout = state.GetLogWriter()
|
||||
makepkgCmd.Stderr = state.GetLogWriter()
|
||||
if err := makepkgCmd.Run(); err != nil {
|
||||
errMsg := fmt.Sprintf("makepkg failed to build AUR package: %v\n", err)
|
||||
state.Write([]byte("error: " + errMsg))
|
||||
return fmt.Errorf("makepkg failed to build AUR package: %w", err)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: built (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
pkgFile, err := findPKGFile(tmpDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find built package: %w", err)
|
||||
}
|
||||
|
||||
state.Write([]byte("pacman -U --noconfirm " + pkgFile + "\n"))
|
||||
installCmd := exec.Command("pacman", "-U", "--noconfirm", pkgFile)
|
||||
installCmd.Stdout = state.GetLogWriter()
|
||||
installCmd.Stderr = state.GetLogWriter()
|
||||
if err := installCmd.Run(); err != nil {
|
||||
errMsg := fmt.Sprintf("failed to install package: %v\n", err)
|
||||
state.Write([]byte("error: " + errMsg))
|
||||
return fmt.Errorf("failed to install package: %w", err)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: built (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
fmt.Fprintf(os.Stderr, "[debug] markAllAsDeps: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return nil
|
||||
}
|
||||
|
||||
func findPKGFile(dir string) (string, error) {
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, entry := range entries {
|
||||
name := entry.Name()
|
||||
if strings.HasSuffix(name, ".pkg.tar.zst") || strings.HasSuffix(name, ".pkg.tar.gz") {
|
||||
return filepath.Join(dir, name), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no package file found in %s", dir)
|
||||
}
|
||||
|
||||
func getInstalledCount() (int, error) {
|
||||
func cleanupOrphans() (int, error) {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] getInstalledCount: starting...\n")
|
||||
fmt.Fprintf(os.Stderr, "[debug] cleanupOrphans: starting...\n")
|
||||
|
||||
cmd := exec.Command("pacman", "-Qq")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return 0, nil
|
||||
}
|
||||
count := strings.Count(string(output), "\n") + 1
|
||||
if strings.TrimSpace(string(output)) == "" {
|
||||
count = 0
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] getInstalledCount: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func SyncPackages(packages []string) error {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] SyncPackages: starting...\n")
|
||||
|
||||
args := append([]string{"-S", "--needed"}, packages...)
|
||||
cmd := exec.Command("pacman", args...)
|
||||
state.Write([]byte("pacman " + strings.Join(args, " ") + "\n"))
|
||||
cmd.Stdout = state.GetLogWriter()
|
||||
cmd.Stderr = state.GetLogWriter()
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
state.Write([]byte(fmt.Sprintf("pacman sync failed: %v\n", err)))
|
||||
return fmt.Errorf("pacman sync failed: %v", err)
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] SyncPackages: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return nil
|
||||
}
|
||||
|
||||
func CleanupOrphans() (int, error) {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] CleanupOrphans: starting...\n")
|
||||
|
||||
f, err := fetch.New()
|
||||
orphans, err := read.ListOrphans()
|
||||
if err != nil {
|
||||
log.Write([]byte(fmt.Sprintf("error: %v\n", err)))
|
||||
return 0, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
orphans, err := f.ListOrphans()
|
||||
if err != nil || len(orphans) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "[debug] CleanupOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
removeCmd := exec.Command("pacman", "-Rns")
|
||||
state.Write([]byte("pacman -Rns\n"))
|
||||
removeCmd.Stdout = state.GetLogWriter()
|
||||
removeCmd.Stderr = state.GetLogWriter()
|
||||
err = removeCmd.Run()
|
||||
removed, err := sync.RemoveOrphans(orphans, log.GetLogWriter())
|
||||
if err != nil {
|
||||
state.Write([]byte(fmt.Sprintf("cleanup orphans failed: %v\n", err)))
|
||||
return 0, fmt.Errorf("cleanup orphans failed: %v", err)
|
||||
log.Write([]byte(fmt.Sprintf("error: %v\n", err)))
|
||||
return 0, err
|
||||
}
|
||||
|
||||
count := len(orphans)
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] CleanupOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func DryRun(packages []string) (*output.Result, error) {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: starting...\n")
|
||||
|
||||
f, err := fetch.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: initialized fetcher (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
resolved, err := f.Resolve(packages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: packages resolved (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
localPkgs, err := f.BuildLocalPkgMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var toInstall []string
|
||||
var aurPkgs []string
|
||||
for _, pkg := range packages {
|
||||
info := resolved[pkg]
|
||||
if info == nil || (!info.Exists && !info.InAUR) {
|
||||
return nil, fmt.Errorf("package not found: %s", pkg)
|
||||
}
|
||||
if info.InAUR {
|
||||
aurPkgs = append(aurPkgs, pkg)
|
||||
} else if _, installed := localPkgs[pkg]; !installed {
|
||||
toInstall = append(toInstall, pkg)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: packages categorized (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
orphans, err := f.ListOrphans()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: orphans listed (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return &output.Result{
|
||||
Installed: len(toInstall) + len(aurPkgs),
|
||||
Removed: len(orphans),
|
||||
ToInstall: append(toInstall, aurPkgs...),
|
||||
ToRemove: orphans,
|
||||
}, nil
|
||||
fmt.Fprintf(os.Stderr, "[debug] cleanupOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return removed, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package read
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Riyyi/declpac/pkg/fetch"
|
||||
"github.com/Riyyi/declpac/pkg/output"
|
||||
)
|
||||
|
||||
var LockFile = "/var/lib/pacman/db.lock"
|
||||
|
||||
func List() ([]string, error) {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] List: starting...\n")
|
||||
|
||||
cmd := exec.Command("pacman", "-Qq")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
list := strings.Split(strings.TrimSpace(string(output)), "\n")
|
||||
if list[0] == "" {
|
||||
list = nil
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] List: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func ListOrphans() ([]string, error) {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] ListOrphans: starting...\n")
|
||||
|
||||
cmd := exec.Command("pacman", "-Qdtq")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orphans := strings.Split(strings.TrimSpace(string(output)), "\n")
|
||||
if len(orphans) > 0 && orphans[0] == "" {
|
||||
orphans = orphans[1:]
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] ListOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return orphans, nil
|
||||
}
|
||||
|
||||
func DBFreshness() (bool, error) {
|
||||
info, err := os.Stat(LockFile)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
age := time.Since(info.ModTime())
|
||||
return age <= 24*time.Hour, nil
|
||||
}
|
||||
|
||||
func DryRun(packages []string) (*output.Result, error) {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: starting...\n")
|
||||
|
||||
f, err := fetch.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: initialized fetcher (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
resolved, err := f.Resolve(packages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: packages resolved (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
var toInstall []string
|
||||
var aurPkgs []string
|
||||
for _, pkg := range packages {
|
||||
info := resolved[pkg]
|
||||
if info == nil || (!info.Exists && !info.InAUR) {
|
||||
return nil, fmt.Errorf("package not found: %s", pkg)
|
||||
}
|
||||
if info.InAUR {
|
||||
aurPkgs = append(aurPkgs, pkg)
|
||||
} else if !info.Installed {
|
||||
toInstall = append(toInstall, pkg)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: packages categorized (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
orphans, err := ListOrphans()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: orphans listed (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return &output.Result{
|
||||
Installed: len(toInstall) + len(aurPkgs),
|
||||
Removed: len(orphans),
|
||||
ToInstall: append(toInstall, aurPkgs...),
|
||||
ToRemove: orphans,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package sync
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Result struct {
|
||||
Installed int
|
||||
Removed int
|
||||
}
|
||||
|
||||
func SyncPackages(packages []string, logWriter io.Writer) error {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] SyncPackages: starting...\n")
|
||||
|
||||
if logWriter == nil {
|
||||
logWriter = os.Stderr
|
||||
}
|
||||
|
||||
args := append([]string{"-S", "--needed"}, packages...)
|
||||
cmd := exec.Command("pacman", args...)
|
||||
cmd.Stdout = logWriter
|
||||
cmd.Stderr = logWriter
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("pacman sync failed: %w", err)
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] SyncPackages: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return nil
|
||||
}
|
||||
|
||||
func RefreshDB(logWriter io.Writer) error {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] RefreshDB: starting...\n")
|
||||
|
||||
if logWriter == nil {
|
||||
logWriter = os.Stderr
|
||||
}
|
||||
|
||||
cmd := exec.Command("pacman", "-Syy")
|
||||
cmd.Stdout = logWriter
|
||||
cmd.Stderr = logWriter
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("failed to refresh pacman database: %w", err)
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] RefreshDB: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
return nil
|
||||
}
|
||||
|
||||
func MarkAs(packages []string, flag string, logWriter io.Writer) error {
|
||||
if len(packages) == 0 {
|
||||
return nil
|
||||
}
|
||||
start := time.Now()
|
||||
flagName := map[string]string{"deps": "asdeps", "explicit": "asexplicit"}[flag]
|
||||
fmt.Fprintf(os.Stderr, "[debug] MarkAs(%s): starting...\n", flag)
|
||||
|
||||
if logWriter == nil {
|
||||
logWriter = os.Stderr
|
||||
}
|
||||
|
||||
args := append([]string{"-D", "--" + flagName}, packages...)
|
||||
cmd := exec.Command("pacman", args...)
|
||||
cmd.Stdout = logWriter
|
||||
cmd.Stderr = logWriter
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("mark as %s failed: %w", flag, err)
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] MarkAs(%s): done (%.2fs)\n", flag, time.Since(start).Seconds())
|
||||
return nil
|
||||
}
|
||||
|
||||
func RemoveOrphans(orphans []string, logWriter io.Writer) (int, error) {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] RemoveOrphans: starting...\n")
|
||||
|
||||
if logWriter == nil {
|
||||
logWriter = os.Stderr
|
||||
}
|
||||
|
||||
if len(orphans) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "[debug] RemoveOrphans: done (no orphans) (%.2fs)\n", time.Since(start).Seconds())
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
args := make([]string, 0, 2+len(orphans))
|
||||
args = append(args, "pacman", "-Rns")
|
||||
args = append(args, orphans...)
|
||||
removeCmd := exec.Command(args[0], args[1:]...)
|
||||
removeCmd.Stdout = logWriter
|
||||
removeCmd.Stderr = logWriter
|
||||
err := removeCmd.Run()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("remove orphans failed: %w", err)
|
||||
}
|
||||
|
||||
count := len(orphans)
|
||||
|
||||
fmt.Fprintf(os.Stderr, "[debug] RemoveOrphans: done (%d) (%.2fs)\n", count, time.Since(start).Seconds())
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func InstallAUR(pkgName string, packageBase string, logWriter io.Writer) error {
|
||||
start := time.Now()
|
||||
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: starting...\n")
|
||||
|
||||
if logWriter == nil {
|
||||
logWriter = os.Stderr
|
||||
}
|
||||
|
||||
sudoUser := os.Getenv("SUDO_USER")
|
||||
if sudoUser == "" {
|
||||
sudoUser = os.Getenv("USER")
|
||||
if sudoUser == "" {
|
||||
sudoUser = "root"
|
||||
}
|
||||
}
|
||||
|
||||
tmpDir := "/tmp/declpac-aur-" + pkgName
|
||||
mkdirCmd := exec.Command("su", "-", sudoUser, "-c", "rm -rf "+tmpDir+" && mkdir -p "+tmpDir)
|
||||
if err := mkdirCmd.Run(); err != nil {
|
||||
return fmt.Errorf("failed to create temp directory: %w", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
cloneURL := "https://aur.archlinux.org/" + packageBase + ".git"
|
||||
cloneCmd := exec.Command("su", "-", sudoUser, "-c", "git clone "+cloneURL+" "+tmpDir)
|
||||
cloneCmd.Stdout = logWriter
|
||||
cloneCmd.Stderr = logWriter
|
||||
if err := cloneCmd.Run(); err != nil {
|
||||
return fmt.Errorf("failed to clone AUR repo: %w", err)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: cloned (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
makepkgCmd := exec.Command("su", "-", sudoUser, "-c", "cd "+tmpDir+" && makepkg -s --noconfirm")
|
||||
makepkgCmd.Stdout = logWriter
|
||||
makepkgCmd.Stderr = logWriter
|
||||
if err := makepkgCmd.Run(); err != nil {
|
||||
return fmt.Errorf("makepkg failed to build AUR package: %w", err)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: built (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
pkgFile, err := findPKGFile(tmpDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find built package: %w", err)
|
||||
}
|
||||
|
||||
installCmd := exec.Command("pacman", "-U", "--noconfirm", pkgFile)
|
||||
installCmd.Stdout = logWriter
|
||||
installCmd.Stderr = logWriter
|
||||
if err := installCmd.Run(); err != nil {
|
||||
return fmt.Errorf("failed to install package: %w", err)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: done (%.2fs)\n", time.Since(start).Seconds())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findPKGFile(dir string) (string, error) {
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, entry := range entries {
|
||||
name := entry.Name()
|
||||
if strings.HasSuffix(name, ".pkg.tar.zst") || strings.HasSuffix(name, ".pkg.tar.gz") {
|
||||
return strings.Join([]string{dir, name}, "/"), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no package file found in %s", dir)
|
||||
}
|
||||
Reference in New Issue
Block a user