Explorar o código

Code refactor

Jguer %!s(int64=8) %!d(string=hai) anos
pai
achega
d6104a526e
Modificáronse 5 ficheiros con 439 adicións e 425 borrados
  1. 1 1
      actions.go
  2. 1 424
      aur/aur.go
  3. 139 0
      aur/query.go
  4. 247 0
      aur/result.go
  5. 51 0
      aur/utils.go

+ 1 - 1
actions.go

@@ -110,7 +110,7 @@ func NumberMenu(pkgName string, flags []string) (err error) {
 		if err != nil {
 			return err
 		} else if n != len(aurInstall) {
-			aur.MissingPackage(aurInstall, q)
+			q.MissingPackage(aurInstall)
 		}
 
 		for _, aurpkg := range q {

+ 1 - 424
aur/aur.go

@@ -2,180 +2,10 @@ package aur
 
 import (
 	"fmt"
-	"os"
-	"os/exec"
-	"sort"
-	"strings"
 
 	"github.com/jguer/yay/pacman"
 )
 
-// TarBin describes the default installation point of tar command.
-const TarBin string = "/usr/bin/tar"
-
-// BaseURL givers the AUR default address.
-const BaseURL string = "https://aur.archlinux.org"
-
-// MakepkgBin describes the default installation point of makepkg command.
-const MakepkgBin string = "/usr/bin/makepkg"
-
-// SearchMode is search without numbers.
-const SearchMode int = -1
-
-// NoConfirm ignores prompts.
-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
-	TopDown
-)
-
-// Result describes an AUR package.
-type Result struct {
-	ID             int     `json:"ID"`
-	Name           string  `json:"Name"`
-	PackageBaseID  int     `json:"PackageBaseID"`
-	PackageBase    string  `json:"PackageBase"`
-	Version        string  `json:"Version"`
-	Description    string  `json:"Description"`
-	URL            string  `json:"URL"`
-	NumVotes       int     `json:"NumVotes"`
-	Popularity     float32 `json:"Popularity"`
-	OutOfDate      int     `json:"OutOfDate"`
-	Maintainer     string  `json:"Maintainer"`
-	FirstSubmitted int     `json:"FirstSubmitted"`
-	LastModified   int64   `json:"LastModified"`
-	URLPath        string  `json:"URLPath"`
-	Installed      bool
-	Depends        []string `json:"Depends"`
-	MakeDepends    []string `json:"MakeDepends"`
-	OptDepends     []string `json:"OptDepends"`
-	Conflicts      []string `json:"Conflicts"`
-	Provides       []string `json:"Provides"`
-	License        []string `json:"License"`
-	Keywords       []string `json:"Keywords"`
-}
-
-// Query is a collection of Results
-type Query []Result
-
-func (q Query) Len() int {
-	return len(q)
-}
-
-func (q Query) Less(i, j int) bool {
-	if SortMode == DownTop {
-		return q[i].NumVotes < q[j].NumVotes
-	}
-	return q[i].NumVotes > q[j].NumVotes
-}
-
-func (q Query) Swap(i, j int) {
-	q[i], q[j] = q[j], q[i]
-}
-
-// PrintSearch handles printing search results in a given format
-func (q Query) PrintSearch(start int) {
-	for i, res := range q {
-		var toprint string
-		if start != SearchMode {
-			if SortMode == DownTop {
-				toprint += fmt.Sprintf("%d ", len(q)+start-i-1)
-			} else {
-				toprint += fmt.Sprintf("%d ", start+i)
-			}
-		}
-		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.OutOfDate != 0 {
-			toprint += fmt.Sprintf("\x1b[31;40m(Out-of-date)\x1b[0m ")
-		}
-
-		if res.Installed == true {
-			toprint += fmt.Sprintf("\x1b[32;40mInstalled\x1b[0m")
-		}
-		toprint += "\n" + res.Description
-		fmt.Println(toprint)
-	}
-}
-
-// Search returns an AUR search
-func Search(pkg string, sortS bool) (Query, int, error) {
-	type returned struct {
-		Results     Query `json:"results"`
-		ResultCount int   `json:"resultcount"`
-	}
-	r := returned{}
-	err := getJSON("https://aur.archlinux.org/rpc/?v=5&type=search&arg="+pkg, &r)
-
-	if sortS {
-		sort.Sort(r.Results)
-	}
-	setter := pacman.PFactory(pFSetTrue)
-
-	for i, res := range r.Results {
-		if i == len(r.Results)-1 {
-			setter(res.Name, &r.Results[i], true)
-			continue
-		}
-		setter(res.Name, &r.Results[i], false)
-	}
-	return r.Results, r.ResultCount, err
-}
-
-// This is very dirty but it works so good.
-func pFSetTrue(res interface{}) {
-	f, ok := res.(*Result)
-	if !ok {
-		fmt.Println("Unable to convert back to Result")
-		return
-	}
-	f.Installed = true
-
-	return
-}
-
-// Info returns an AUR search with package details
-func Info(pkg string) (Query, int, error) {
-	type returned struct {
-		Results     Query `json:"results"`
-		ResultCount int   `json:"resultcount"`
-	}
-	r := returned{}
-
-	err := getJSON("https://aur.archlinux.org/rpc/?v=5&type=info&arg[]="+pkg, &r)
-
-	return r.Results, r.ResultCount, err
-}
-
-// MultiInfo takes a slice of strings and returns a slice with the info of each package
-func MultiInfo(pkgS []string) (Query, int, error) {
-	type returned struct {
-		Results     Query `json:"results"`
-		ResultCount int   `json:"resultcount"`
-	}
-	r := returned{}
-
-	var pkg string
-	for _, pkgn := range pkgS {
-		pkg += "&arg[]=" + pkgn
-	}
-
-	err := getJSON("https://aur.archlinux.org/rpc/?v=5&type=info"+pkg, &r)
-
-	return r.Results, r.ResultCount, err
-}
-
 // Install sends system commands to make and install a package from pkgName
 func Install(pkg string, flags []string) (err error) {
 	q, n, err := Info(pkg)
@@ -231,7 +61,7 @@ func Upgrade(flags []string) error {
 	}
 
 	// Install updated packages
-	if !continueTask("Proceed with upgrade?", "n & N") {
+	if !continueTask("Proceed with upgrade?", "nN") {
 		return nil
 	}
 
@@ -241,256 +71,3 @@ func Upgrade(flags []string) error {
 
 	return nil
 }
-
-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)
-	if err != nil {
-		fmt.Println(err)
-		return
-	}
-
-	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()
-	if err != nil {
-		return
-	}
-
-	return
-}
-
-// 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()
-	}
-
-	runDeps, makeDeps, err := a.Dependencies()
-	if err != nil {
-		return
-	}
-
-	repoDeps := append(runDeps[0], makeDeps[0]...)
-	aurDeps := append(runDeps[1], makeDeps[1]...)
-
-	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) {
-		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([]string{"--asdeps", "--noconfirm"})
-		if errA != nil {
-			return errA
-		}
-	}
-
-	// Repo dependencies
-	if len(repoDeps) != 0 {
-		errR := pacman.Install(repoDeps, []string{"--asdeps", "--noconfirm"})
-		if errR != nil {
-			pacman.CleanRemove(aurDeps)
-			return errR
-		}
-	}
-
-	err = os.Chdir(dir)
-	if err != nil {
-		return
-	}
-
-	var makepkgcmd *exec.Cmd
-	var args []string
-	args = append(args, "-sri")
-	args = append(args, flags...)
-	makepkgcmd = exec.Command(MakepkgBin, args...)
-	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
-}
-
-// 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 {
-			if dep.Name == depName {
-				found = true
-				break
-			}
-		}
-
-		if !found {
-			fmt.Println("\x1b[31mUnable to find", depName, "in AUR\x1b[0m")
-		}
-	}
-	return
-}
-
-// PrintInfo prints package info like pacman -Si
-func (a *Result) PrintInfo() {
-	fmt.Println("\x1b[1;37mRepository      :\x1b[0m", "aur")
-	fmt.Println("\x1b[1;37mName            :\x1b[0m", a.Name)
-	fmt.Println("\x1b[1;37mVersion         :\x1b[0m", a.Version)
-	fmt.Println("\x1b[1;37mDescription     :\x1b[0m", a.Description)
-	if a.URL != "" {
-		fmt.Println("\x1b[1;37mURL             :\x1b[0m", a.URL)
-	} else {
-		fmt.Println("\x1b[1;37mURL             :\x1b[0m", "None")
-	}
-	fmt.Println("\x1b[1;37mLicenses        :\x1b[0m", a.License)
-
-	if len(a.Provides) != 0 {
-		fmt.Println("\x1b[1;37mProvides        :\x1b[0m", a.Provides)
-	} else {
-		fmt.Println("\x1b[1;37mProvides        :\x1b[0m", "None")
-	}
-
-	if len(a.Depends) != 0 {
-		fmt.Println("\x1b[1;37mDepends On      :\x1b[0m", a.Depends)
-	} else {
-		fmt.Println("\x1b[1;37mDepends On      :\x1b[0m", "None")
-	}
-
-	if len(a.MakeDepends) != 0 {
-		fmt.Println("\x1b[1;37mMake depends On :\x1b[0m", a.MakeDepends)
-	} else {
-		fmt.Println("\x1b[1;37mMake depends On :\x1b[0m", "None")
-	}
-
-	if len(a.OptDepends) != 0 {
-		fmt.Println("\x1b[1;37mOptional Deps   :\x1b[0m", a.OptDepends)
-	} else {
-		fmt.Println("\x1b[1;37mOptional Deps   :\x1b[0m", "None")
-	}
-
-	if len(a.Conflicts) != 0 {
-		fmt.Println("\x1b[1;37mConflicts With  :\x1b[0m", a.Conflicts)
-	} else {
-		fmt.Println("\x1b[1;37mConflicts With  :\x1b[0m", "None")
-	}
-
-	if a.Maintainer != "" {
-		fmt.Println("\x1b[1;37mMaintainer      :\x1b[0m", a.Maintainer)
-	} else {
-		fmt.Println("\x1b[1;37mMaintainer      :\x1b[0m", "None")
-	}
-	fmt.Println("\x1b[1;37mVotes           :\x1b[0m", a.NumVotes)
-	fmt.Println("\x1b[1;37mPopularity      :\x1b[0m", a.Popularity)
-
-	if a.OutOfDate != 0 {
-		fmt.Println("\x1b[1;37mOut-of-date     :\x1b[0m", "Yes")
-	}
-
-}
-
-// Dependencies returns package dependencies not installed belonging to AUR
-// 0 is Repo, 1 is Foreign.
-func (a *Result) Dependencies() (runDeps [2][]string, makeDeps [2][]string, err error) {
-	var q Query
-	if len(a.Depends) == 0 && len(a.MakeDepends) == 0 {
-		var n int
-		q, n, err = Info(a.Name)
-		if n == 0 || err != nil {
-			err = fmt.Errorf("Unable to search dependencies, %s", err)
-			return
-		}
-	} else {
-		q = append(q, *a)
-	}
-
-	depSearch := pacman.BuildDependencies(a.Depends)
-	if len(a.Depends) != 0 {
-		runDeps[0], runDeps[1] = depSearch(q[0].Depends, true, false)
-		if len(runDeps[0]) != 0 || len(runDeps[1]) != 0 {
-			fmt.Println("\x1b[1;32m=>\x1b[1;33m Run Dependencies: \x1b[0m")
-			printDeps(runDeps[0], runDeps[1])
-		}
-	}
-
-	if len(a.MakeDepends) != 0 {
-		makeDeps[0], makeDeps[1] = depSearch(q[0].MakeDepends, false, false)
-		if len(makeDeps[0]) != 0 || len(makeDeps[1]) != 0 {
-			fmt.Println("\x1b[1;32m=>\x1b[1;33m Make Dependencies: \x1b[0m")
-			printDeps(makeDeps[0], makeDeps[1])
-		}
-	}
-	depSearch(a.MakeDepends, false, true)
-
-	err = nil
-	return
-}
-
-func printDeps(repoDeps []string, aurDeps []string) {
-	if len(repoDeps) != 0 {
-		fmt.Print("\x1b[1;32m==> Repository dependencies: \x1b[0m")
-		for _, repoD := range repoDeps {
-			fmt.Print("\x1b[33m", repoD, " \x1b[0m")
-		}
-		fmt.Print("\n")
-
-	}
-	if len(aurDeps) != 0 {
-		fmt.Print("\x1b[1;32m==> AUR dependencies: \x1b[0m")
-		for _, aurD := range aurDeps {
-			fmt.Print("\x1b[33m", aurD, " \x1b[0m")
-		}
-		fmt.Print("\n")
-	}
-}

