Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a1670519c | |||
| 238001fb61 |
@@ -0,0 +1 @@
|
|||||||
|
apac
|
||||||
+78
-13
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user