Added Pacargo, changes to search

This commit is contained in:
Jguer 2016-09-09 14:55:16 +01:00
parent c7fd16e367
commit fcabffa649
7 changed files with 440 additions and 384 deletions

267
aur.go
View file

@ -1,267 +0,0 @@
package main
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"sort"
"strings"
)
// AurInfo is the result of an info search
type AurInfo struct {
Version int `json:"version"`
Type string `json:"type"`
Resultcount int `json:"resultcount"`
Results []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 float64 `json:"Popularity"`
OutOfDate interface{} `json:"OutOfDate"`
Maintainer string `json:"Maintainer"`
FirstSubmitted int `json:"FirstSubmitted"`
LastModified int `json:"LastModified"`
URLPath string `json:"URLPath"`
Depends []string `json:"Depends"`
MakeDepends []string `json:"MakeDepends"`
OptDepends []string `json:"OptDepends"`
Conflicts []string `json:"Conflicts"`
License []string `json:"License"`
Keywords []string `json:"Keywords"`
} `json:"results"`
}
// AurResult describes an AUR package
type AurResult 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 int `json:"Popularity"`
OutOfDate interface{} `json:"OutOfDate"`
Maintainer string `json:"Maintainer"`
FirstSubmitted int `json:"FirstSubmitted"`
LastModified int `json:"LastModified"`
URLPath string `json:"URLPath"`
}
// AurSearch describes an AUR search
type AurSearch struct {
Resultcount int `json:"resultcount"`
Results []AurResult `json:"results"`
Type string `json:"type"`
Version int `json:"version"`
}
// getJSON handles JSON retrieval and decoding to struct
func getJSON(url string, target interface{}) error {
r, err := http.Get(url)
if err != nil {
return err
}
defer r.Body.Close()
return json.NewDecoder(r.Body).Decode(target)
}
func (r AurSearch) Len() int {
return len(r.Results)
}
func (r AurSearch) Less(i, j int) bool {
return r.Results[i].NumVotes > r.Results[j].NumVotes
}
func (r AurSearch) Swap(i, j int) {
r.Results[i], r.Results[j] = r.Results[j], r.Results[i]
}
func searchAurPackages(pkg string) (search AurSearch, err error) {
err = getJSON("https://aur.archlinux.org/rpc/?v=5&type=search&arg="+pkg, &search)
sort.Sort(search)
return
}
func infoAurPackage(pkg string) (info AurInfo, err error) {
err = getJSON("https://aur.archlinux.org/rpc/?v=5&type=info&arg[]="+pkg, &info)
return
}
func (r AurSearch) printSearch(index int) (err error) {
for i, result := range r.Results {
if index != SearchMode {
fmt.Printf("%d \033[1maur/\x1B[33m%s \x1B[36m%s\033[0m (%d)\n %s\n",
i+index, result.Name, result.Version, result.NumVotes, result.Description)
} else {
fmt.Printf("\033[1maur/\x1B[33m%s \x1B[36m%s\033[0m (%d)\n %s\n",
result.Name, result.Version, result.NumVotes, result.Description)
}
}
return
}
func downloadFile(filepath string, url string) (err error) {
// Create the file
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
// Get the data
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
// Writer the body to file
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
return nil
}
// To implement
func (a AurResult) getDepsfromFile(pkgbuildLoc string) (err error) {
var depend string
file, err := os.Open(pkgbuildLoc)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
if strings.Contains(scanner.Text(), "optdepends=(") {
continue
}
if strings.Contains(scanner.Text(), "depends=(") {
depend = scanner.Text()
fields := strings.Fields(depend)
for _, i := range fields {
fmt.Println(i)
}
break
}
}
return nil
}
func (a AurResult) getDepsFromRPC() (final []string, err error) {
f := func(c rune) bool {
return c == '>' || c == '<' || c == '=' || c == ' '
}
info, err := infoAurPackage(a.Name)
if len(info.Results) == 0 {
return final, errors.New("Failed to get deps from RPC")
}
for _, deps := range info.Results[0].MakeDepends {
fields := strings.FieldsFunc(deps, f)
if !isInRepo(fields[0]) {
final = append(final, fields[0])
}
}
for _, deps := range info.Results[0].Depends {
fields := strings.FieldsFunc(deps, f)
if !isInRepo(fields[0]) {
final = append(final, fields[0])
}
}
return
}
func installAURPackage(pkg string) (err error) {
info, err := infoAurPackage(pkg)
if err != nil {
return
}
return err
}
func (a AurResult) getAURDependencies() (err error) {
pkglist, err := a.getDepsFromRPC()
for _, i := range pkglist {
err = installAURPackage(i)
if err != nil {
// uninstall list TODO
return
}
}
return nil
}
func (a AurResult) installResult() (err error) {
// No need to use filepath.separators because it won't run on inferior platforms
err = os.MkdirAll(BuildDir+"builds", 0755)
if err != nil {
fmt.Println(err)
return
}
tarLocation := BuildDir + a.Name + ".tar.gz"
err = downloadFile(tarLocation, BaseURL+a.URLPath)
if err != nil {
return
}
err = exec.Command(TarBin, "-xf", tarLocation, "-C", BuildDir).Run()
if err != nil {
return
}
a.getAURDependencies()
os.Exit(0)
fmt.Print("\033[1m\x1b[32m==> Edit PKGBUILD? (y/n)\033[0m")
var response string
fmt.Scanln(&response)
if strings.ContainsAny(response, "y & Y") {
editcmd := exec.Command(Editor, BuildDir+a.Name+"/"+"PKGBUILD")
editcmd.Stdout = os.Stdout
editcmd.Stderr = os.Stderr
editcmd.Stdin = os.Stdin
err = editcmd.Run()
}
err = os.Chdir(BuildDir + a.Name)
if err != nil {
return
}
makepkgcmd := exec.Command(MakepkgBin, "-sri")
makepkgcmd.Stdout = os.Stdout
makepkgcmd.Stderr = os.Stderr
makepkgcmd.Stdin = os.Stdin
err = makepkgcmd.Run()
return
}