+ 139 - 0
aur/query.go

@@ -0,0 +1,139 @@
+package aur
+
+import (
+	"fmt"
+	"sort"
+
+	"github.com/jguer/yay/pacman"
+)
+
+// Query is a collection of Results
+type Query []Result
+
+func (q Query) Len() int {
+	return len(q)
+}
+
+func (q Query) Less(i, j int) bool {
+	if SortMode == DownTop {
+		return q[i].NumVotes < q[j].NumVotes
+	}
+	return q[i].NumVotes > q[j].NumVotes
+}
+
+func (q Query) Swap(i, j int) {
+	q[i], q[j] = q[j], q[i]
+}
+
+// PrintSearch handles printing search results in a given format
+func (q Query) PrintSearch(start int) {
+	for i, res := range q {
+		var toprint string
+		if start != SearchMode {
+			if SortMode == DownTop {
+				toprint += fmt.Sprintf("%d ", len(q)+start-i-1)
+			} else {
+				toprint += fmt.Sprintf("%d ", start+i)
+			}
+		}
+		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.OutOfDate != 0 {
+			toprint += fmt.Sprintf("\x1b[31;40m(Out-of-date)\x1b[0m ")
+		}
+
+		if res.Installed == true {
+			toprint += fmt.Sprintf("\x1b[32;40mInstalled\x1b[0m")
+		}
+		toprint += "\n" + res.Description
+		fmt.Println(toprint)
+	}
+}
+
+// Info returns an AUR search with package details
+func Info(pkg string) (Query, int, error) {
+	type returned struct {
+		Results     Query `json:"results"`
+		ResultCount int   `json:"resultcount"`
+	}
+	r := returned{}
+
+	err := getJSON("https://aur.archlinux.org/rpc/?v=5&type=info&arg[]="+pkg, &r)
+
+	return r.Results, r.ResultCount, err
+}
+
+// MultiInfo takes a slice of strings and returns a slice with the info of each package
+func MultiInfo(pkgS []string) (Query, int, error) {
+	type returned struct {
+		Results     Query `json:"results"`
+		ResultCount int   `json:"resultcount"`
+	}
+	r := returned{}
+
+	var pkg string
+	for _, pkgn := range pkgS {
+		pkg += "&arg[]=" + pkgn
+	}
+
+	err := getJSON("https://aur.archlinux.org/rpc/?v=5&type=info"+pkg, &r)
+
+	return r.Results, r.ResultCount, err
+}
+
+// Search returns an AUR search
+func Search(pkg string, sortS bool) (Query, int, error) {
+	type returned struct {
+		Results     Query `json:"results"`
+		ResultCount int   `json:"resultcount"`
+	}
+	r := returned{}
+	err := getJSON("https://aur.archlinux.org/rpc/?v=5&type=search&arg="+pkg, &r)
+
+	if sortS {
+		sort.Sort(r.Results)
+	}
+	setter := pacman.PFactory(pFSetTrue)
+
+	for i, res := range r.Results {
+		if i == len(r.Results)-1 {
+			setter(res.Name, &r.Results[i], true)
+			continue
+		}
+		setter(res.Name, &r.Results[i], false)
+	}
+	return r.Results, r.ResultCount, err
+}
+
+// This is very dirty but it works so good.
+func pFSetTrue(res interface{}) {
+	f, ok := res.(*Result)
+	if !ok {
+		fmt.Println("Unable to convert back to Result")
+		return
+	}
+	f.Installed = true
+
+	return
+}
+
+// MissingPackage warns if the Query was unable to find a package
+func (q Query) MissingPackage(pkgS []string) {
+	for _, depName := range pkgS {
+		found := false
+		for _, dep := range q {
+			if dep.Name == depName {
+				found = true
+				break
+			}
+		}
+
+		if !found {
+			fmt.Println("\x1b[31mUnable to find", depName, "in AUR\x1b[0m")
+		}
+	}
+	return
+}

