diff --git a/actions.go b/actions.go index dd4b0fc1..d22727bf 100644 --- a/actions.go +++ b/actions.go @@ -13,9 +13,6 @@ import ( pac "github.com/jguer/yay/pacman" ) -// BuildDir is the root for package building -const BuildDir string = "/tmp/yaytmp/" - // SearchMode is search without numbers. const SearchMode int = -1 @@ -25,6 +22,9 @@ var SortMode = DownTop // NoConfirm ignores prompts. var NoConfirm = false +// BaseDir is the default building directory for yay +var BaseDir = "/tmp/yaytmp/" + // Determines NumberMenu and Search Order const ( DownTop = iota @@ -37,6 +37,7 @@ func Config() { pac.SortMode = SortMode aur.NoConfirm = NoConfirm pac.NoConfirm = NoConfirm + aur.BaseDir = BaseDir } // NumberMenu presents a CLI for selecting packages to install. @@ -73,7 +74,7 @@ func NumberMenu(pkgName string, flags []string) (err error) { return } - var aurInstall []aur.Result + var aurInstall []string var repoInstall []string result := strings.Fields(numberString) for _, numS := range result { @@ -87,9 +88,9 @@ func NumberMenu(pkgName string, flags []string) (err error) { continue } else if num > nR-1 { if aur.SortMode == aur.DownTop { - aurInstall = append(aurInstall, a[nA+nR-num-1]) + aurInstall = append(aurInstall, a[nA+nR-num-1].Name) } else { - aurInstall = append(aurInstall, a[num-nR]) + aurInstall = append(aurInstall, a[num-nR].Name) } } else { if aur.SortMode == aur.DownTop { @@ -104,14 +105,24 @@ func NumberMenu(pkgName string, flags []string) (err error) { pac.Install(repoInstall, flags) } - for _, aurpkg := range aurInstall { - err = aurpkg.Install(BuildDir, flags) + if len(aurInstall) != 0 { + q, n, err := aur.MultiInfo(aurInstall) if err != nil { - // Do not abandon program, we might still be able to install the rest - fmt.Println(err) + return err + } else if n != len(aurInstall) { + aur.MissingPackage(aurInstall, q) + } + + for _, aurpkg := range q { + err = aurpkg.Install(flags) + if err != nil { + // Do not abandon program, we might still be able to install the rest + fmt.Println(err) + } } } - return + + return nil } // Install handles package installs @@ -129,7 +140,7 @@ func Install(pkgs []string, flags []string) error { } for _, aurpkg := range q { - err = aurpkg.Install(BuildDir, flags) + err = aurpkg.Install(flags) if err != nil { fmt.Println("Error installing", aurpkg.Name, ":", err) } @@ -141,7 +152,7 @@ func Install(pkgs []string, flags []string) error { // Upgrade handles updating the cache and installing updates. func Upgrade(flags []string) error { errp := pac.UpdatePackages(flags) - erra := aur.Upgrade(BuildDir, flags) + erra := aur.Upgrade(flags) if errp != nil { return errp @@ -179,7 +190,7 @@ func LocalStatistics(version string) error { return err } - _, foreign, _ := pac.ForeignPackages() + foreignS, foreign, _ := pac.ForeignPackages() fmt.Printf("\n Yay version r%s\n", version) fmt.Println("\x1B[1;34m===========================================\x1B[0m") @@ -195,6 +206,23 @@ func LocalStatistics(version string) error { } fmt.Println("\x1B[1;34m===========================================\x1B[0m") + keys := make([]string, len(foreignS)) + i := 0 + for k := range foreignS { + keys[i] = k + i++ + } + q, _, err := aur.MultiInfo(keys) + if err != nil { + return err + } + + for _, res := range q { + if res.Maintainer == "" { + fmt.Printf("\x1b[1;31;40mWarning: \x1B[1;33;40m%s\x1b[0;;40m is orphaned.\x1b[0m\n", res.Name) + } + } + return nil } @@ -253,5 +281,4 @@ func PassToPacman(op string, pkgs []string, flags []string) error { cmd.Stderr = os.Stderr err := cmd.Run() return err - } diff --git a/aur/aur.go b/aur/aur.go index b12244a1..6c2310ef 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -1,7 +1,6 @@ package aur import ( - "bytes" "fmt" "os" "os/exec" @@ -29,6 +28,9 @@ var NoConfirm = false // SortMode determines top down package or down top package display var SortMode = DownTop +// BaseDir is the default building directory for yay +var BaseDir = "/tmp/yaytmp/" + // Describes Sorting method for numberdisplay const ( DownTop = iota @@ -91,6 +93,10 @@ func (q Query) PrintSearch(start int) { } } toprint += fmt.Sprintf("\x1b[1m%s/\x1b[33m%s \x1b[36m%s \x1b[0m(%d) ", "aur", res.Name, res.Version, res.NumVotes) + if res.Maintainer == "" { + toprint += fmt.Sprintf("\x1b[31;40m(Orphaned)\x1b[0m ") + } + if res.Installed == true { toprint += fmt.Sprintf("\x1b[32;40mInstalled\x1b[0m") } @@ -167,7 +173,7 @@ func MultiInfo(pkgS []string) (Query, int, error) { } // Install sends system commands to make and install a package from pkgName -func Install(pkg string, baseDir string, flags []string) (err error) { +func Install(pkg string, flags []string) (err error) { q, n, err := Info(pkg) if err != nil { return @@ -177,12 +183,12 @@ func Install(pkg string, baseDir string, flags []string) (err error) { return fmt.Errorf("Package %s does not exist", pkg) } - q[0].Install(baseDir, flags) + q[0].Install(flags) return err } // Upgrade tries to update every foreign package installed in the system -func Upgrade(baseDir string, flags []string) error { +func Upgrade(flags []string) error { fmt.Println("\x1b[1;36;1m::\x1b[0m\x1b[1m Starting AUR upgrade...\x1b[0m") foreign, n, err := pacman.ForeignPackages() @@ -221,93 +227,87 @@ func Upgrade(baseDir string, flags []string) error { } // Install updated packages - if !NoConfirm { - fmt.Println("\x1b[1m\x1b[32m==> Proceed with upgrade\x1b[0m\x1b[1m (Y/n)\x1b[0m") - var response string - fmt.Scanln(&response) - if strings.ContainsAny(response, "n & N") { - return nil - } + if !continueTask("Proceed with upgrade?", "n & N") { + return nil } for _, pkg := range outdated { - pkg.Install(baseDir, flags) + pkg.Install(flags) } return nil } -// Install handles install from Result -func (a *Result) Install(baseDir string, flags []string) (err error) { - fmt.Printf("\x1b[1m\x1b[32m==> Installing\x1b[33m %s\x1b[0m\n", a.Name) - +func (a *Result) setupWorkspace() (err error) { // No need to use filepath.separators because it won't run on inferior platforms - err = os.MkdirAll(baseDir+"builds", 0755) + err = os.MkdirAll(BaseDir+"builds", 0755) if err != nil { fmt.Println(err) return } - tarLocation := baseDir + a.Name + ".tar.gz" - defer os.Remove(baseDir + a.Name + ".tar.gz") + tarLocation := BaseDir + a.PackageBase + ".tar.gz" + defer os.Remove(BaseDir + a.PackageBase + ".tar.gz") err = downloadFile(tarLocation, BaseURL+a.URLPath) if err != nil { return } - err = exec.Command(TarBin, "-xf", tarLocation, "-C", baseDir).Run() + err = exec.Command(TarBin, "-xf", tarLocation, "-C", BaseDir).Run() if err != nil { return } - defer os.RemoveAll(baseDir + a.Name) - var response string - var dir bytes.Buffer - dir.WriteString(baseDir) - dir.WriteString(a.Name) - dir.WriteString("/") + return +} - if !NoConfirm { - fmt.Println("\x1b[1m\x1b[32m==> Edit PKGBUILD?\x1b[0m\x1b[1m (y/N)\x1b[0m") - fmt.Scanln(&response) - if strings.ContainsAny(response, "y & Y") { - editcmd := exec.Command(Editor, dir.String()+"PKGBUILD") - editcmd.Stdout = os.Stdout - editcmd.Stderr = os.Stderr - editcmd.Stdin = os.Stdin - editcmd.Run() +// Install handles install from Info Result +func (a *Result) Install(flags []string) (err error) { + fmt.Printf("\x1b[1;32m==> Installing\x1b[33m %s\x1b[0m\n", a.Name) + if a.Maintainer == "" { + fmt.Println("\x1b[1;31;40m==> Warning:\x1b[0;;40m This package is orphaned.\x1b[0m") + } + dir := BaseDir + a.PackageBase + "/" + + if _, err = os.Stat(dir); os.IsNotExist(err) { + if err = a.setupWorkspace(); err != nil { + return } } + + // defer os.RemoveAll(BaseDir + a.PackageBase) + + if !continueTask("Edit PKGBUILD?", "y & Y") { + editcmd := exec.Command(Editor, dir+"PKGBUILD") + editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr + editcmd.Run() + } + aurDeps, repoDeps, err := a.Dependencies() if err != nil { return } printDependencies(aurDeps, repoDeps) - if !NoConfirm && (len(aurDeps) != 0 || len(repoDeps) != 0) { - fmt.Println("\x1b[1m\x1b[32m==> Continue?\x1b[0m\x1b[1m (Y/n)\x1b[0m") - fmt.Scanln(&response) - if strings.ContainsAny(response, "n & N") { + + if len(aurDeps) != 0 || len(repoDeps) != 0 { + if !continueTask("Continue?", "n & N") { return fmt.Errorf("user did not like the dependencies") } } aurQ, n, err := MultiInfo(aurDeps) if n != len(aurDeps) { - missingDeps(aurDeps, aurQ) - if !NoConfirm { - fmt.Println("\x1b[1m\x1b[32m==> Continue?\x1b[0m\x1b[1m (Y/n)\x1b[0m") - fmt.Scanln(&response) - if strings.ContainsAny(response, "n & N") { - return fmt.Errorf("unable to install dependencies") - } + MissingPackage(aurDeps, aurQ) + if !continueTask("Continue?", "n & N") { + return fmt.Errorf("unable to install dependencies") } } // Handle AUR dependencies first for _, dep := range aurQ { - errA := dep.Install(baseDir, []string{"--asdeps", "--noconfirm"}) + errA := dep.Install([]string{"--asdeps", "--noconfirm"}) if errA != nil { return errA } @@ -322,7 +322,7 @@ func (a *Result) Install(baseDir string, flags []string) (err error) { } } - err = os.Chdir(dir.String()) + err = os.Chdir(dir) if err != nil { return } @@ -332,17 +332,37 @@ func (a *Result) Install(baseDir string, flags []string) (err error) { args = append(args, "-sri") args = append(args, flags...) makepkgcmd = exec.Command(MakepkgBin, args...) - makepkgcmd.Stdout = os.Stdout - makepkgcmd.Stderr = os.Stderr - makepkgcmd.Stdin = os.Stdin + makepkgcmd.Stdin, makepkgcmd.Stdout, makepkgcmd.Stderr = os.Stdin, os.Stdout, os.Stderr err = makepkgcmd.Run() - return } +func continueTask(s string, def string) (cont bool) { + if NoConfirm { + return true + } + var postFix string + + if def == "n & N" { + postFix = "(Y/n)" + } else { + postFix = "(y/N)" + } + + var response string + fmt.Printf("\x1b[1;32m==> %s\x1b[1;37m %s\x1b[0m\n", s, postFix) + + fmt.Scanln(&response) + if strings.ContainsAny(response, def) { + return false + } + + return true +} + func printDependencies(aurDeps []string, repoDeps []string) { if len(repoDeps) != 0 { - fmt.Print("\x1b[1m\x1b[32m==> Repository dependencies: \x1b[0m") + fmt.Print("\x1b[1;32m==> Repository dependencies: \x1b[0m") for _, repoD := range repoDeps { fmt.Print("\x1b[33m", repoD, " \x1b[0m") } @@ -350,7 +370,7 @@ func printDependencies(aurDeps []string, repoDeps []string) { } if len(repoDeps) != 0 { - fmt.Print("\x1b[1m\x1b[32m==> AUR dependencies: \x1b[0m") + fmt.Print("\x1b[1;32m==> AUR dependencies: \x1b[0m") for _, aurD := range aurDeps { fmt.Print("\x1b[33m", aurD, " \x1b[0m") } @@ -358,7 +378,8 @@ func printDependencies(aurDeps []string, repoDeps []string) { } } -func missingDeps(aurDeps []string, aurQ Query) { +// MissingPackage warns if the Query was unable to find a package +func MissingPackage(aurDeps []string, aurQ Query) { for _, depName := range aurDeps { found := false for _, dep := range aurQ { diff --git a/aur/aur_test.go b/aur/aur_test.go index 2fb8c7aa..cae7b454 100644 --- a/aur/aur_test.go +++ b/aur/aur_test.go @@ -60,7 +60,7 @@ func TestInfo(t *testing.T) { } func TestUpgrade(t *testing.T) { - err := Upgrade("/tmp/yaytmp", []string{}) + err := Upgrade([]string{}) if err != nil { t.Fatalf("Expected err to be nil but it was %s", err) } @@ -68,6 +68,6 @@ func TestUpgrade(t *testing.T) { func BenchmarkUpgrade(b *testing.B) { for n := 0; n < b.N; n++ { - Upgrade("/tmp/yaytmp", []string{}) + Upgrade([]string{}) } }