114
install.go Normal file
View file

@ -0,0 +1,114 @@
package main
import (
"errors"
"fmt"
"os"
"os/exec"
"strings"
)
func installnumArray(num []int, aurRes AurSearch, repoRes RepoSearch, flags ...string) (err error) {
if len(num) == 0 {
return errors.New("Installing AUR array: No nums selected")
}
var index int
for _, i := range num {
if i > repoRes.Resultcount-1 {
index = i - repoRes.Resultcount
err = aurRes.Results[i-index].install(flags...)
if err != nil {
// Do not abandon program, we might still be able to install the rest
fmt.Println(err)
}
} else {
InstallPackage(repoRes.Results[i].Name, flags...)
}
}
return err
}
func installAURPackage(pkg string, flags ...string) (err error) {
info, err := infoAurPackage(pkg)
if err != nil {
return
}
if info.Resultcount == 0 {
return errors.New("Package '" + pkg + "' does not exist")
}
info.Results[0].install(flags...)
return err
}
func (a AurResult) install(flags ...string) (err error) {
// No need to use filepath.separators because it won't run on inferior platforms
err = os.MkdirAll(BuildDir+"builds", 0755)
if err != nil {
fmt.Println(err)
return
}
tarLocation := BuildDir + a.Name + ".tar.gz"
defer os.Remove(BuildDir + a.Name + ".tar.gz")
err = downloadFile(tarLocation, BaseURL+a.URLPath)
if err != nil {
return
}
err = exec.Command(TarBin, "-xf", tarLocation, "-C", BuildDir).Run()
if err != nil {
return
}
defer os.RemoveAll(BuildDir + a.Name)
err = a.getAURDependencies()
if err != nil {
return
}
fmt.Print("\033[1m\x1b[32m==> Edit PKGBUILD? (y/n)\033[0m")
var response string
fmt.Scanln(&response)
if strings.ContainsAny(response, "y & Y") {
editcmd := exec.Command(Editor, BuildDir+a.Name+"/"+"PKGBUILD")
editcmd.Stdout = os.Stdout
editcmd.Stderr = os.Stderr
editcmd.Stdin = os.Stdin
err = editcmd.Run()
}
err = os.Chdir(BuildDir + a.Name)
if err != nil {
return
}
var args string
if len(flags) != 0 {
args = fmt.Sprintf(" %s", strings.Join(flags, " "))
}
makepkgcmd := exec.Command(MakepkgBin, "-sri"+args)
makepkgcmd.Stdout = os.Stdout
makepkgcmd.Stderr = os.Stderr
makepkgcmd.Stdin = os.Stdin
err = makepkgcmd.Run()
return
}
// InstallPackage handles repo installs
func InstallPackage(pkg string, flags ...string) (err error) {
var args string
fmt.Println(len(flags))
if len(flags) != 0 {
args = fmt.Sprintf(" %s", strings.Join(flags, " "))
}
cmd := exec.Command("sudo", "pacman", "-S", pkg+args)
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
err = cmd.Run()
return nil
}