+ 247 - 0
aur/result.go

@@ -0,0 +1,247 @@
+package aur
+
+import (
+	"fmt"
+	"os"
+	"os/exec"
+
+	"github.com/jguer/yay/pacman"
+)
+
+// Result describes an AUR package.
+type Result struct {
+	ID             int     `json:"ID"`
+	Name           string  `json:"Name"`
+	PackageBaseID  int     `json:"PackageBaseID"`
+	PackageBase    string  `json:"PackageBase"`
+	Version        string  `json:"Version"`
+	Description    string  `json:"Description"`
+	URL            string  `json:"URL"`
+	NumVotes       int     `json:"NumVotes"`
+	Popularity     float32 `json:"Popularity"`
+	OutOfDate      int     `json:"OutOfDate"`
+	Maintainer     string  `json:"Maintainer"`
+	FirstSubmitted int     `json:"FirstSubmitted"`
+	LastModified   int64   `json:"LastModified"`
+	URLPath        string  `json:"URLPath"`
+	Installed      bool
+	Depends        []string `json:"Depends"`
+	MakeDepends    []string `json:"MakeDepends"`
+	OptDepends     []string `json:"OptDepends"`
+	Conflicts      []string `json:"Conflicts"`
+	Provides       []string `json:"Provides"`
+	License        []string `json:"License"`
+	Keywords       []string `json:"Keywords"`
+}
+
+// Dependencies returns package dependencies not installed belonging to AUR
+// 0 is Repo, 1 is Foreign.
+func (a *Result) Dependencies() (runDeps [2][]string, makeDeps [2][]string, err error) {
+	var q Query
+	if len(a.Depends) == 0 && len(a.MakeDepends) == 0 {
+		var n int
+		q, n, err = Info(a.Name)
+		if n == 0 || err != nil {
+			err = fmt.Errorf("Unable to search dependencies, %s", err)
+			return
+		}
+	} else {
+		q = append(q, *a)
+	}
+
+	depSearch := pacman.BuildDependencies(a.Depends)
+	if len(a.Depends) != 0 {
+		runDeps[0], runDeps[1] = depSearch(q[0].Depends, true, false)
+		if len(runDeps[0]) != 0 || len(runDeps[1]) != 0 {
+			fmt.Println("\x1b[1;32m=>\x1b[1;33m Run Dependencies: \x1b[0m")
+			printDeps(runDeps[0], runDeps[1])
+		}
+	}
+
+	if len(a.MakeDepends) != 0 {
+		makeDeps[0], makeDeps[1] = depSearch(q[0].MakeDepends, false, false)
+		if len(makeDeps[0]) != 0 || len(makeDeps[1]) != 0 {
+			fmt.Println("\x1b[1;32m=>\x1b[1;33m Make Dependencies: \x1b[0m")
+			printDeps(makeDeps[0], makeDeps[1])
+		}
+	}
+	depSearch(a.MakeDepends, false, true)
+
+	err = nil
+	return
+}
+
+func printDeps(repoDeps []string, aurDeps []string) {
+	if len(repoDeps) != 0 {
+		fmt.Print("\x1b[1;32m==> Repository dependencies: \x1b[0m")
+		for _, repoD := range repoDeps {
+			fmt.Print("\x1b[33m", repoD, " \x1b[0m")
+		}
+		fmt.Print("\n")
+
+	}
+	if len(aurDeps) != 0 {
+		fmt.Print("\x1b[1;32m==> AUR dependencies: \x1b[0m")
+		for _, aurD := range aurDeps {
+			fmt.Print("\x1b[33m", aurD, " \x1b[0m")
+		}
+		fmt.Print("\n")
+	}
+}
+
+// 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?", "yY") {
+		editcmd := exec.Command(Editor, dir+"PKGBUILD")
+		editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+		editcmd.Run()
+	}
+
+	runDeps, makeDeps, err := a.Dependencies()
+	if err != nil {
+		return
+	}
+
+	repoDeps := append(runDeps[0], makeDeps[0]...)
+	aurDeps := append(runDeps[1], makeDeps[1]...)
+
+	if len(aurDeps) != 0 || len(repoDeps) != 0 {
+		if !continueTask("Continue?", "nN") {
+			return fmt.Errorf("user did not like the dependencies")
+		}
+	}
+
+	aurQ, n, err := MultiInfo(aurDeps)
+	if n != len(aurDeps) {
+		aurQ.MissingPackage(aurDeps)
+		if !continueTask("Continue?", "nN") {
+			return fmt.Errorf("unable to install dependencies")
+		}
+	}
+
+	// Handle AUR dependencies first
+	for _, dep := range aurQ {
+		errA := dep.Install([]string{"--asdeps", "--noconfirm"})
+		if errA != nil {
+			return errA
+		}
+	}
+
+	// Repo dependencies
+	if len(repoDeps) != 0 {
+		errR := pacman.Install(repoDeps, []string{"--asdeps", "--noconfirm"})
+		if errR != nil {
+			pacman.CleanRemove(aurDeps)
+			return errR
+		}
+	}
+
+	err = os.Chdir(dir)
+	if err != nil {
+		return
+	}
+
+	var makepkgcmd *exec.Cmd
+	var args []string
+	args = append(args, "-sri")
+	args = append(args, flags...)
+	makepkgcmd = exec.Command(MakepkgBin, args...)
+	makepkgcmd.Stdin, makepkgcmd.Stdout, makepkgcmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+	err = makepkgcmd.Run()
+	return
+}
+
+// PrintInfo prints package info like pacman -Si
+func (a *Result) PrintInfo() {
+	fmt.Println("\x1b[1;37mRepository      :\x1b[0m", "aur")
+	fmt.Println("\x1b[1;37mName            :\x1b[0m", a.Name)
+	fmt.Println("\x1b[1;37mVersion         :\x1b[0m", a.Version)
+	fmt.Println("\x1b[1;37mDescription     :\x1b[0m", a.Description)
+	if a.URL != "" {
+		fmt.Println("\x1b[1;37mURL             :\x1b[0m", a.URL)
+	} else {
+		fmt.Println("\x1b[1;37mURL             :\x1b[0m", "None")
+	}
+	fmt.Println("\x1b[1;37mLicenses        :\x1b[0m", a.License)
+
+	if len(a.Provides) != 0 {
+		fmt.Println("\x1b[1;37mProvides        :\x1b[0m", a.Provides)
+	} else {
+		fmt.Println("\x1b[1;37mProvides        :\x1b[0m", "None")
+	}
+
+	if len(a.Depends) != 0 {
+		fmt.Println("\x1b[1;37mDepends On      :\x1b[0m", a.Depends)
+	} else {
+		fmt.Println("\x1b[1;37mDepends On      :\x1b[0m", "None")
+	}
+
+	if len(a.MakeDepends) != 0 {
+		fmt.Println("\x1b[1;37mMake depends On :\x1b[0m", a.MakeDepends)
+	} else {
+		fmt.Println("\x1b[1;37mMake depends On :\x1b[0m", "None")
+	}
+
+	if len(a.OptDepends) != 0 {
+		fmt.Println("\x1b[1;37mOptional Deps   :\x1b[0m", a.OptDepends)
+	} else {
+		fmt.Println("\x1b[1;37mOptional Deps   :\x1b[0m", "None")
+	}
+
+	if len(a.Conflicts) != 0 {
+		fmt.Println("\x1b[1;37mConflicts With  :\x1b[0m", a.Conflicts)
+	} else {
+		fmt.Println("\x1b[1;37mConflicts With  :\x1b[0m", "None")
+	}
+
+	if a.Maintainer != "" {
+		fmt.Println("\x1b[1;37mMaintainer      :\x1b[0m", a.Maintainer)
+	} else {
+		fmt.Println("\x1b[1;37mMaintainer      :\x1b[0m", "None")
+	}
+	fmt.Println("\x1b[1;37mVotes           :\x1b[0m", a.NumVotes)
+	fmt.Println("\x1b[1;37mPopularity      :\x1b[0m", a.Popularity)
+
+	if a.OutOfDate != 0 {
+		fmt.Println("\x1b[1;37mOut-of-date     :\x1b[0m", "Yes")
+	}
+
+}
+
+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)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+
+	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()
+	if err != nil {
+		return
+	}
+
+	return
+}

