diff --git a/aur.go b/aur.go deleted file mode 100644 index 3d44d47d..00000000 --- a/aur.go +++ /dev/null @@ -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 -} diff --git a/install.go b/install.go new file mode 100644 index 00000000..99174470 --- /dev/null +++ b/install.go @@ -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 +} diff --git a/remove.go b/remove.go new file mode 100644 index 00000000..27951307 --- /dev/null +++ b/remove.go @@ -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 +} diff --git a/repo.go b/repo.go deleted file mode 100644 index 6a33170f..00000000 --- a/repo.go +++ /dev/null @@ -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 -} diff --git a/search.go b/search.go new file mode 100644 index 00000000..1b10fb29 --- /dev/null +++ b/search.go @@ -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 +} + + diff --git a/utilstructs.go b/utilstructs.go new file mode 100644 index 00000000..f1505283 --- /dev/null +++ b/utilstructs.go @@ -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 +} diff --git a/yay.go b/yay.go index b1a29037..ca5f020e 100644 --- a/yay.go +++ b/yay.go @@ -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)