16
remove.go Normal file
View file

@ -0,0 +1,16 @@
package main
import (
"os"
"os/exec"
"strings"
)
func removePackage(pkg string, extra string, flags ...string) (err error) {
cmd := exec.Command("sudo", PacmanBin, "-R"+extra, pkg, strings.Join(flags, " "))
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
err = cmd.Run()
return nil
}

91
repo.go
View file

@ -1,91 +0,0 @@
package main
import (
"fmt"
"os"
"os/exec"
"strings"
)
// RepoResult describes a Repository package
type RepoResult struct {
Description string
Repository string
Version string
Name string
}
// RepoSearch describes a Repository search
type RepoSearch struct {
Resultcount int
Results []RepoResult
}
func getInstalledPackage(pkg string) (err error) {
cmd := exec.Command(PacmanBin, "-Qi", pkg)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
return
}
// InstallPackage handles repo installs
func InstallPackage(pkg string, flags ...string) (err error) {
cmd := exec.Command(PacmanBin, "-S", pkg, strings.Join(flags, " "))
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
err = cmd.Run()
return nil
}
// SearchPackages handles repo searches
func SearchPackages(pkg string) (search RepoSearch, err error) {
cmdOutput, err := exec.Command(PacmanBin, "-Ss", pkg).Output()
outputSlice := strings.Split(string(cmdOutput), "\n")
if outputSlice[0] == "" {
return search, nil
}
i := true
var tempStr string
var rRes *RepoResult
for _, pkgStr := range outputSlice {
if i {
rRes = new(RepoResult)
fmt.Sscanf(pkgStr, "%s %s\n", &tempStr, &rRes.Version)
repoNameSlc := strings.Split(tempStr, "/")
rRes.Repository = repoNameSlc[0]
rRes.Name = repoNameSlc[1]
i = false
} else {
rRes.Description = pkgStr
search.Resultcount++
search.Results = append(search.Results, *rRes)
i = true
}
}
return
}
func isInRepo(pkg string) bool {
if _, err := exec.Command(PacmanBin, "-Sp", pkg).Output(); err != nil {
return false
}
return true
}
func (s RepoSearch) printSearch(index int) (err error) {
for i, result := range s.Results {
if index != SearchMode {
fmt.Printf("%d \033[1m%s/\x1B[33m%s \x1B[36m%s\033[0m\n%s\n",
i, result.Repository, result.Name, result.Version, result.Description)
} else {
fmt.Printf("\033[1m%s/\x1B[33m%s \x1B[36m%s\033[0m\n%s\n",
result.Repository, result.Name, result.Version, result.Description)
}
}
return nil
}

165
search.go Normal file
View file