+ 51 - 0
aur/utils.go

@@ -2,6 +2,7 @@ package aur
 
 import (
 	"encoding/json"
+	"fmt"
 	"io"
 	"net/http"
 	"os"
@@ -10,6 +11,33 @@ import (
 // Editor gives the default system editor, uses vi in last case
 var Editor = "vi"
 
+// TarBin describes the default installation point of tar command.
+const TarBin string = "/usr/bin/tar"
+
+// BaseURL givers the AUR default address.
+const BaseURL string = "https://aur.archlinux.org"
+
+// MakepkgBin describes the default installation point of makepkg command.
+const MakepkgBin string = "/usr/bin/makepkg"
+
+// SearchMode is search without numbers.
+const SearchMode int = -1
+
+// NoConfirm ignores prompts.
+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
+	TopDown
+)
+
 func init() {
 	if os.Getenv("EDITOR") != "" {
 		Editor = os.Getenv("EDITOR")
@@ -46,3 +74,26 @@ func downloadFile(filepath string, url string) (err error) {
 	_, err = io.Copy(out, resp.Body)
 	return err
 }
+
+func continueTask(s string, def string) (cont bool) {
+	if NoConfirm {
+		return true
+	}
+	var postFix string
+
+	if def == "nN" {
+		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 response == string(def[0]) || response == string(def[1]) {
+		return false
+	}
+
+	return true
+}