added basic cache functionality. Note that this works only with the install command, and stores only the PKGBUILD files.

This commit is contained in:
2026-05-02 21:25:53 +02:00
parent 238001fb61
commit 8a1670519c
+78 -13
View File
@@ -2,12 +2,17 @@ package cmd
import ( import (
"fmt" "fmt"
"io"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
const cacheBase = "/var/cache/apac/pkgs"
var installCmd = &cobra.Command{ var installCmd = &cobra.Command{
Use: "install", Use: "install",
Short: "installs a package", Short: "installs a package",
@@ -15,36 +20,96 @@ var installCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 { if len(args) == 0 {
fmt.Fprintln(os.Stderr, "error: package name required") fmt.Fprintln(os.Stderr, "error: package name required")
return os.Exit(1)
} }
pkg := args[0] pkg := args[0]
url := "https://aur.archlinux.org/" + pkg url := "https://aur.archlinux.org/" + pkg
// git clone // ensure cache directory exists (use sudo mkdir -p so permissions can be elevated)
fmt.Println("cloning:", url) mkdirCmd := exec.Command("sudo", "mkdir", "-p", cacheBase)
out, err := exec.Command("git", "clone", url).CombinedOutput() mkdirCmd.Stdin = os.Stdin
if err != nil { mkdirCmd.Stdout = os.Stdout
fmt.Fprintf(os.Stderr, "git clone failed: %v\n%s\n", err, string(out)) mkdirCmd.Stderr = os.Stderr
return if err := mkdirCmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "failed to create cache dir %s: %v\n", cacheBase, err)
os.Exit(1)
} }
// makepkg -si inside package dir cacheDir := filepath.Join(cacheBase, pkg)
tmpDir := filepath.Join(os.TempDir(), "apac-build-"+pkg+"-"+time.Now().Format("20060102-150405"))
// clone into cache if missing; DO NOT pull/update existing cache
if _, err := os.Stat(cacheDir); os.IsNotExist(err) {
fmt.Println("cloning into cache:", url, "->", cacheDir)
cloneCmd := exec.Command("sudo", "git", "clone", url, cacheDir)
cloneCmd.Stdin = os.Stdin
cloneCmd.Stdout = os.Stdout
cloneCmd.Stderr = os.Stderr
if err := cloneCmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "git clone failed: %v\n", err)
os.Exit(1)
}
} else if err != nil {
fmt.Fprintf(os.Stderr, "stat cache dir failed: %v\n", err)
os.Exit(1)
} else {
fmt.Println("using cached repo:", cacheDir)
}
// copy cached repo into a temporary build directory
if err := copyDir(cacheDir, tmpDir); err != nil {
fmt.Fprintf(os.Stderr, "failed to copy to build dir: %v\n", err)
os.Exit(1)
}
defer os.RemoveAll(tmpDir)
// run makepkg in tmpDir (makepkg will handle permissions)
fmt.Println("building/installing:", pkg) fmt.Println("building/installing:", pkg)
buildCmd := exec.Command("makepkg", "-si", "--noconfirm") buildCmd := exec.Command("makepkg", "-si", "--noconfirm")
buildCmd.Dir = pkg buildCmd.Dir = tmpDir
buildCmd.Stdin = os.Stdin buildCmd.Stdin = os.Stdin
buildCmd.Stdout = os.Stdout buildCmd.Stdout = os.Stdout
buildCmd.Stderr = os.Stderr buildCmd.Stderr = os.Stderr
buildCmd.Run() if err := buildCmd.Run(); err != nil {
// cleanup fmt.Fprintf(os.Stderr, "makepkg failed: %v\n", err)
if err := os.RemoveAll(pkg); err != nil { os.Exit(1)
fmt.Fprintf(os.Stderr, "warning: failed to remove %s: %v\n", pkg, err)
} }
fmt.Println("install successful") fmt.Println("install successful")
}, },
} }
func copyDir(src, dst string) error {
if err := os.MkdirAll(dst, 0755); err != nil {
return err
}
return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
rel, err := filepath.Rel(src, path)
if err != nil {
return err
}
target := filepath.Join(dst, rel)
if info.IsDir() {
return os.MkdirAll(target, info.Mode())
}
in, err := os.Open(path)
if err != nil {
return err
}
defer in.Close()
out, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, info.Mode())
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, in)
return err
})
}
func init() { func init() {
rootCmd.AddCommand(installCmd) rootCmd.AddCommand(installCmd)
} }