@ -0,0 +1,165 @@
package main
import (
"bufio"
"errors"
"fmt"
"os"
"os/exec"
"sort"
"strings"
)
func searchAurPackages(pkg string, index int) (search AurSearch, err error) {
err = getJSON("https://aur.archlinux.org/rpc/?v=5&type=search&arg="+pkg, &search)
if index != SearchMode {
sort.Sort(search)
}
return
}
// SearchPackages handles repo searches
func SearchPackages(pkg string) (search RepoSearch, err error) {
cmdOutput, err := exec.Command(PacmanBin, "-Ss", pkg).Output()
outputSlice := strings.Split(string(cmdOutput), "\n")
if outputSlice[0] == "" {
return search, nil
}
i := true
var tempStr string
var rRes *RepoResult
for _, pkgStr := range outputSlice {
if i {
rRes = new(RepoResult)
fmt.Sscanf(pkgStr, "%s %s\n", &tempStr, &rRes.Version)
repoNameSlc := strings.Split(tempStr, "/")
rRes.Repository = repoNameSlc[0]
rRes.Name = repoNameSlc[1]
i = false
} else {
rRes.Description = pkgStr
search.Resultcount++
search.Results = append(search.Results, *rRes)
i = true
}
}
return
}
func infoAurPackage(pkg string) (info AurSearch, err error) {
err = getJSON("https://aur.archlinux.org/rpc/?v=5&type=info&arg[]="+pkg, &info)
return
}
func (r AurSearch) printSearch(index int) (err error) {
for i, result := range r.Results {
if index != SearchMode {
fmt.Printf("%d \033[1maur/\x1B[33m%s \x1B[36m%s\033[0m (%d)\n %s\n",
i+index, result.Name, result.Version, result.NumVotes, result.Description)
} else {
fmt.Printf("\033[1maur/\x1B[33m%s \x1B[36m%s\033[0m (%d)\n %s\n",
result.Name, result.Version, result.NumVotes, result.Description)
}
}
return
}
func (s RepoSearch) printSearch(index int) (err error) {
for i, result := range s.Results {
if index != SearchMode {
fmt.Printf("%d \033[1m%s/\x1B[33m%s \x1B[36m%s\033[0m\n%s\n",
i, result.Repository, result.Name, result.Version, result.Description)
} else {
fmt.Printf("\033[1m%s/\x1B[33m%s \x1B[36m%s\033[0m\n%s\n",
result.Repository, result.Name, result.Version, result.Description)
}
}
return nil
}
// To implement
func (a AurResult) getDepsfromFile(pkgbuildLoc string) (err error) {
var depend string
file, err := os.Open(pkgbuildLoc)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
if strings.Contains(scanner.Text(), "optdepends=(") {
continue
}
if strings.Contains(scanner.Text(), "depends=(") {
depend = scanner.Text()
fields := strings.Fields(depend)
for _, i := range fields {
fmt.Println(i)
}
break
}
}
return nil
}
func (a AurResult) getDepsFromRPC() (final []string, err error) {
f := func(c rune) bool {
return c == '>' || c == '<' || c == '=' || c == ' '
}
info, err := infoAurPackage(a.Name)
if err != nil {
return
}
if len(info.Results) == 0 {
return final, errors.New("Failed to get deps from RPC")
}
for _, deps := range info.Results[0].MakeDepends {
fields := strings.FieldsFunc(deps, f)
if !isInRepo(fields[0]) {
final = append(final, fields[0])
}
}
for _, deps := range info.Results[0].Depends {
fields := strings.FieldsFunc(deps, f)
if !isInRepo(fields[0]) {
final = append(final, fields[0])
}
}
return
}
func (a AurResult) getAURDependencies() (err error) {
pkglist, err := a.getDepsFromRPC()
fmt.Printf("%+v\n", pkglist)
for _, i := range pkglist {
err = installAURPackage(i, "--asdeps")
if err != nil {
for _, e := range pkglist {
removePackage(e, "sdc")
}
return
}
}
return nil
}
func getInstalledPackage(pkg string) (err error) {
cmd := exec.Command(PacmanBin, "-Qi", pkg)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
return
}

116
utilstructs.go Normal file
View file

@ -0,0 +1,116 @@
package main
import (
"encoding/json"
"io"
"net/http"
"os"
"os/exec"
)
// RepoResult describes a Repository package
type RepoResult struct {
Description string
Repository string
Version string
Name string
}
// RepoSearch describes a Repository search
type RepoSearch struct {
Resultcount int
Results []RepoResult
}
// AurResult describes an AUR package
type AurResult 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 interface{} `json:"OutOfDate"`
Maintainer string `json:"Maintainer"`
FirstSubmitted int `json:"FirstSubmitted"`
LastModified int `json:"LastModified"`
URLPath string `json:"URLPath"`
Depends []string `json:"Depends"`
MakeDepends []string `json:"MakeDepends"`
OptDepends []string `json:"OptDepends"`
Conflicts []string `json:"Conflicts"`
License []string `json:"License"`
Keywords []string `json:"Keywords"`
}
// AurSearch describes an AUR search
type AurSearch struct {
Resultcount int `json:"resultcount"`
Results []AurResult `json:"results"`
Type string `json:"type"`
Version int `json:"version"`
}
func downloadFile(filepath string, url string) (err error) {
// Create the file
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
// Get the data
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
// Writer the body to file
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
return nil
}
// getJSON handles JSON retrieval and decoding to struct
func getJSON(url string, target interface{}) error {
r, err := http.Get(url)
if err != nil {
return err
}
defer r.Body.Close()
return json.NewDecoder(r.Body).Decode(target)
}
func (r AurSearch) Len() int {
return len(r.Results)
}
func (r AurSearch) Less(i, j int) bool {
return r.Results[i].NumVotes > r.Results[j].NumVotes
}
func (r AurSearch) Swap(i, j int) {
r.Results[i], r.Results[j] = r.Results[j], r.Results[i]
}
func isInRepo(pkg string) bool {
if _, err := exec.Command(PacmanBin, "-Sp", pkg).Output(); err != nil {
return false
}
return true
}
func isInstalled(pkg string) bool {
if _, err := exec.Command(PacmanBin, "-Qq", pkg).Output(); err != nil {
return false
}
return true
}

55
yay.go
View file

@ -56,31 +56,8 @@ func getNums() (numbers []int, err error) {
return
}
func installnumArray(num []int, aurRes AurSearch, repoRes RepoSearch) (err error) {
if len(num) == 0 {
return errors.New("Installing AUR array: No nums selected")
}
var index int
for _, i := range num {
if i > repoRes.Resultcount-1 {
index = i - repoRes.Resultcount
fmt.Printf("%+v\n\n", aurRes.Results[i-index])
err = aurRes.Results[i-index].installResult()
if err != nil {
// Do not abandon program, we might still be able to install the rest
fmt.Println(err)
}
} else {
}
}
return err
}
func defaultMode(pkg string) (err error) {
aurRes, err := searchAurPackages(pkg)
aurRes, err := searchAurPackages(pkg, 0)
repoRes, err := SearchPackages(pkg)
if err != nil {
return
@ -103,13 +80,39 @@ func defaultMode(pkg string) (err error) {
return
}
func searchMode(pkg string) (err error) {
aur, err := searchAurPackages(pkg, SearchMode)
repo, err := SearchPackages(pkg)
if err != nil {
return err
}
aur.printSearch(SearchMode)
repo.printSearch(SearchMode)
return nil
}
func main() {
flag.Parse()
var err error
if os.Getenv("EDITOR") != "" {
Editor = os.Getenv("EDITOR")
}
searchTerm := flag.Args()
err := defaultMode(searchTerm[0])
args := flag.Args()
if args[0] == "-Ss" {
err = searchMode(strings.Join(args[2:], " "))
} else if args[0] == "-S" {
if isInRepo(args[1]) {
err = InstallPackage(args[1], args[2:]...)
} else {
err = installAURPackage(args[1], args[2:]...)
}
} else {
err = defaultMode(args[0])
}
if err != nil {
fmt.Println(err)
os.Exit(1)