From 38617c2781766081fe8933ca0172d8809f05a866 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sat, 29 Apr 2017 18:12:12 +0100 Subject: [PATCH 01/30] Refactored cmd/yay --- actions.go | 276 +------------------------------------------------ cmd/yay/yay.go | 139 ------------------------- query.go | 97 +++++++++++++++++ util/util.go | 3 +- utils.go | 103 ++++++++++++++++++ yay.go | 234 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 437 insertions(+), 415 deletions(-) delete mode 100644 cmd/yay/yay.go create mode 100644 query.go create mode 100644 utils.go create mode 100644 yay.go diff --git a/actions.go b/actions.go index 4245afe3..a2ac4dc0 100644 --- a/actions.go +++ b/actions.go @@ -1,112 +1,14 @@ -package yay +package main import ( - "bufio" "fmt" - "io" - "math" "os" - "os/exec" - "strconv" - "strings" - "time" aur "github.com/jguer/yay/aur" pac "github.com/jguer/yay/pacman" "github.com/jguer/yay/util" ) -// NumberMenu presents a CLI for selecting packages to install. -func NumberMenu(pkgS []string, flags []string) (err error) { - var num int - - aq, numaq, err := aur.Search(pkgS, true) - if err != nil { - fmt.Println("Error during AUR search:", err) - } - pq, numpq, err := pac.Search(pkgS) - if err != nil { - return - } - - if numpq == 0 && numaq == 0 { - return fmt.Errorf("no packages match search") - } - - if util.SortMode == util.BottomUp { - aq.PrintSearch(numpq) - pq.PrintSearch() - } else { - pq.PrintSearch() - aq.PrintSearch(numpq) - } - - fmt.Printf("\x1b[32m%s\x1b[0m\nNumbers:", "Type numbers to install. Separate each number with a space.") - reader := bufio.NewReader(os.Stdin) - numberBuf, overflow, err := reader.ReadLine() - if err != nil || overflow { - fmt.Println(err) - return - } - - numberString := string(numberBuf) - var aurInstall []string - var repoInstall []string - result := strings.Fields(numberString) - for _, numS := range result { - num, err = strconv.Atoi(numS) - if err != nil { - continue - } - - // Install package - if num > numaq+numpq-1 || num < 0 { - continue - } else if num > numpq-1 { - if util.SortMode == util.BottomUp { - aurInstall = append(aurInstall, aq[numaq+numpq-num-1].Name) - } else { - aurInstall = append(aurInstall, aq[num-numpq].Name) - } - } else { - if util.SortMode == util.BottomUp { - repoInstall = append(repoInstall, pq[numpq-num-1].Name) - } else { - repoInstall = append(repoInstall, pq[num].Name) - } - } - } - - if len(repoInstall) != 0 { - pac.Install(repoInstall, flags) - } - - if len(aurInstall) != 0 { - q, n, err := aur.MultiInfo(aurInstall) - if err != nil { - return err - } else if n != len(aurInstall) { - q.MissingPackage(aurInstall) - } - - var finalrm []string - for _, aurpkg := range q { - finalmdeps, err := aurpkg.Install(flags) - finalrm = append(finalrm, finalmdeps...) - if err != nil { - // Do not abandon program, we might still be able to install the rest - fmt.Println(err) - } - } - - if len(finalrm) != 0 { - aur.RemoveMakeDeps(finalrm) - } - } - - return nil -} - // Install handles package installs func Install(pkgs []string, flags []string) error { aurs, repos, _ := pac.PackageSlices(pkgs) @@ -149,151 +51,6 @@ func Upgrade(flags []string) error { return erra } -// SyncSearch presents a query to the local repos and to the AUR. -func SyncSearch(pkgS []string) (err error) { - aq, _, err := aur.Search(pkgS, true) - if err != nil { - return err - } - pq, _, err := pac.Search(pkgS) - if err != nil { - return err - } - - if util.SortMode == util.BottomUp { - aq.PrintSearch(0) - pq.PrintSearch() - } else { - pq.PrintSearch() - aq.PrintSearch(0) - } - - return nil -} - -// SyncInfo serves as a pacman -Si for repo packages and AUR packages. -func SyncInfo(pkgS []string, flags []string) (err error) { - aurS, repoS, err := pac.PackageSlices(pkgS) - if err != nil { - return - } - - q, _, err := aur.MultiInfo(aurS) - if err != nil { - fmt.Println(err) - } - - for _, aurP := range q { - aurP.PrintInfo() - } - - if len(repoS) != 0 { - err = PassToPacman("-Si", repoS, flags) - } - - return -} - -// LocalStatistics returns installed packages statistics. -func LocalStatistics(version string) error { - info, err := pac.Statistics() - if err != nil { - return err - } - - foreignS, foreign, _ := pac.ForeignPackages() - - fmt.Printf("\n Yay version r%s\n", version) - fmt.Println("\x1B[1;34m===========================================\x1B[0m") - fmt.Printf("\x1B[1;32mTotal installed packages: \x1B[0;33m%d\x1B[0m\n", info.Totaln) - fmt.Printf("\x1B[1;32mTotal foreign installed packages: \x1B[0;33m%d\x1B[0m\n", foreign) - fmt.Printf("\x1B[1;32mExplicitly installed packages: \x1B[0;33m%d\x1B[0m\n", info.Expln) - fmt.Printf("\x1B[1;32mTotal Size occupied by packages: \x1B[0;33m%s\x1B[0m\n", size(info.TotalSize)) - fmt.Println("\x1B[1;34m===========================================\x1B[0m") - fmt.Println("\x1B[1;32mTen biggest packages\x1B[0m") - pac.BiggestPackages() - 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;37;40m is orphaned.\x1b[0m\n", res.Name) - } - if res.OutOfDate != 0 { - fmt.Printf("\x1b[1;31;40mWarning: \x1B[1;33;40m%s\x1b[0;37;40m is out-of-date in AUR.\x1b[0m\n", res.Name) - } - } - - return nil -} - -// Function by pyk https://github.com/pyk/byten -func index(s int64) float64 { - x := math.Log(float64(s)) / math.Log(1024) - return math.Floor(x) -} - -// Function by pyk https://github.com/pyk/byten -func countSize(s int64, i float64) float64 { - return float64(s) / math.Pow(1024, math.Floor(i)) -} - -// Size return a formated string from file size -// Function by pyk https://github.com/pyk/byten -func size(s int64) string { - - symbols := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"} - i := index(s) - if s < 10 { - return fmt.Sprintf("%dB", s) - } - size := countSize(s, i) - format := "%.0f" - if size < 10 { - format = "%.1f" - } - - return fmt.Sprintf(format+"%s", size, symbols[int(i)]) -} - -// PassToPacman outsorces execution to pacman binary without modifications. -func PassToPacman(op string, pkgs []string, flags []string) error { - var cmd *exec.Cmd - var args []string - - args = append(args, op) - if len(pkgs) != 0 { - args = append(args, pkgs...) - } - - if len(flags) != 0 { - args = append(args, flags...) - } - - if strings.Contains(op, "-Q") || op == "-Si" { - cmd = exec.Command("pacman", args...) - } else { - args = append([]string{"pacman"}, args...) - cmd = exec.Command("sudo", args...) - } - - cmd.Stdout = os.Stdout - cmd.Stdin = os.Stdin - cmd.Stderr = os.Stderr - err := cmd.Run() - return err -} - // CleanDependencies removels all dangling dependencies in system func CleanDependencies(pkgs []string) error { hanging, err := pac.HangingPackages() @@ -327,34 +84,3 @@ func GetPkgbuild(pkg string) (err error) { err = aur.GetPkgbuild(pkg, wd) return } - -// Complete provides completion info for shells -func Complete() (err error) { - path := os.Getenv("HOME") + "/.cache/yay/aur_" + util.Shell + ".cache" - - if info, err := os.Stat(path); os.IsNotExist(err) || time.Since(info.ModTime()).Hours() > 48 { - os.MkdirAll(os.Getenv("HOME")+"/.cache/yay", 0755) - - out, err := os.Create(path) - if err != nil { - return err - } - - if aur.CreateAURList(out) != nil { - defer os.Remove(path) - } - err = pac.CreatePackageList(out) - - out.Close() - return err - } - - in, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0755) - if err != nil { - return err - } - defer in.Close() - - _, err = io.Copy(os.Stdout, in) - return err -} diff --git a/cmd/yay/yay.go b/cmd/yay/yay.go deleted file mode 100644 index 294e0e49..00000000 --- a/cmd/yay/yay.go +++ /dev/null @@ -1,139 +0,0 @@ -package main - -import ( - "fmt" - "os" - - "github.com/jguer/yay" - "github.com/jguer/yay/util" -) - -func usage() { - fmt.Println(`usage: yay [...] - operations: - yay {-h --help} - yay {-V --version} - yay {-D --database} - yay {-F --files} [options] [package(s)] - yay {-Q --query} [options] [package(s)] - yay {-R --remove} [options] - yay {-S --sync} [options] [package(s)] - yay {-T --deptest} [options] [package(s)] - yay {-U --upgrade} [options] - - New operations: - yay -Qstats displays system information - yay -Cd remove unneeded dependencies - yay -G [package(s)] get pkgbuild from ABS or AUR - - New options: - --topdown shows repository's packages first and then aur's - --bottomup shows aur's packages first and then repository's - --noconfirm skip user input on package install -`) -} - -var version = "1.100" - -func parser() (op string, options []string, packages []string, err error) { - if len(os.Args) < 2 { - err = fmt.Errorf("no operation specified") - return - } - op = "yogurt" - - for _, arg := range os.Args[1:] { - if arg[0] == '-' && arg[1] != '-' { - switch arg { - case "-b": - util.Build = true - default: - op = arg - } - continue - } - - if arg[0] == '-' && arg[1] == '-' { - switch arg { - case "--build": - util.Build = true - case "--bottomup": - util.SortMode = util.BottomUp - case "--topdown": - util.SortMode = util.TopDown - - case "--complete": - util.Shell = "sh" - yay.Complete() - os.Exit(0) - case "--fcomplete": - util.Shell = "fish" - yay.Complete() - os.Exit(0) - case "--help": - usage() - os.Exit(0) - case "--noconfirm": - util.NoConfirm = true - fallthrough - default: - options = append(options, arg) - } - continue - } - - packages = append(packages, arg) - } - return -} - -func main() { - op, options, pkgs, err := parser() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - switch op { - case "-Cd": - err = yay.CleanDependencies(pkgs) - case "-G": - for _, pkg := range pkgs { - err = yay.GetPkgbuild(pkg) - if err != nil { - fmt.Println(pkg+":", err) - } - } - case "-Qstats": - err = yay.LocalStatistics(version) - case "-Ss", "-Ssq", "-Sqs": - if op == "-Ss" { - util.SearchVerbosity = util.Detailed - } else { - util.SearchVerbosity = util.Minimal - } - - if pkgs != nil { - err = yay.SyncSearch(pkgs) - } - case "-S": - err = yay.Install(pkgs, options) - case "-Syu", "-Suy": - err = yay.Upgrade(options) - case "-Si": - err = yay.SyncInfo(pkgs, options) - case "yogurt": - util.SearchVerbosity = util.NumberMenu - - if pkgs != nil { - err = yay.NumberMenu(pkgs, options) - } - default: - err = yay.PassToPacman(op, pkgs, options) - } - - if err != nil { - fmt.Println(err) - os.Exit(1) - } -} diff --git a/query.go b/query.go new file mode 100644 index 00000000..c9752264 --- /dev/null +++ b/query.go @@ -0,0 +1,97 @@ +package main + +import ( + "fmt" + + "github.com/jguer/yay/aur" + pac "github.com/jguer/yay/pacman" + "github.com/jguer/yay/util" +) + +// SyncSearch presents a query to the local repos and to the AUR. +func SyncSearch(pkgS []string) (err error) { + aq, _, err := aur.Search(pkgS, true) + if err != nil { + return err + } + pq, _, err := pac.Search(pkgS) + if err != nil { + return err + } + + if util.SortMode == util.BottomUp { + aq.PrintSearch(0) + pq.PrintSearch() + } else { + pq.PrintSearch() + aq.PrintSearch(0) + } + + return nil +} + +// SyncInfo serves as a pacman -Si for repo packages and AUR packages. +func SyncInfo(pkgS []string, flags []string) (err error) { + aurS, repoS, err := pac.PackageSlices(pkgS) + if err != nil { + return + } + + q, _, err := aur.MultiInfo(aurS) + if err != nil { + fmt.Println(err) + } + + for _, aurP := range q { + aurP.PrintInfo() + } + + if len(repoS) != 0 { + err = PassToPacman("-Si", repoS, flags) + } + + return +} + +// LocalStatistics returns installed packages statistics. +func LocalStatistics(version string) error { + info, err := pac.Statistics() + if err != nil { + return err + } + + foreignS, foreign, _ := pac.ForeignPackages() + + fmt.Printf("\n Yay version r%s\n", version) + fmt.Println("\x1B[1;34m===========================================\x1B[0m") + fmt.Printf("\x1B[1;32mTotal installed packages: \x1B[0;33m%d\x1B[0m\n", info.Totaln) + fmt.Printf("\x1B[1;32mTotal foreign installed packages: \x1B[0;33m%d\x1B[0m\n", foreign) + fmt.Printf("\x1B[1;32mExplicitly installed packages: \x1B[0;33m%d\x1B[0m\n", info.Expln) + fmt.Printf("\x1B[1;32mTotal Size occupied by packages: \x1B[0;33m%s\x1B[0m\n", size(info.TotalSize)) + fmt.Println("\x1B[1;34m===========================================\x1B[0m") + fmt.Println("\x1B[1;32mTen biggest packages\x1B[0m") + pac.BiggestPackages() + 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;37;40m is orphaned.\x1b[0m\n", res.Name) + } + if res.OutOfDate != 0 { + fmt.Printf("\x1b[1;31;40mWarning: \x1B[1;33;40m%s\x1b[0;37;40m is out-of-date in AUR.\x1b[0m\n", res.Name) + } + } + + return nil +} diff --git a/util/util.go b/util/util.go index 29b815e2..380cfa39 100644 --- a/util/util.go +++ b/util/util.go @@ -25,6 +25,7 @@ const ( Minimal ) +// Shell describes the default user shell var Shell = "fish" // Build controls if packages will be built from ABS. @@ -122,7 +123,7 @@ func DownloadAndUnpack(url string, path string, trim bool) (err error) { return } -// Editor returns the prefered system editor. +// Editor returns the preferred system editor. func Editor() string { if os.Getenv("EDITOR") != "" { return os.Getenv("EDITOR") diff --git a/utils.go b/utils.go new file mode 100644 index 00000000..a72984ad --- /dev/null +++ b/utils.go @@ -0,0 +1,103 @@ +package main + +import ( + "fmt" + "io" + "math" + "os" + "os/exec" + "strings" + "time" + + "github.com/jguer/yay/aur" + pac "github.com/jguer/yay/pacman" + "github.com/jguer/yay/util" +) + +// PassToPacman outsorces execution to pacman binary without modifications. +func PassToPacman(op string, pkgs []string, flags []string) error { + var cmd *exec.Cmd + var args []string + + args = append(args, op) + if len(pkgs) != 0 { + args = append(args, pkgs...) + } + + if len(flags) != 0 { + args = append(args, flags...) + } + + if strings.Contains(op, "-Q") { + cmd = exec.Command("pacman", args...) + } else { + args = append([]string{"pacman"}, args...) + cmd = exec.Command("sudo", args...) + } + + cmd.Stdout = os.Stdout + cmd.Stdin = os.Stdin + cmd.Stderr = os.Stderr + err := cmd.Run() + return err +} + +// Complete provides completion info for shells +func Complete() (err error) { + path := os.Getenv("HOME") + "/.cache/yay/aur_" + util.Shell + ".cache" + + if info, err := os.Stat(path); os.IsNotExist(err) || time.Since(info.ModTime()).Hours() > 48 { + os.MkdirAll(os.Getenv("HOME")+"/.cache/yay", 0755) + + out, err := os.Create(path) + if err != nil { + return err + } + + if aur.CreateAURList(out) != nil { + defer os.Remove(path) + } + err = pac.CreatePackageList(out) + + out.Close() + return err + } + + in, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0755) + if err != nil { + return err + } + defer in.Close() + + _, err = io.Copy(os.Stdout, in) + return err +} + +// Function by pyk https://github.com/pyk/byten +func index(s int64) float64 { + x := math.Log(float64(s)) / math.Log(1024) + return math.Floor(x) +} + +// Function by pyk https://github.com/pyk/byten +func countSize(s int64, i float64) float64 { + return float64(s) / math.Pow(1024, math.Floor(i)) +} + +// Size return a formated string from file size +// Function by pyk https://github.com/pyk/byten +func size(s int64) string { + + symbols := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"} + i := index(s) + if s < 10 { + return fmt.Sprintf("%dB", s) + } + size := countSize(s, i) + format := "%.0f" + if size < 10 { + format = "%.1f" + } + + return fmt.Sprintf(format+"%s", size, symbols[int(i)]) +} diff --git a/yay.go b/yay.go new file mode 100644 index 00000000..fb1a1ea1 --- /dev/null +++ b/yay.go @@ -0,0 +1,234 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" + + "github.com/jguer/yay/aur" + pac "github.com/jguer/yay/pacman" + "github.com/jguer/yay/util" +) + +func usage() { + fmt.Println(`usage: yay [...] + operations: + yay {-h --help} + yay {-V --version} + yay {-D --database} + yay {-F --files} [options] [package(s)] + yay {-Q --query} [options] [package(s)] + yay {-R --remove} [options] + yay {-S --sync} [options] [package(s)] + yay {-T --deptest} [options] [package(s)] + yay {-U --upgrade} [options] + + New operations: + yay -Qstats displays system information + yay -Cd remove unneeded dependencies + yay -G [package(s)] get pkgbuild from ABS or AUR + + New options: + --topdown shows repository's packages first and then aur's + --bottomup shows aur's packages first and then repository's + --noconfirm skip user input on package install +`) +} + +var version = "1.116" + +func parser() (op string, options []string, packages []string, err error) { + if len(os.Args) < 2 { + err = fmt.Errorf("no operation specified") + return + } + op = "yogurt" + + for _, arg := range os.Args[1:] { + if arg[0] == '-' && arg[1] != '-' { + switch arg { + case "-b": + util.Build = true + default: + op = arg + } + continue + } + + if arg[0] == '-' && arg[1] == '-' { + switch arg { + case "--build": + util.Build = true + case "--bottomup": + util.SortMode = util.BottomUp + case "--topdown": + util.SortMode = util.TopDown + + case "--complete": + util.Shell = "sh" + Complete() + os.Exit(0) + case "--fcomplete": + util.Shell = "fish" + Complete() + os.Exit(0) + case "--help": + usage() + os.Exit(0) + case "--noconfirm": + util.NoConfirm = true + fallthrough + default: + options = append(options, arg) + } + continue + } + + packages = append(packages, arg) + } + return +} + +func main() { + op, options, pkgs, err := parser() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + switch op { + case "-Cd": + err = CleanDependencies(pkgs) + case "-G": + for _, pkg := range pkgs { + err = GetPkgbuild(pkg) + if err != nil { + fmt.Println(pkg+":", err) + } + } + case "-Qstats": + err = LocalStatistics(version) + case "-Ss", "-Ssq", "-Sqs": + if op == "-Ss" { + util.SearchVerbosity = util.Detailed + } else { + util.SearchVerbosity = util.Minimal + } + + if pkgs != nil { + err = SyncSearch(pkgs) + } + case "-S": + err = Install(pkgs, options) + case "-Syu", "-Suy": + err = Upgrade(options) + case "-Si": + err = SyncInfo(pkgs, options) + case "yogurt": + util.SearchVerbosity = util.NumberMenu + + if pkgs != nil { + err = numberMenu(pkgs, options) + } + default: + err = PassToPacman(op, pkgs, options) + } + + if err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +// NumberMenu presents a CLI for selecting packages to install. +func numberMenu(pkgS []string, flags []string) (err error) { + var num int + + aq, numaq, err := aur.Search(pkgS, true) + if err != nil { + fmt.Println("Error during AUR search:", err) + } + pq, numpq, err := pac.Search(pkgS) + if err != nil { + return + } + + if numpq == 0 && numaq == 0 { + return fmt.Errorf("no packages match search") + } + + if util.SortMode == util.BottomUp { + aq.PrintSearch(numpq) + pq.PrintSearch() + } else { + pq.PrintSearch() + aq.PrintSearch(numpq) + } + + fmt.Printf("\x1b[32m%s\x1b[0m\nNumbers:", "Type numbers to install. Separate each number with a space.") + reader := bufio.NewReader(os.Stdin) + numberBuf, overflow, err := reader.ReadLine() + if err != nil || overflow { + fmt.Println(err) + return + } + + numberString := string(numberBuf) + var aurInstall []string + var repoInstall []string + result := strings.Fields(numberString) + for _, numS := range result { + num, err = strconv.Atoi(numS) + if err != nil { + continue + } + + // Install package + if num > numaq+numpq-1 || num < 0 { + continue + } else if num > numpq-1 { + if util.SortMode == util.BottomUp { + aurInstall = append(aurInstall, aq[numaq+numpq-num-1].Name) + } else { + aurInstall = append(aurInstall, aq[num-numpq].Name) + } + } else { + if util.SortMode == util.BottomUp { + repoInstall = append(repoInstall, pq[numpq-num-1].Name) + } else { + repoInstall = append(repoInstall, pq[num].Name) + } + } + } + + if len(repoInstall) != 0 { + pac.Install(repoInstall, flags) + } + + if len(aurInstall) != 0 { + q, n, err := aur.MultiInfo(aurInstall) + if err != nil { + return err + } else if n != len(aurInstall) { + q.MissingPackage(aurInstall) + } + + var finalrm []string + for _, aurpkg := range q { + finalmdeps, err := aurpkg.Install(flags) + finalrm = append(finalrm, finalmdeps...) + if err != nil { + // Do not abandon program, we might still be able to install the rest + fmt.Println(err) + } + } + + if len(finalrm) != 0 { + aur.RemoveMakeDeps(finalrm) + } + } + + return nil +} From acf2a33a683fca30fee887284005238e7fcbc07c Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 1 May 2017 02:23:03 +0100 Subject: [PATCH 02/30] Added repo parsing --- aur/github/github.go | 30 ++++++++++++++++++++++++++++++ aur/github/github_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 aur/github/github.go create mode 100644 aur/github/github_test.go diff --git a/aur/github/github.go b/aur/github/github.go new file mode 100644 index 00000000..b32a942e --- /dev/null +++ b/aur/github/github.go @@ -0,0 +1,30 @@ +package github + +import "strings" + +// Branches contains the information of a repository branch +type Branches []struct { + Name string `json:"name"` + Commit struct { + Sha string `json:"sha"` + URL string `json:"url"` + } `json:"commit"` +} + +const repoAPI = "https://api.github.com/repos/{USER}/{REPOSITORY}/branches" + +func parseSource(source string) (owner string, repo string) { + split := strings.Split(source, "github.com/") + if len(split) > 1 { + secondSplit := strings.Split(split[1], "/") + if len(secondSplit) > 1 { + owner = secondSplit[0] + thirdSplit := strings.Split(secondSplit[1], ".git") + if len(thirdSplit) > 0 { + repo = thirdSplit[0] + } + } + + } + return +} diff --git a/aur/github/github_test.go b/aur/github/github_test.go new file mode 100644 index 00000000..9f2027dc --- /dev/null +++ b/aur/github/github_test.go @@ -0,0 +1,33 @@ +package github + +import ( + "testing" +) + +func TestParsing(t *testing.T) { + type source struct { + sourceurl string + owner string + repo string + } + + neovim := source{sourceurl: "git+https://github.com/neovim/neovim.git"} + neovim.owner, neovim.repo = parseSource(neovim.sourceurl) + + if neovim.owner != "neovim" || neovim.repo != "neovim" { + t.Fatalf("Expected to find neovim/neovim, found %+v/%+v", neovim.owner, neovim.repo) + } + + yay := source{sourceurl: "git://github.com/jguer/yay.git#branch=master"} + yay.owner, yay.repo = parseSource(yay.sourceurl) + if yay.owner != "jguer" || yay.repo != "yay" { + t.Fatalf("Expected to find jguer/yay, found %+v/%+v", yay.owner, yay.repo) + } + + ack := source{sourceurl: "git://github.com/davidgiven/ack"} + ack.owner, ack.repo = parseSource(ack.sourceurl) + if ack.owner != "davidgiven" || ack.repo != "ack" { + t.Fatalf("Expected to find davidgiven/ack, found %+v/%+v", ack.owner, ack.repo) + } + +} From c258986edc495114298c27e751428da2c2cdc9b8 Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 1 May 2017 02:23:26 +0100 Subject: [PATCH 03/30] Simplified code --- aur/query.go | 46 +++++++++++----------------------- pacman/pacman.go | 64 +++++++++--------------------------------------- util/util.go | 24 ++++++++++++++++++ 3 files changed, 50 insertions(+), 84 deletions(-) diff --git a/aur/query.go b/aur/query.go index f6fa08d1..d9aa1dac 100644 --- a/aur/query.go +++ b/aur/query.go @@ -5,13 +5,17 @@ import ( "sort" "strings" - "github.com/jguer/yay/pacman" "github.com/jguer/yay/util" ) // Query is a collection of Results type Query []Result +type returned struct { + Results Query `json:"results"` + ResultCount int `json:"resultcount"` +} + func (q Query) Len() int { return len(q) } @@ -62,10 +66,6 @@ func (q Query) PrintSearch(start int) { // 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) @@ -75,10 +75,6 @@ func Info(pkg string) (Query, int, error) { // 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 @@ -93,18 +89,16 @@ func MultiInfo(pkgS []string) (Query, int, error) { // Search returns an AUR search func Search(pkgS []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="+pkgS[0], &r) var aq Query n := 0 - setter := pacman.PFactory(pFSetTrue) - var fri int + h, _ := util.Conf.CreateHandle() + localDb, _ := h.LocalDb() + + var fri int for _, res := range r.Results { match := true for _, pkgN := range pkgS[1:] { @@ -118,33 +112,21 @@ func Search(pkgS []string, sortS bool) (Query, int, error) { n++ aq = append(aq, res) fri = len(aq) - 1 - setter(aq[fri].Name, &aq[fri], false) + _, err := localDb.PkgByName(res.Name) + if err == nil { + aq[fri].Installed = true + } } } - if aq != nil { - setter(aq[fri].Name, &aq[fri], true) - } - if sortS { sort.Sort(aq) } + h.Release() return aq, n, 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 { diff --git a/pacman/pacman.go b/pacman/pacman.go index 894204bf..9c88cb75 100644 --- a/pacman/pacman.go +++ b/pacman/pacman.go @@ -23,27 +23,6 @@ type Result struct { Installed bool } -// PacmanConf describes the default pacman config file -const PacmanConf string = "/etc/pacman.conf" - -var conf alpm.PacmanConfig - -func init() { - conf, _ = readConfig(PacmanConf) -} - -func readConfig(pacmanconf string) (conf alpm.PacmanConfig, err error) { - file, err := os.Open(pacmanconf) - if err != nil { - return - } - conf, err = alpm.ParseConfig(file) - if err != nil { - return - } - return -} - // UpdatePackages handles cache update and upgrade func UpdatePackages(flags []string) error { args := append([]string{"pacman", "-Syu"}, flags...) @@ -56,7 +35,7 @@ func UpdatePackages(flags []string) error { // Search handles repo searches. Creates a RepoSearch struct. func Search(pkgInputN []string) (s Query, n int, err error) { - h, err := conf.CreateHandle() + h, err := util.Conf.CreateHandle() defer h.Release() if err != nil { } @@ -167,28 +146,9 @@ func (s Query) PrintSearch() { } } -// PFactory execute an action over a series of packages without reopening the handle everytime. -// Everybody told me it wouln't work. It does. It's just not pretty. -// When it worked: https://youtu.be/a4Z5BdEL0Ag?t=1m11s -func PFactory(action func(interface{})) func(name string, object interface{}, rel bool) { - h, _ := conf.CreateHandle() - localDb, _ := h.LocalDb() - - return func(name string, object interface{}, rel bool) { - _, err := localDb.PkgByName(name) - if err == nil { - action(object) - } - - if rel { - h.Release() - } - } -} - // PackageSlices separates an input slice into aur and repo slices func PackageSlices(toCheck []string) (aur []string, repo []string, err error) { - h, err := conf.CreateHandle() + h, err := util.Conf.CreateHandle() defer h.Release() if err != nil { return @@ -226,7 +186,7 @@ func PackageSlices(toCheck []string) (aur []string, repo []string, err error) { // BuildDependencies finds packages, on the second run // compares with a baselist and avoids searching those func BuildDependencies(baselist []string) func(toCheck []string, isBaseList bool, last bool) (repo []string, notFound []string) { - h, _ := conf.CreateHandle() + h, _ := util.Conf.CreateHandle() localDb, _ := h.LocalDb() dbList, _ := h.SyncDbs() @@ -266,7 +226,7 @@ func BuildDependencies(baselist []string) func(toCheck []string, isBaseList bool // DepSatisfier receives a string slice, returns a slice of packages found in // repos and one of packages not found in repos. Leaves out installed packages. func DepSatisfier(toCheck []string) (repo []string, notFound []string, err error) { - h, err := conf.CreateHandle() + h, err := util.Conf.CreateHandle() defer h.Release() if err != nil { return @@ -324,7 +284,7 @@ func CleanRemove(pkgName []string) (err error) { args := []string{"pacman", "-Rnsc"} args = append(args, pkgName...) - args = append(args, "--noconfirm") + args = append(args, "--noutil.Conf.rm") cmd := exec.Command("sudo", args...) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr @@ -337,7 +297,7 @@ func ForeignPackages() (foreign map[string]*struct { Version string Date int64 }, n int, err error) { - h, err := conf.CreateHandle() + h, err := util.Conf.CreateHandle() defer h.Release() if err != nil { return @@ -390,7 +350,7 @@ func Statistics() (info struct { var nPkg int var ePkg int - h, err := conf.CreateHandle() + h, err := util.Conf.CreateHandle() defer h.Release() if err != nil { return @@ -422,7 +382,7 @@ func Statistics() (info struct { // BiggestPackages prints the name of the ten biggest packages in the system. func BiggestPackages() { - h, err := conf.CreateHandle() + h, err := util.Conf.CreateHandle() defer h.Release() if err != nil { return @@ -449,7 +409,7 @@ func BiggestPackages() { // HangingPackages returns a list of packages installed as deps // and unneeded by the system func HangingPackages() (hanging []string, err error) { - h, err := conf.CreateHandle() + h, err := util.Conf.CreateHandle() defer h.Release() if err != nil { return @@ -480,7 +440,7 @@ func HangingPackages() (hanging []string, err error) { // SliceHangingPackages returns a list of packages installed as deps // and unneeded by the system from a provided list of package names. func SliceHangingPackages(pkgS []string) (hanging []string) { - h, err := conf.CreateHandle() + h, err := util.Conf.CreateHandle() defer h.Release() if err != nil { return @@ -517,7 +477,7 @@ big: // GetPkgbuild downloads pkgbuild from the ABS. func GetPkgbuild(pkgN string, path string) (err error) { - h, err := conf.CreateHandle() + h, err := util.Conf.CreateHandle() defer h.Release() if err != nil { return @@ -549,7 +509,7 @@ func GetPkgbuild(pkgN string, path string) (err error) { //CreatePackageList appends Repo packages to completion cache func CreatePackageList(out *os.File) (err error) { - h, err := conf.CreateHandle() + h, err := util.Conf.CreateHandle() defer h.Release() if err != nil { return diff --git a/util/util.go b/util/util.go index 380cfa39..f958774e 100644 --- a/util/util.go +++ b/util/util.go @@ -7,6 +7,8 @@ import ( "os" "os/exec" "strings" + + alpm "github.com/jguer/go-alpm" ) // TarBin describes the default installation point of tar command. @@ -46,6 +48,16 @@ const ( TopDown ) +// PacmanConf describes the default pacman config file +const PacmanConf string = "/etc/pacman.conf" + +// Conf describes the default alpm config +var Conf alpm.PacmanConfig + +func init() { + Conf, _ = readConfig(PacmanConf) +} + // ContinueTask prompts if user wants to continue task. //If NoConfirm is set the action will continue without user input. func ContinueTask(s string, def string) (cont bool) { @@ -149,3 +161,15 @@ func Editor() string { return editor } } + +func readConfig(pacmanconf string) (conf alpm.PacmanConfig, err error) { + file, err := os.Open(pacmanconf) + if err != nil { + return + } + conf, err = alpm.ParseConfig(file) + if err != nil { + return + } + return +} From b58100fcaff1e9c540a2ea8a3b02eb8fc8047a6f Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 1 May 2017 02:34:40 +0100 Subject: [PATCH 04/30] branchInfo added --- aur/github/github.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/aur/github/github.go b/aur/github/github.go index b32a942e..a0534bf3 100644 --- a/aur/github/github.go +++ b/aur/github/github.go @@ -1,9 +1,13 @@ package github -import "strings" +import ( + "encoding/json" + "net/http" + "strings" +) -// Branches contains the information of a repository branch -type Branches []struct { +// Branch contains the information of a repository branch +type Branch struct { Name string `json:"name"` Commit struct { Sha string `json:"sha"` @@ -11,8 +15,6 @@ type Branches []struct { } `json:"commit"` } -const repoAPI = "https://api.github.com/repos/{USER}/{REPOSITORY}/branches" - func parseSource(source string) (owner string, repo string) { split := strings.Split(source, "github.com/") if len(split) > 1 { @@ -28,3 +30,16 @@ func parseSource(source string) (owner string, repo string) { } return } + +func branchInfo(owner string, repo string) (newRepo []Branch, err error) { + url := "https://api.github.com/repos/" + owner + "/" + repo + "/branches" + r, err := http.Get(url) + if err != nil { + return + } + defer r.Body.Close() + + json.NewDecoder(r.Body).Decode(newRepo) + + return +} From 5c0650fe5ab9a97a3e5db653b399e65f6f0a74db Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 2 May 2017 01:06:16 +0100 Subject: [PATCH 05/30] Minor bug fixed in completions. Github updates progressing. Info fetching done --- aur/github/github.go | 77 +++++++++++++++++++++++++++++++++++++++----- utils.go | 2 +- 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/aur/github/github.go b/aur/github/github.go index a0534bf3..6e195c14 100644 --- a/aur/github/github.go +++ b/aur/github/github.go @@ -2,17 +2,49 @@ package github import ( "encoding/json" + "fmt" "net/http" + "os" "strings" ) -// Branch contains the information of a repository branch -type Branch struct { - Name string `json:"name"` - Commit struct { - Sha string `json:"sha"` - URL string `json:"url"` - } `json:"commit"` +// branch contains the information of a repository branch +type branch struct { + Name string `json:"name"` + SHA string `json:"sha"` + URL string `json:"url"` +} + +type branches []branch + +// Info contains the last commit sha of a repo +type Info struct { + Package string `json:"owner"` + Repo string `json:"Repo"` + SHA string `json:"sha"` +} + +type infos []Info + +var savedInfo infos + +func init() { + path := os.Getenv("HOME") + "/.config/yay/yay_github.json" + + if _, err := os.Stat(path); os.IsNotExist(err) { + os.MkdirAll(os.Getenv("HOME")+"/.config/yay/yay_github.json", 0755) + } + + file, err := os.Open(path) + if err != nil { + fmt.Println("error:", err) + return + } + decoder := json.NewDecoder(file) + err = decoder.Decode(&savedInfo) + if err != nil { + fmt.Println("error:", err) + } } func parseSource(source string) (owner string, repo string) { @@ -31,7 +63,22 @@ func parseSource(source string) (owner string, repo string) { return } -func branchInfo(owner string, repo string) (newRepo []Branch, err error) { +func checkUpdates() { + +} + +func inStore(pkgname string) *Info { + for i, e := range savedInfo { + if pkgname == e.Package { + return &savedInfo[i] + } + } + return nil +} + +// BranchInfo updates saved information +func BranchInfo(pkgname string, owner string, repo string) (err error) { + var newRepo branches url := "https://api.github.com/repos/" + owner + "/" + repo + "/branches" r, err := http.Get(url) if err != nil { @@ -41,5 +88,19 @@ func branchInfo(owner string, repo string) (newRepo []Branch, err error) { json.NewDecoder(r.Body).Decode(newRepo) + packinfo := inStore(pkgname) + + for _, e := range newRepo { + if e.Name == "master" { + if packinfo != nil { + packinfo.Package = pkgname + packinfo.Repo = owner + "/" + repo + packinfo.SHA = e.SHA + } else { + savedInfo = append(savedInfo, Info{Package: pkgname, Repo: owner + "/" + repo, SHA: e.SHA}) + } + } + } + return } diff --git a/utils.go b/utils.go index a72984ad..bdbafebb 100644 --- a/utils.go +++ b/utils.go @@ -47,7 +47,7 @@ func Complete() (err error) { path := os.Getenv("HOME") + "/.cache/yay/aur_" + util.Shell + ".cache" if info, err := os.Stat(path); os.IsNotExist(err) || time.Since(info.ModTime()).Hours() > 48 { - os.MkdirAll(os.Getenv("HOME")+"/.cache/yay", 0755) + os.MkdirAll(os.Getenv("HOME")+"/.cache/yay/aur_"+util.Shell+".cache", 0755) out, err := os.Create(path) if err != nil { From 9f781c04118ada731f5c74d9b0ea5cd9137fd212 Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 2 May 2017 11:50:11 +0100 Subject: [PATCH 06/30] Added Save info to vcs --- aur/result.go | 13 +++--- aur/{github => vcs}/github.go | 72 +++++++++++++++++++++++++----- aur/{github => vcs}/github_test.go | 1 - utils.go | 2 +- 4 files changed, 66 insertions(+), 22 deletions(-) rename aur/{github => vcs}/github.go (51%) rename aur/{github => vcs}/github_test.go (99%) diff --git a/aur/result.go b/aur/result.go index 88ee7696..de4019f5 100644 --- a/aur/result.go +++ b/aur/result.go @@ -98,19 +98,16 @@ func (a *Result) Install(flags []string) (finalmdeps []string, err error) { } dir := util.BaseDir + a.PackageBase + "/" - if _, err = os.Stat(dir); os.IsNotExist(err) { - if err = util.DownloadAndUnpack(BaseURL+a.URLPath, util.BaseDir, false); err != nil { - return - } - } else { + if _, err = os.Stat(dir); os.IsExist(err) { if !util.ContinueTask("Directory exists. Clean Build?", "yY") { os.RemoveAll(util.BaseDir + a.PackageBase) - if err = util.DownloadAndUnpack(BaseURL+a.URLPath, util.BaseDir, false); err != nil { - return - } } } + if err = util.DownloadAndUnpack(BaseURL+a.URLPath, util.BaseDir, false); err != nil { + return + } + if !util.ContinueTask("Edit PKGBUILD?", "yY") { editcmd := exec.Command(util.Editor(), dir+"PKGBUILD") editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr diff --git a/aur/github/github.go b/aur/vcs/github.go similarity index 51% rename from aur/github/github.go rename to aur/vcs/github.go index 6e195c14..036e0285 100644 --- a/aur/github/github.go +++ b/aur/vcs/github.go @@ -19,23 +19,24 @@ type branches []branch // Info contains the last commit sha of a repo type Info struct { - Package string `json:"owner"` - Repo string `json:"Repo"` + Package string `json:"pkgname"` + URL string `json:"url"` SHA string `json:"sha"` } type infos []Info var savedInfo infos +var configfile string func init() { - path := os.Getenv("HOME") + "/.config/yay/yay_github.json" + configfile = os.Getenv("HOME") + "/.config/yay/yay_vcs.json" - if _, err := os.Stat(path); os.IsNotExist(err) { - os.MkdirAll(os.Getenv("HOME")+"/.config/yay/yay_github.json", 0755) + if _, err := os.Stat(configfile); os.IsNotExist(err) { + _ = os.MkdirAll(os.Getenv("HOME")+"/.config/yay", 0755) } - file, err := os.Open(path) + file, err := os.Open(configfile) if err != nil { fmt.Println("error:", err) return @@ -47,7 +48,8 @@ func init() { } } -func parseSource(source string) (owner string, repo string) { +// ParseSource returns owner and repo from source +func ParseSource(source string) (owner string, repo string) { split := strings.Split(source, "github.com/") if len(split) > 1 { secondSplit := strings.Split(split[1], "/") @@ -58,13 +60,44 @@ func parseSource(source string) (owner string, repo string) { repo = thirdSplit[0] } } - } return } -func checkUpdates() { +func (info *Info) needsUpdate() bool { + var newRepo branches + r, err := http.Get(info.URL) + if err != nil { + fmt.Println(err) + return false + } + defer r.Body.Close() + err = json.NewDecoder(r.Body).Decode(&newRepo) + if err != nil { + fmt.Println(err) + return false + } + + for _, e := range newRepo { + if e.Name == "master" { + if e.SHA != info.SHA { + return true + } else { + return false + } + } + } + return false +} + +func CheckUpdates() (toUpdate []string) { + for _, e := range savedInfo { + if e.needsUpdate() { + toUpdate = append(toUpdate, e.Package) + } + } + return } func inStore(pkgname string) *Info { @@ -86,7 +119,7 @@ func BranchInfo(pkgname string, owner string, repo string) (err error) { } defer r.Body.Close() - json.NewDecoder(r.Body).Decode(newRepo) + _ = json.NewDecoder(r.Body).Decode(&newRepo) packinfo := inStore(pkgname) @@ -94,13 +127,28 @@ func BranchInfo(pkgname string, owner string, repo string) (err error) { if e.Name == "master" { if packinfo != nil { packinfo.Package = pkgname - packinfo.Repo = owner + "/" + repo + packinfo.URL = url packinfo.SHA = e.SHA } else { - savedInfo = append(savedInfo, Info{Package: pkgname, Repo: owner + "/" + repo, SHA: e.SHA}) + savedInfo = append(savedInfo, Info{Package: pkgname, URL: url, SHA: e.SHA}) } } } return } + +func SaveBranchInfo() error { + marshalledinfo, _ := json.Marshal(savedInfo) + in, err := os.OpenFile(configfile, os.O_RDWR|os.O_CREATE, 0755) + if err != nil { + return err + } + defer in.Close() + _, err = in.Write(marshalledinfo) + if err != nil { + return err + } + err = in.Sync() + return err +} diff --git a/aur/github/github_test.go b/aur/vcs/github_test.go similarity index 99% rename from aur/github/github_test.go rename to aur/vcs/github_test.go index 9f2027dc..9895602d 100644 --- a/aur/github/github_test.go +++ b/aur/vcs/github_test.go @@ -29,5 +29,4 @@ func TestParsing(t *testing.T) { if ack.owner != "davidgiven" || ack.repo != "ack" { t.Fatalf("Expected to find davidgiven/ack, found %+v/%+v", ack.owner, ack.repo) } - } diff --git a/utils.go b/utils.go index bdbafebb..4952a5bc 100644 --- a/utils.go +++ b/utils.go @@ -47,7 +47,7 @@ func Complete() (err error) { path := os.Getenv("HOME") + "/.cache/yay/aur_" + util.Shell + ".cache" if info, err := os.Stat(path); os.IsNotExist(err) || time.Since(info.ModTime()).Hours() > 48 { - os.MkdirAll(os.Getenv("HOME")+"/.cache/yay/aur_"+util.Shell+".cache", 0755) + os.MkdirAll(os.Getenv("HOME")+"/.cache/yay/", 0755) out, err := os.Create(path) if err != nil { From 9b4667344e9c17fb591e7ef2b0e85c4e614b92bb Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 2 May 2017 16:46:14 +0100 Subject: [PATCH 07/30] Refactored yay to use mikkeloscars aur package --- actions.go | 28 +++---------- aur/aur.go | 74 ++++++++++++++++++++++++++++----- aur/aur_test.go | 87 -------------------------------------- aur/query.go | 108 ++---------------------------------------------- aur/result.go | 60 ++++++++------------------- query.go | 61 ++++++++++++++++++++++----- utils.go | 4 +- yay.go | 48 +++++++-------------- 8 files changed, 158 insertions(+), 312 deletions(-) delete mode 100644 aur/aur_test.go diff --git a/actions.go b/actions.go index a2ac4dc0..21b6aeb6 100644 --- a/actions.go +++ b/actions.go @@ -10,7 +10,7 @@ import ( ) // Install handles package installs -func Install(pkgs []string, flags []string) error { +func install(pkgs []string, flags []string) error { aurs, repos, _ := pac.PackageSlices(pkgs) err := pac.Install(repos, flags) @@ -18,29 +18,13 @@ func Install(pkgs []string, flags []string) error { fmt.Println("Error installing repo packages.") } - q, n, err := aur.MultiInfo(aurs) - if len(aurs) != n || err != nil { - fmt.Println("Unable to get info on some packages") - } + err = aur.Install(aurs, flags) - var finalrm []string - for _, aurpkg := range q { - finalmdeps, err := aurpkg.Install(flags) - finalrm = append(finalrm, finalmdeps...) - if err != nil { - fmt.Println("Error installing", aurpkg.Name, ":", err) - } - } - - if len(finalrm) != 0 { - aur.RemoveMakeDeps(finalrm) - } - - return nil + return err } // Upgrade handles updating the cache and installing updates. -func Upgrade(flags []string) error { +func upgrade(flags []string) error { errp := pac.UpdatePackages(flags) erra := aur.Upgrade(flags) @@ -52,7 +36,7 @@ func Upgrade(flags []string) error { } // CleanDependencies removels all dangling dependencies in system -func CleanDependencies(pkgs []string) error { +func cleanDependencies(pkgs []string) error { hanging, err := pac.HangingPackages() if err != nil { return err @@ -69,7 +53,7 @@ func CleanDependencies(pkgs []string) error { } // GetPkgbuild gets the pkgbuild of the package 'pkg' trying the ABS first and then the AUR trying the ABS first and then the AUR. -func GetPkgbuild(pkg string) (err error) { +func getPkgbuild(pkg string) (err error) { wd, err := os.Getwd() if err != nil { return diff --git a/aur/aur.go b/aur/aur.go index bcb41620..d4c0bde2 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -5,23 +5,75 @@ import ( "fmt" "net/http" "os" + "sort" + "strings" "github.com/jguer/yay/pacman" "github.com/jguer/yay/util" + rpc "github.com/mikkeloscar/aur" ) +// NarrowSearch searches AUR and narrows based on subarguments +func NarrowSearch(pkgS []string, sortS bool) (Query, error) { + if len(pkgS) == 0 { + return nil, nil + } + + r, err := rpc.Search(pkgS[0]) + + if len(pkgS) == 1 { + return r, err + } + + var aq Query + var n int = 0 + + for _, res := range r { + match := true + for _, pkgN := range pkgS[1:] { + if !(strings.Contains(res.Name, pkgN) || strings.Contains(strings.ToLower(res.Description), pkgN)) { + match = false + break + } + } + + if match { + n++ + aq = append(aq, res) + } + } + + if sortS { + sort.Sort(aq) + } + + return aq, 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) +func Install(pkgName []string, flags []string) (err error) { + q, err := rpc.Info(pkgName) if err != nil { return } - if n == 0 { - return fmt.Errorf("Package %s does not exist", pkg) + if len(q) != len(pkgName) { + return fmt.Errorf("Some package from list\n%+v\ndoes not exist", pkgName) + } + + var finalrm []string + for _, i := range q { + mrm, err := PkgInstall(&i, flags) + if err != nil { + fmt.Println("Error installing", i.Name, ":", err) + } + finalrm = append(finalrm, mrm...) + } + + if len(finalrm) != 0 { + err = RemoveMakeDeps(finalrm) } - q[0].Install(flags) return err } @@ -41,7 +93,7 @@ func Upgrade(flags []string) error { i++ } - q, _, err := MultiInfo(keys) + q, err := rpc.Info(keys) if err != nil { return err } @@ -50,7 +102,7 @@ func Upgrade(flags []string) error { for _, res := range q { if _, ok := foreign[res.Name]; ok { // Leaving this here for now, warn about downgrades later - if res.LastModified > foreign[res.Name].Date { + if res.LastModified > int(foreign[res.Name].Date) { fmt.Printf("\x1b[1m\x1b[32m==>\x1b[33;1m %s: \x1b[0m%s \x1b[33;1m-> \x1b[0m%s\n", res.Name, foreign[res.Name].Version, res.Version) outdated = append(outdated, res) @@ -69,8 +121,8 @@ func Upgrade(flags []string) error { return nil } - for _, pkg := range outdated { - pkg.Install(flags) + for _, pkgi := range outdated { + PkgInstall(&pkgi, flags) } return nil @@ -78,12 +130,12 @@ func Upgrade(flags []string) error { // GetPkgbuild downloads pkgbuild from the AUR. func GetPkgbuild(pkgN string, dir string) (err error) { - aq, numaq, err := Info(pkgN) + aq, err := rpc.Info([]string{pkgN}) if err != nil { return err } - if numaq == 0 { + if len(aq) == 0 { return fmt.Errorf("no results") } diff --git a/aur/aur_test.go b/aur/aur_test.go deleted file mode 100644 index edae5abb..00000000 --- a/aur/aur_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package aur - -import ( - "os" - "reflect" - "testing" -) - -func TestSearch(t *testing.T) { - - eN := "yay" - result, _, err := Search([]string{"yay"}, true) - if err != nil { - t.Fatalf("Expected err to be nil but it was %s", err) - } - - // t.Logf("Got struct: %+v", result) - found := false - for _, v := range result { - if v.Name == eN { - found = true - } - } - - if !found { - t.Fatalf("Expected to find yay, found %+v", result) - } -} - -func benchmarkSearch(search string, sort bool, b *testing.B) { - - for n := 0; n < b.N; n++ { - Search([]string{search}, sort) - } -} - -func BenchmarkSearchSimpleNoSort(b *testing.B) { benchmarkSearch("yay", false, b) } -func BenchmarkSearchComplexNoSort(b *testing.B) { benchmarkSearch("linux", false, b) } -func BenchmarkSearchSimpleSorted(b *testing.B) { benchmarkSearch("yay", true, b) } -func BenchmarkSearchComplexSorted(b *testing.B) { benchmarkSearch("linux", true, b) } - -func TestInfo(t *testing.T) { - - eN := "yay" - eM := []string{"go", "git"} - result, _, err := Info("yay") - if err != nil { - t.Fatalf("Expected err to be nil but it was %s", err) - } - - // t.Logf("Got struct: %+v", result) - found := false - for _, v := range result { - if v.Name == eN && reflect.DeepEqual(v.MakeDepends, eM) { - found = true - } - } - - if !found { - t.Fatalf("Expected to find yay, found %+v", result) - } -} - -func TestUpgrade(t *testing.T) { - old := os.Stdout - _, w, _ := os.Pipe() - os.Stdout = w - - err := Upgrade([]string{}) - if err != nil { - t.Fatalf("Expected err to be nil but it was %s", err) - } - - os.Stdout = old -} - -func BenchmarkUpgrade(b *testing.B) { - old := os.Stdout - _, w, _ := os.Pipe() - os.Stdout = w - - for n := 0; n < b.N; n++ { - Upgrade([]string{}) - } - - os.Stdout = old -} diff --git a/aur/query.go b/aur/query.go index d9aa1dac..077c4ee4 100644 --- a/aur/query.go +++ b/aur/query.go @@ -2,19 +2,15 @@ package aur import ( "fmt" - "sort" - "strings" "github.com/jguer/yay/util" + rpc "github.com/mikkeloscar/aur" ) -// Query is a collection of Results -type Query []Result +const aurURL = "https://aur.archlinux.org/rpc/?" -type returned struct { - Results Query `json:"results"` - ResultCount int `json:"resultcount"` -} +// Query is a collection of Results +type Query []rpc.Pkg func (q Query) Len() int { return len(q) @@ -31,102 +27,6 @@ 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 util.SearchVerbosity == util.NumberMenu { - if util.SortMode == util.BottomUp { - toprint += fmt.Sprintf("%d ", len(q)+start-i-1) - } else { - toprint += fmt.Sprintf("%d ", start+i) - } - } else if util.SearchVerbosity == util.Minimal { - fmt.Println(res.Name) - continue - } - 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) - } - - return -} - -// Info returns an AUR search with package details -func Info(pkg string) (Query, int, error) { - 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) { - 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(pkgS []string, sortS bool) (Query, int, error) { - r := returned{} - err := getJSON("https://aur.archlinux.org/rpc/?v=5&type=search&arg="+pkgS[0], &r) - - var aq Query - n := 0 - - h, _ := util.Conf.CreateHandle() - localDb, _ := h.LocalDb() - - var fri int - for _, res := range r.Results { - match := true - for _, pkgN := range pkgS[1:] { - if !(strings.Contains(res.Name, pkgN) || strings.Contains(strings.ToLower(res.Description), pkgN)) { - match = false - break - } - } - - if match { - n++ - aq = append(aq, res) - fri = len(aq) - 1 - _, err := localDb.PkgByName(res.Name) - if err == nil { - aq[fri].Installed = true - } - } - } - - if sortS { - sort.Sort(aq) - } - - h.Release() - return aq, n, err -} - // MissingPackage warns if the Query was unable to find a package func (q Query) MissingPackage(pkgS []string) { for _, depName := range pkgS { diff --git a/aur/result.go b/aur/result.go index de4019f5..7ae6bbdc 100644 --- a/aur/result.go +++ b/aur/result.go @@ -7,42 +7,16 @@ import ( "github.com/jguer/yay/pacman" "github.com/jguer/yay/util" + rpc "github.com/mikkeloscar/aur" ) -// Result describes an AUR package. -type Result struct { - Conflicts []string `json:"Conflicts"` - Depends []string `json:"Depends"` - Description string `json:"Description"` - FirstSubmitted int `json:"FirstSubmitted"` - ID int `json:"ID"` - Keywords []string `json:"Keywords"` - LastModified int64 `json:"LastModified"` - License []string `json:"License"` - Maintainer string `json:"Maintainer"` - MakeDepends []string `json:"MakeDepends"` - Name string `json:"Name"` - NumVotes int `json:"NumVotes"` - OptDepends []string `json:"OptDepends"` - OutOfDate int `json:"OutOfDate"` - PackageBase string `json:"PackageBase"` - PackageBaseID int `json:"PackageBaseID"` - Provides []string `json:"Provides"` - URL string `json:"URL"` - URLPath string `json:"URLPath"` - Version string `json:"Version"` - Installed bool - Popularity float32 `json:"Popularity"` -} - // 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) { +func PkgDependencies(a *rpc.Pkg) (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 { + q, err = rpc.Info([]string{a.Name}) + if len(q) == 0 || err != nil { err = fmt.Errorf("Unable to search dependencies, %s", err) return } @@ -91,7 +65,7 @@ func printDeps(repoDeps []string, aurDeps []string) { } // Install handles install from Info Result. -func (a *Result) Install(flags []string) (finalmdeps []string, err error) { +func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []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") @@ -100,7 +74,7 @@ func (a *Result) Install(flags []string) (finalmdeps []string, err error) { if _, err = os.Stat(dir); os.IsExist(err) { if !util.ContinueTask("Directory exists. Clean Build?", "yY") { - os.RemoveAll(util.BaseDir + a.PackageBase) + _ = os.RemoveAll(util.BaseDir + a.PackageBase) } } @@ -114,7 +88,7 @@ func (a *Result) Install(flags []string) (finalmdeps []string, err error) { editcmd.Run() } - runDeps, makeDeps, err := a.Dependencies() + runDeps, makeDeps, err := PkgDependencies(a) if err != nil { return } @@ -130,9 +104,9 @@ func (a *Result) Install(flags []string) (finalmdeps []string, err error) { } } - aurQ, n, _ := MultiInfo(aurDeps) - if n != len(aurDeps) { - aurQ.MissingPackage(aurDeps) + aurQ, _ := rpc.Info(aurDeps) + if len(aurQ) != len(aurDeps) { + (Query)(aurQ).MissingPackage(aurDeps) if !util.ContinueTask("Continue?", "nN") { return finalmdeps, fmt.Errorf("unable to install dependencies") } @@ -154,7 +128,7 @@ func (a *Result) Install(flags []string) (finalmdeps []string, err error) { // Handle AUR dependencies for _, dep := range aurQ { - finalmdepsR, errA := dep.Install(depArgs) + finalmdepsR, errA := PkgInstall(&dep, depArgs) finalmdeps = append(finalmdeps, finalmdepsR...) if errA != nil { @@ -178,7 +152,7 @@ func (a *Result) Install(flags []string) (finalmdeps []string, err error) { } // PrintInfo prints package info like pacman -Si. -func (a *Result) PrintInfo() { +func AURPrintInfo(a *rpc.Pkg) { 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) @@ -190,11 +164,11 @@ func (a *Result) PrintInfo() { } 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.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) diff --git a/query.go b/query.go index c9752264..06a422c5 100644 --- a/query.go +++ b/query.go @@ -6,11 +6,52 @@ import ( "github.com/jguer/yay/aur" pac "github.com/jguer/yay/pacman" "github.com/jguer/yay/util" + rpc "github.com/mikkeloscar/aur" ) +// PrintSearch handles printing search results in a given format +func printAURSearch(q aur.Query, start int) { + h, err := util.Conf.CreateHandle() + defer h.Release() + if err != nil { + } + + localDb, _ := h.LocalDb() + + for i, res := range q { + var toprint string + if util.SearchVerbosity == util.NumberMenu { + if util.SortMode == util.BottomUp { + toprint += fmt.Sprintf("%d ", len(q)+start-i-1) + } else { + toprint += fmt.Sprintf("%d ", start+i) + } + } else if util.SearchVerbosity == util.Minimal { + fmt.Println(res.Name) + continue + } + 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 _, err := localDb.PkgByName(res.Name); err == nil { + toprint += fmt.Sprintf("\x1b[32;40mInstalled\x1b[0m") + } + toprint += "\n" + res.Description + fmt.Println(toprint) + } + + return +} + // SyncSearch presents a query to the local repos and to the AUR. -func SyncSearch(pkgS []string) (err error) { - aq, _, err := aur.Search(pkgS, true) +func syncSearch(pkgS []string) (err error) { + aq, err := aur.NarrowSearch(pkgS, true) if err != nil { return err } @@ -20,41 +61,41 @@ func SyncSearch(pkgS []string) (err error) { } if util.SortMode == util.BottomUp { - aq.PrintSearch(0) + printAURSearch(aq, 0) pq.PrintSearch() } else { pq.PrintSearch() - aq.PrintSearch(0) + printAURSearch(aq, 0) } return nil } // SyncInfo serves as a pacman -Si for repo packages and AUR packages. -func SyncInfo(pkgS []string, flags []string) (err error) { +func syncInfo(pkgS []string, flags []string) (err error) { aurS, repoS, err := pac.PackageSlices(pkgS) if err != nil { return } - q, _, err := aur.MultiInfo(aurS) + q, err := rpc.Info(aurS) if err != nil { fmt.Println(err) } for _, aurP := range q { - aurP.PrintInfo() + aur.AURPrintInfo(&aurP) } if len(repoS) != 0 { - err = PassToPacman("-Si", repoS, flags) + err = passToPacman("-Si", repoS, flags) } return } // LocalStatistics returns installed packages statistics. -func LocalStatistics(version string) error { +func localStatistics(version string) error { info, err := pac.Statistics() if err != nil { return err @@ -79,7 +120,7 @@ func LocalStatistics(version string) error { keys[i] = k i++ } - q, _, err := aur.MultiInfo(keys) + q, err := rpc.Info(keys) if err != nil { return err } diff --git a/utils.go b/utils.go index 4952a5bc..1912ed16 100644 --- a/utils.go +++ b/utils.go @@ -15,7 +15,7 @@ import ( ) // PassToPacman outsorces execution to pacman binary without modifications. -func PassToPacman(op string, pkgs []string, flags []string) error { +func passToPacman(op string, pkgs []string, flags []string) error { var cmd *exec.Cmd var args []string @@ -43,7 +43,7 @@ func PassToPacman(op string, pkgs []string, flags []string) error { } // Complete provides completion info for shells -func Complete() (err error) { +func complete() (err error) { path := os.Getenv("HOME") + "/.cache/yay/aur_" + util.Shell + ".cache" if info, err := os.Stat(path); os.IsNotExist(err) || time.Since(info.ModTime()).Hours() > 48 { diff --git a/yay.go b/yay.go index fb1a1ea1..c7c61790 100644 --- a/yay.go +++ b/yay.go @@ -68,11 +68,11 @@ func parser() (op string, options []string, packages []string, err error) { case "--complete": util.Shell = "sh" - Complete() + complete() os.Exit(0) case "--fcomplete": util.Shell = "fish" - Complete() + complete() os.Exit(0) case "--help": usage() @@ -100,16 +100,16 @@ func main() { switch op { case "-Cd": - err = CleanDependencies(pkgs) + err = cleanDependencies(pkgs) case "-G": for _, pkg := range pkgs { - err = GetPkgbuild(pkg) + err = getPkgbuild(pkg) if err != nil { fmt.Println(pkg+":", err) } } case "-Qstats": - err = LocalStatistics(version) + err = localStatistics(version) case "-Ss", "-Ssq", "-Sqs": if op == "-Ss" { util.SearchVerbosity = util.Detailed @@ -118,14 +118,14 @@ func main() { } if pkgs != nil { - err = SyncSearch(pkgs) + err = syncSearch(pkgs) } case "-S": - err = Install(pkgs, options) + err = install(pkgs, options) case "-Syu", "-Suy": - err = Upgrade(options) + err = upgrade(options) case "-Si": - err = SyncInfo(pkgs, options) + err = syncInfo(pkgs, options) case "yogurt": util.SearchVerbosity = util.NumberMenu @@ -133,7 +133,7 @@ func main() { err = numberMenu(pkgs, options) } default: - err = PassToPacman(op, pkgs, options) + err = passToPacman(op, pkgs, options) } if err != nil { @@ -146,10 +146,11 @@ func main() { func numberMenu(pkgS []string, flags []string) (err error) { var num int - aq, numaq, err := aur.Search(pkgS, true) + aq, err := aur.NarrowSearch(pkgS, true) if err != nil { fmt.Println("Error during AUR search:", err) } + numaq := len(aq) pq, numpq, err := pac.Search(pkgS) if err != nil { return @@ -160,11 +161,11 @@ func numberMenu(pkgS []string, flags []string) (err error) { } if util.SortMode == util.BottomUp { - aq.PrintSearch(numpq) + printAURSearch(aq, numpq) pq.PrintSearch() } else { pq.PrintSearch() - aq.PrintSearch(numpq) + printAURSearch(aq, numpq) } fmt.Printf("\x1b[32m%s\x1b[0m\nNumbers:", "Type numbers to install. Separate each number with a space.") @@ -208,26 +209,7 @@ func numberMenu(pkgS []string, flags []string) (err error) { } if len(aurInstall) != 0 { - q, n, err := aur.MultiInfo(aurInstall) - if err != nil { - return err - } else if n != len(aurInstall) { - q.MissingPackage(aurInstall) - } - - var finalrm []string - for _, aurpkg := range q { - finalmdeps, err := aurpkg.Install(flags) - finalrm = append(finalrm, finalmdeps...) - if err != nil { - // Do not abandon program, we might still be able to install the rest - fmt.Println(err) - } - } - - if len(finalrm) != 0 { - aur.RemoveMakeDeps(finalrm) - } + aur.Install(aurInstall, flags) } return nil From 484eb3b75f7b679f75b25c5949d0d436eca97d38 Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 2 May 2017 16:59:30 +0100 Subject: [PATCH 08/30] Fixed sorting issue in improved Narrow Search --- aur/aur.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aur/aur.go b/aur/aur.go index d4c0bde2..4ab0233d 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -22,6 +22,9 @@ func NarrowSearch(pkgS []string, sortS bool) (Query, error) { r, err := rpc.Search(pkgS[0]) if len(pkgS) == 1 { + if sortS { + sort.Sort(Query(r)) + } return r, err } From a91984045c51adaa90a204885b49cac6fd47b7ef Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 2 May 2017 17:32:50 +0100 Subject: [PATCH 09/30] Refactored AUR package --- aur/aur.go | 3 +++ aur/query.go | 2 -- aur/utils.go | 20 -------------------- 3 files changed, 3 insertions(+), 22 deletions(-) delete mode 100644 aur/utils.go diff --git a/aur/aur.go b/aur/aur.go index 4ab0233d..094df781 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -13,6 +13,9 @@ import ( rpc "github.com/mikkeloscar/aur" ) +// BaseURL givers the AUR default address. +const BaseURL string = "https://aur.archlinux.org" + // NarrowSearch searches AUR and narrows based on subarguments func NarrowSearch(pkgS []string, sortS bool) (Query, error) { if len(pkgS) == 0 { diff --git a/aur/query.go b/aur/query.go index 077c4ee4..45ee406c 100644 --- a/aur/query.go +++ b/aur/query.go @@ -7,8 +7,6 @@ import ( rpc "github.com/mikkeloscar/aur" ) -const aurURL = "https://aur.archlinux.org/rpc/?" - // Query is a collection of Results type Query []rpc.Pkg diff --git a/aur/utils.go b/aur/utils.go deleted file mode 100644 index 4b77206d..00000000 --- a/aur/utils.go +++ /dev/null @@ -1,20 +0,0 @@ -package aur - -import ( - "encoding/json" - "net/http" -) - -// BaseURL givers the AUR default address. -const BaseURL string = "https://aur.archlinux.org" - -// 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) -} From c1eb116c533af094edace57b353bf37cd9eadfc6 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sat, 6 May 2017 16:05:55 +0100 Subject: [PATCH 10/30] Fixes #20 --- aur/aur.go | 5 ++++- util/util.go | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/aur/aur.go b/aur/aur.go index 094df781..db855f94 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -23,6 +23,9 @@ func NarrowSearch(pkgS []string, sortS bool) (Query, error) { } r, err := rpc.Search(pkgS[0]) + if err != nil { + return nil, err + } if len(pkgS) == 1 { if sortS { @@ -32,7 +35,7 @@ func NarrowSearch(pkgS []string, sortS bool) (Query, error) { } var aq Query - var n int = 0 + var n int for _, res := range r { match := true diff --git a/util/util.go b/util/util.go index f958774e..19044687 100644 --- a/util/util.go +++ b/util/util.go @@ -67,13 +67,13 @@ func ContinueTask(s string, def string) (cont bool) { var postFix string if def == "nN" { - postFix = "(Y/n)" + postFix = "[Y/n] " } else { - postFix = "(y/N)" + postFix = "[y/N] " } var response string - fmt.Printf("\x1b[1;32m==> %s\x1b[1;37m %s\x1b[0m\n", s, postFix) + fmt.Printf("\x1b[1;32m==> %s\x1b[1;37m %s\x1b[0m", s, postFix) fmt.Scanln(&response) if response == string(def[0]) || response == string(def[1]) { From 9ca98f798102753dc34db9c756b7cbeaf9665e26 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sat, 6 May 2017 17:34:40 +0100 Subject: [PATCH 11/30] Transfer a lot of functions to Config. Establish global handle --- config/config.go | 211 +++++++++++++++++++++++++++++++++++++++++++++++ util/util.go | 149 --------------------------------- utils.go | 4 +- 3 files changed, 212 insertions(+), 152 deletions(-) create mode 100644 config/config.go diff --git a/config/config.go b/config/config.go new file mode 100644 index 00000000..48927624 --- /dev/null +++ b/config/config.go @@ -0,0 +1,211 @@ +package config + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "os/exec" + "strings" + + alpm "github.com/jguer/go-alpm" +) + +// Configuration stores yay's config +type Configuration struct { + BuildDir string + Editor string + MakepkgBin string + NoConfirm bool + PacmanBin string + PacmanConf string + SortMode string + TarBin string +} + +// YayConf holds the current config values for yay. +var YayConf Configuration + +// AlpmConf holds the current config values for pacman. +var AlpmConf alpm.PacmanConfig + +// AlpmHandle is the alpm handle used by yay +var AlpmHandle alpm.Handle + +func init() { + configfile := os.Getenv("HOME") + "/.config/yay/config.json" + + if _, err := os.Stat(configfile); os.IsNotExist(err) { + _ = os.MkdirAll(os.Getenv("HOME")+"/.config/yay", 0755) + } + + file, err := os.Open(configfile) + if err != nil { + fmt.Println("Error reading config:", err) + return + } + + decoder := json.NewDecoder(file) + err = decoder.Decode(&YayConf) + if err != nil { + fmt.Println("Error reading config:", err) + } + + AlpmConf, err = readAlpmConfig(YayConf.PacmanConf) + if err != nil { + fmt.Println("Unable to read Pacman conf", err) + } +} + +func readAlpmConfig(pacmanconf string) (conf alpm.PacmanConfig, err error) { + file, err := os.Open(pacmanconf) + if err != nil { + return + } + conf, err = alpm.ParseConfig(file) + if err != nil { + return + } + return +} + +func defaultSettings(config *Configuration) { + config.BuildDir = "/tmp/yaytmp/" + config.Editor = "" + config.MakepkgBin = "/usr/bin/makepkg" + config.NoConfirm = false + config.PacmanBin = "/usr/bin/pacman" + config.PacmanConf = "/etc/pacman.conf" + config.SortMode = "BottomUp" + config.TarBin = "/usr/bin/bsdtar" +} + +// Editor returns the preferred system editor. +func Editor() string { + switch { + case YayConf.Editor != "": + editor, err := exec.LookPath(YayConf.Editor) + if err != nil { + fmt.Println(err) + } else { + return editor + } + fallthrough + case os.Getenv("EDITOR") != "": + editor, err := exec.LookPath(os.Getenv("EDITOR")) + if err != nil { + fmt.Println(err) + } else { + return editor + } + fallthrough + case os.Getenv("VISUAL") != "": + editor, err := exec.LookPath(os.Getenv("VISUAL")) + if err != nil { + fmt.Println(err) + } else { + return editor + } + fallthrough + default: + fmt.Printf("\x1b[1;31;40mWarning: \x1B[1;33;40m$EDITOR\x1b[0;37;40m is not set.\x1b[0m\nPlease add $EDITOR or to your environment variables.\n") + + editorLoop: + fmt.Printf("\x1b[32m%s\x1b[0m ", "Edit PKGBUILD with:") + var editorInput string + _, err := fmt.Scanln(&editorInput) + if err != nil { + fmt.Println(err) + goto editorLoop + } + + editor, err := exec.LookPath(editorInput) + if err != nil { + fmt.Println(err) + goto editorLoop + } + return editor + } +} + +// ContinueTask prompts if user wants to continue task. +//If NoConfirm is set the action will continue without user input. +func ContinueTask(s string, def string) (cont bool) { + if YayConf.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", s, postFix) + + n, err := fmt.Scanln(&response) + if err != nil || n == 0 { + return true + } + + if response == string(def[0]) || response == string(def[1]) { + return false + } + + return true +} + +func downloadFile(path string, url string) (err error) { + // Create the file + out, err := os.Create(path) + 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) + return err +} + +// DownloadAndUnpack downloads url tgz and extracts to path. +func DownloadAndUnpack(url string, path string, trim bool) (err error) { + err = os.MkdirAll(path, 0755) + if err != nil { + return + } + + tokens := strings.Split(url, "/") + fileName := tokens[len(tokens)-1] + + tarLocation := path + fileName + defer os.Remove(tarLocation) + + err = downloadFile(tarLocation, url) + if err != nil { + return + } + + if trim { + err = exec.Command("/bin/sh", "-c", + YayConf.TarBin+" --strip-components 2 --include='*/"+fileName[:len(fileName)-7]+"/trunk/' -xf "+tarLocation+" -C "+path).Run() + os.Rename(path+"trunk", path+fileName[:len(fileName)-7]) // kurwa + } else { + err = exec.Command(YayConf.TarBin, "-xf", tarLocation, "-C", path).Run() + } + if err != nil { + return + } + + return +} diff --git a/util/util.go b/util/util.go index 19044687..79fc4ebe 100644 --- a/util/util.go +++ b/util/util.go @@ -1,22 +1,5 @@ package util -import ( - "fmt" - "io" - "net/http" - "os" - "os/exec" - "strings" - - alpm "github.com/jguer/go-alpm" -) - -// TarBin describes the default installation point of tar command. -const TarBin string = "/usr/bin/bsdtar" - -// MakepkgBin describes the default installation point of makepkg command. -const MakepkgBin string = "/usr/bin/makepkg" - // SearchVerbosity determines print method used in PrintSearch var SearchVerbosity = NumberMenu @@ -27,9 +10,6 @@ const ( Minimal ) -// Shell describes the default user shell -var Shell = "fish" - // Build controls if packages will be built from ABS. var Build = false @@ -39,137 +19,8 @@ var NoConfirm = false // SortMode determines top down package or down top package display var SortMode = BottomUp -// BaseDir is the default building directory for yay -var BaseDir = "/tmp/yaytmp/" - // Describes Sorting method for numberdisplay const ( BottomUp = iota TopDown ) - -// PacmanConf describes the default pacman config file -const PacmanConf string = "/etc/pacman.conf" - -// Conf describes the default alpm config -var Conf alpm.PacmanConfig - -func init() { - Conf, _ = readConfig(PacmanConf) -} - -// ContinueTask prompts if user wants to continue task. -//If NoConfirm is set the action will continue without user input. -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", s, postFix) - - fmt.Scanln(&response) - if response == string(def[0]) || response == string(def[1]) { - return false - } - - return true -} - -func downloadFile(path string, url string) (err error) { - // Create the file - out, err := os.Create(path) - 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) - return err -} - -// DownloadAndUnpack downloads url tgz and extracts to path. -func DownloadAndUnpack(url string, path string, trim bool) (err error) { - err = os.MkdirAll(path, 0755) - if err != nil { - return - } - - tokens := strings.Split(url, "/") - fileName := tokens[len(tokens)-1] - - tarLocation := path + fileName - defer os.Remove(tarLocation) - - err = downloadFile(tarLocation, url) - if err != nil { - return - } - - if trim { - err = exec.Command("/bin/sh", "-c", - TarBin+" --strip-components 2 --include='*/"+fileName[:len(fileName)-7]+"/trunk/' -xf "+tarLocation+" -C "+path).Run() - os.Rename(path+"trunk", path+fileName[:len(fileName)-7]) // kurwa - } else { - err = exec.Command(TarBin, "-xf", tarLocation, "-C", path).Run() - } - if err != nil { - return - } - - return -} - -// Editor returns the preferred system editor. -func Editor() string { - if os.Getenv("EDITOR") != "" { - return os.Getenv("EDITOR") - } else if os.Getenv("VISUAL") != "" { - return os.Getenv("VISUAL") - } else { - fmt.Printf("\x1b[1;31;40mWarning: \x1B[1;33;40m$EDITOR\x1b[0;37;40m is not set.\x1b[0m\nPlease add $EDITOR or to your environment variables.\n") - - editorLoop: - fmt.Printf("\x1b[32m%s\x1b[0m ", "Edit PKGBUILD with:") - var editorInput string - _, err := fmt.Scanln(&editorInput) - if err != nil { - fmt.Println(err) - goto editorLoop - } - - editor, err := exec.LookPath(editorInput) - if err != nil { - fmt.Println(err) - goto editorLoop - } - return editor - } -} - -func readConfig(pacmanconf string) (conf alpm.PacmanConfig, err error) { - file, err := os.Open(pacmanconf) - if err != nil { - return - } - conf, err = alpm.ParseConfig(file) - if err != nil { - return - } - return -} diff --git a/utils.go b/utils.go index 1912ed16..1f8a1151 100644 --- a/utils.go +++ b/utils.go @@ -35,9 +35,7 @@ func passToPacman(op string, pkgs []string, flags []string) error { cmd = exec.Command("sudo", args...) } - cmd.Stdout = os.Stdout - cmd.Stdin = os.Stdin - cmd.Stderr = os.Stderr + cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr err := cmd.Run() return err } From 0473084ed2459723d32773e693b11e42810ea3b9 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sat, 6 May 2017 18:32:33 +0100 Subject: [PATCH 12/30] More porting from util to config --- actions.go | 4 +- aur/aur.go | 8 ++-- aur/result.go | 27 +++++++------- config/config.go | 44 +++++++++++++--------- pacman/pacman.go | 95 +++++++++--------------------------------------- query.go | 10 ++--- utils.go | 4 +- yay.go | 6 ++- 8 files changed, 74 insertions(+), 124 deletions(-) diff --git a/actions.go b/actions.go index 21b6aeb6..456cc87e 100644 --- a/actions.go +++ b/actions.go @@ -5,8 +5,8 @@ import ( "os" aur "github.com/jguer/yay/aur" + "github.com/jguer/yay/config" pac "github.com/jguer/yay/pacman" - "github.com/jguer/yay/util" ) // Install handles package installs @@ -43,7 +43,7 @@ func cleanDependencies(pkgs []string) error { } if len(hanging) != 0 { - if !util.ContinueTask("Confirm Removal?", "nN") { + if !config.ContinueTask("Confirm Removal?", "nN") { return nil } err = pac.CleanRemove(hanging) diff --git a/aur/aur.go b/aur/aur.go index db855f94..96f563db 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -8,8 +8,8 @@ import ( "sort" "strings" + "github.com/jguer/yay/config" "github.com/jguer/yay/pacman" - "github.com/jguer/yay/util" rpc "github.com/mikkeloscar/aur" ) @@ -126,7 +126,7 @@ func Upgrade(flags []string) error { } // Install updated packages - if !util.ContinueTask("Proceed with upgrade?", "nN") { + if !config.ContinueTask("Proceed with upgrade?", "nN") { return nil } @@ -149,7 +149,7 @@ func GetPkgbuild(pkgN string, dir string) (err error) { } fmt.Printf("\x1b[1;32m==>\x1b[1;33m %s \x1b[1;32mfound in AUR.\x1b[0m\n", pkgN) - util.DownloadAndUnpack(BaseURL+aq[0].URLPath, dir, false) + config.DownloadAndUnpack(BaseURL+aq[0].URLPath, dir, false) return } @@ -167,7 +167,7 @@ func CreateAURList(out *os.File) (err error) { for scanner.Scan() { fmt.Print(scanner.Text()) out.WriteString(scanner.Text()) - if util.Shell == "fish" { + if config.YayConf.Shell == "fish" { fmt.Print("\tAUR\n") out.WriteString("\tAUR\n") } else { diff --git a/aur/result.go b/aur/result.go index 7ae6bbdc..db523450 100644 --- a/aur/result.go +++ b/aur/result.go @@ -5,12 +5,13 @@ import ( "os" "os/exec" + "github.com/jguer/yay/config" "github.com/jguer/yay/pacman" "github.com/jguer/yay/util" rpc "github.com/mikkeloscar/aur" ) -// Dependencies returns package dependencies not installed belonging to AUR +// PkgDependencies returns package dependencies not installed belonging to AUR // 0 is Repo, 1 is Foreign. func PkgDependencies(a *rpc.Pkg) (runDeps [2][]string, makeDeps [2][]string, err error) { var q Query @@ -64,26 +65,26 @@ func printDeps(repoDeps []string, aurDeps []string) { } } -// Install handles install from Info Result. +// PkgInstall handles install from Info Result. func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []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 := util.BaseDir + a.PackageBase + "/" + dir := config.YayConf.BuildDir + a.PackageBase + "/" if _, err = os.Stat(dir); os.IsExist(err) { - if !util.ContinueTask("Directory exists. Clean Build?", "yY") { - _ = os.RemoveAll(util.BaseDir + a.PackageBase) + if !config.ContinueTask("Directory exists. Clean Build?", "yY") { + _ = os.RemoveAll(config.YayConf.BuildDir + a.PackageBase) } } - if err = util.DownloadAndUnpack(BaseURL+a.URLPath, util.BaseDir, false); err != nil { + if err = config.DownloadAndUnpack(BaseURL+a.URLPath, config.YayConf.BuildDir, false); err != nil { return } - if !util.ContinueTask("Edit PKGBUILD?", "yY") { - editcmd := exec.Command(util.Editor(), dir+"PKGBUILD") + if !config.ContinueTask("Edit PKGBUILD?", "yY") { + editcmd := exec.Command(config.Editor(), dir+"PKGBUILD") editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr editcmd.Run() } @@ -99,7 +100,7 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { finalmdeps = append(finalmdeps, makeDeps[1]...) if len(aurDeps) != 0 || len(repoDeps) != 0 { - if !util.ContinueTask("Continue?", "nN") { + if !config.ContinueTask("Continue?", "nN") { return finalmdeps, fmt.Errorf("user did not like the dependencies") } } @@ -107,7 +108,7 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { aurQ, _ := rpc.Info(aurDeps) if len(aurQ) != len(aurDeps) { (Query)(aurQ).MissingPackage(aurDeps) - if !util.ContinueTask("Continue?", "nN") { + if !config.ContinueTask("Continue?", "nN") { return finalmdeps, fmt.Errorf("unable to install dependencies") } } @@ -145,14 +146,14 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { args := []string{"-sri"} args = append(args, flags...) - makepkgcmd := exec.Command(util.MakepkgBin, args...) + makepkgcmd := exec.Command(config.YayConf.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 AURPrintInfo(a *rpc.Pkg) { +func PrintInfo(a *rpc.Pkg) { 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) @@ -214,7 +215,7 @@ func RemoveMakeDeps(depS []string) (err error) { hanging := pacman.SliceHangingPackages(depS) if len(hanging) != 0 { - if !util.ContinueTask("Confirm Removal?", "nN") { + if !config.ContinueTask("Confirm Removal?", "nN") { return nil } err = pacman.CleanRemove(hanging) diff --git a/config/config.go b/config/config.go index 48927624..d8dd73da 100644 --- a/config/config.go +++ b/config/config.go @@ -17,7 +17,8 @@ type Configuration struct { BuildDir string Editor string MakepkgBin string - NoConfirm bool + Shell string + noConfirm bool PacmanBin string PacmanConf string SortMode string @@ -31,30 +32,39 @@ var YayConf Configuration var AlpmConf alpm.PacmanConfig // AlpmHandle is the alpm handle used by yay -var AlpmHandle alpm.Handle +var AlpmHandle *alpm.Handle func init() { + var err error configfile := os.Getenv("HOME") + "/.config/yay/config.json" - if _, err := os.Stat(configfile); os.IsNotExist(err) { + if _, err = os.Stat(configfile); os.IsNotExist(err) { _ = os.MkdirAll(os.Getenv("HOME")+"/.config/yay", 0755) - } - - file, err := os.Open(configfile) - if err != nil { - fmt.Println("Error reading config:", err) - return - } - - decoder := json.NewDecoder(file) - err = decoder.Decode(&YayConf) - if err != nil { - fmt.Println("Error reading config:", err) + defaultSettings(&YayConf) + } else { + file, err := os.Open(configfile) + if err != nil { + fmt.Println("Error reading config:", err) + } else { + decoder := json.NewDecoder(file) + err = decoder.Decode(&YayConf) + if err != nil { + fmt.Println("Loading default Settings\nError reading config:", err) + defaultSettings(&YayConf) + } + } } AlpmConf, err = readAlpmConfig(YayConf.PacmanConf) if err != nil { fmt.Println("Unable to read Pacman conf", err) + os.Exit(1) + } + + AlpmHandle, err = AlpmConf.CreateHandle() + if err != nil { + fmt.Println("Unable to CreateHandle", err) + os.Exit(1) } } @@ -74,7 +84,7 @@ func defaultSettings(config *Configuration) { config.BuildDir = "/tmp/yaytmp/" config.Editor = "" config.MakepkgBin = "/usr/bin/makepkg" - config.NoConfirm = false + config.noConfirm = false config.PacmanBin = "/usr/bin/pacman" config.PacmanConf = "/etc/pacman.conf" config.SortMode = "BottomUp" @@ -132,7 +142,7 @@ func Editor() string { // ContinueTask prompts if user wants to continue task. //If NoConfirm is set the action will continue without user input. func ContinueTask(s string, def string) (cont bool) { - if YayConf.NoConfirm { + if YayConf.noConfirm { return true } var postFix string diff --git a/pacman/pacman.go b/pacman/pacman.go index 9c88cb75..ef63fa92 100644 --- a/pacman/pacman.go +++ b/pacman/pacman.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/jguer/go-alpm" + "github.com/jguer/yay/config" "github.com/jguer/yay/util" ) @@ -35,16 +36,11 @@ func UpdatePackages(flags []string) error { // Search handles repo searches. Creates a RepoSearch struct. func Search(pkgInputN []string) (s Query, n int, err error) { - h, err := util.Conf.CreateHandle() - defer h.Release() - if err != nil { - } - - localDb, err := h.LocalDb() + localDb, err := config.AlpmHandle.LocalDb() if err != nil { return } - dbList, err := h.SyncDbs() + dbList, err := config.AlpmHandle.SyncDbs() if err != nil { return } @@ -148,13 +144,7 @@ func (s Query) PrintSearch() { // PackageSlices separates an input slice into aur and repo slices func PackageSlices(toCheck []string) (aur []string, repo []string, err error) { - h, err := util.Conf.CreateHandle() - defer h.Release() - if err != nil { - return - } - - dbList, err := h.SyncDbs() + dbList, err := config.AlpmHandle.SyncDbs() if err != nil { return } @@ -186,10 +176,8 @@ func PackageSlices(toCheck []string) (aur []string, repo []string, err error) { // BuildDependencies finds packages, on the second run // compares with a baselist and avoids searching those func BuildDependencies(baselist []string) func(toCheck []string, isBaseList bool, last bool) (repo []string, notFound []string) { - h, _ := util.Conf.CreateHandle() - - localDb, _ := h.LocalDb() - dbList, _ := h.SyncDbs() + localDb, _ := config.AlpmHandle.LocalDb() + dbList, _ := config.AlpmHandle.SyncDbs() f := func(c rune) bool { return c == '>' || c == '<' || c == '=' || c == ' ' @@ -197,7 +185,6 @@ func BuildDependencies(baselist []string) func(toCheck []string, isBaseList bool return func(toCheck []string, isBaseList bool, close bool) (repo []string, notFound []string) { if close { - h.Release() return } @@ -226,17 +213,11 @@ func BuildDependencies(baselist []string) func(toCheck []string, isBaseList bool // DepSatisfier receives a string slice, returns a slice of packages found in // repos and one of packages not found in repos. Leaves out installed packages. func DepSatisfier(toCheck []string) (repo []string, notFound []string, err error) { - h, err := util.Conf.CreateHandle() - defer h.Release() + localDb, err := config.AlpmHandle.LocalDb() if err != nil { return } - - localDb, err := h.LocalDb() - if err != nil { - return - } - dbList, err := h.SyncDbs() + dbList, err := config.AlpmHandle.SyncDbs() if err != nil { return } @@ -297,17 +278,12 @@ func ForeignPackages() (foreign map[string]*struct { Version string Date int64 }, n int, err error) { - h, err := util.Conf.CreateHandle() - defer h.Release() - if err != nil { - return - } - localDb, err := h.LocalDb() + localDb, err := config.AlpmHandle.LocalDb() if err != nil { return } - dbList, err := h.SyncDbs() + dbList, err := config.AlpmHandle.SyncDbs() if err != nil { return } @@ -350,13 +326,7 @@ func Statistics() (info struct { var nPkg int var ePkg int - h, err := util.Conf.CreateHandle() - defer h.Release() - if err != nil { - return - } - - localDb, err := h.LocalDb() + localDb, err := config.AlpmHandle.LocalDb() if err != nil { return } @@ -382,13 +352,8 @@ func Statistics() (info struct { // BiggestPackages prints the name of the ten biggest packages in the system. func BiggestPackages() { - h, err := util.Conf.CreateHandle() - defer h.Release() - if err != nil { - return - } - localDb, err := h.LocalDb() + localDb, err := config.AlpmHandle.LocalDb() if err != nil { return } @@ -409,13 +374,7 @@ func BiggestPackages() { // HangingPackages returns a list of packages installed as deps // and unneeded by the system func HangingPackages() (hanging []string, err error) { - h, err := util.Conf.CreateHandle() - defer h.Release() - if err != nil { - return - } - - localDb, err := h.LocalDb() + localDb, err := config.AlpmHandle.LocalDb() if err != nil { return } @@ -440,13 +399,7 @@ func HangingPackages() (hanging []string, err error) { // SliceHangingPackages returns a list of packages installed as deps // and unneeded by the system from a provided list of package names. func SliceHangingPackages(pkgS []string) (hanging []string) { - h, err := util.Conf.CreateHandle() - defer h.Release() - if err != nil { - return - } - - localDb, err := h.LocalDb() + localDb, err := config.AlpmHandle.LocalDb() if err != nil { return } @@ -477,13 +430,7 @@ big: // GetPkgbuild downloads pkgbuild from the ABS. func GetPkgbuild(pkgN string, path string) (err error) { - h, err := util.Conf.CreateHandle() - defer h.Release() - if err != nil { - return - } - - dbList, err := h.SyncDbs() + dbList, err := config.AlpmHandle.SyncDbs() if err != nil { return } @@ -500,7 +447,7 @@ func GetPkgbuild(pkgN string, path string) (err error) { return fmt.Errorf("Not in standard repositories") } fmt.Printf("\x1b[1;32m==>\x1b[1;33m %s \x1b[1;32mfound in ABS.\x1b[0m\n", pkgN) - errD := util.DownloadAndUnpack(url, path, true) + errD := config.DownloadAndUnpack(url, path, true) return errD } } @@ -509,13 +456,7 @@ func GetPkgbuild(pkgN string, path string) (err error) { //CreatePackageList appends Repo packages to completion cache func CreatePackageList(out *os.File) (err error) { - h, err := util.Conf.CreateHandle() - defer h.Release() - if err != nil { - return - } - - dbList, err := h.SyncDbs() + dbList, err := config.AlpmHandle.SyncDbs() if err != nil { return } @@ -523,7 +464,7 @@ func CreatePackageList(out *os.File) (err error) { p := func(pkg alpm.Package) error { fmt.Print(pkg.Name()) out.WriteString(pkg.Name()) - if util.Shell == "fish" { + if config.YayConf.Shell == "fish" { fmt.Print("\t" + pkg.DB().Name() + "\n") out.WriteString("\t" + pkg.DB().Name() + "\n") } else { diff --git a/query.go b/query.go index 06a422c5..cdb1b252 100644 --- a/query.go +++ b/query.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/jguer/yay/aur" + "github.com/jguer/yay/config" pac "github.com/jguer/yay/pacman" "github.com/jguer/yay/util" rpc "github.com/mikkeloscar/aur" @@ -11,12 +12,7 @@ import ( // PrintSearch handles printing search results in a given format func printAURSearch(q aur.Query, start int) { - h, err := util.Conf.CreateHandle() - defer h.Release() - if err != nil { - } - - localDb, _ := h.LocalDb() + localDb, _ := config.AlpmHandle.LocalDb() for i, res := range q { var toprint string @@ -84,7 +80,7 @@ func syncInfo(pkgS []string, flags []string) (err error) { } for _, aurP := range q { - aur.AURPrintInfo(&aurP) + aur.PrintInfo(&aurP) } if len(repoS) != 0 { diff --git a/utils.go b/utils.go index 1f8a1151..d42bab01 100644 --- a/utils.go +++ b/utils.go @@ -10,8 +10,8 @@ import ( "time" "github.com/jguer/yay/aur" + "github.com/jguer/yay/config" pac "github.com/jguer/yay/pacman" - "github.com/jguer/yay/util" ) // PassToPacman outsorces execution to pacman binary without modifications. @@ -42,7 +42,7 @@ func passToPacman(op string, pkgs []string, flags []string) error { // Complete provides completion info for shells func complete() (err error) { - path := os.Getenv("HOME") + "/.cache/yay/aur_" + util.Shell + ".cache" + path := os.Getenv("HOME") + "/.cache/yay/aur_" + config.YayConf.Shell + ".cache" if info, err := os.Stat(path); os.IsNotExist(err) || time.Since(info.ModTime()).Hours() > 48 { os.MkdirAll(os.Getenv("HOME")+"/.cache/yay/", 0755) diff --git a/yay.go b/yay.go index c7c61790..ec96b8c9 100644 --- a/yay.go +++ b/yay.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/jguer/yay/aur" + "github.com/jguer/yay/config" pac "github.com/jguer/yay/pacman" "github.com/jguer/yay/util" ) @@ -67,11 +68,11 @@ func parser() (op string, options []string, packages []string, err error) { util.SortMode = util.TopDown case "--complete": - util.Shell = "sh" + config.YayConf.Shell = "sh" complete() os.Exit(0) case "--fcomplete": - util.Shell = "fish" + config.YayConf.Shell = "fish" complete() os.Exit(0) case "--help": @@ -136,6 +137,7 @@ func main() { err = passToPacman(op, pkgs, options) } + config.AlpmHandle.Release() if err != nil { fmt.Println(err) os.Exit(1) From bd2842841a09528406ea330fa87627ca2f1ffc7d Mon Sep 17 00:00:00 2001 From: Jguer Date: Sun, 7 May 2017 02:43:49 +0100 Subject: [PATCH 13/30] Killed util, config is now saved --- actions.go | 4 +- aur/query.go | 4 +- aur/result.go | 5 +-- config/config.go | 86 ++++++++++++++++++++++++++++++++++++------- pacman/pacman.go | 46 +++-------------------- pacman/pacman_test.go | 25 +++++++------ query.go | 11 +++--- util/util.go | 26 ------------- utils.go | 28 -------------- yay.go | 40 ++++++++++---------- 10 files changed, 123 insertions(+), 152 deletions(-) delete mode 100644 util/util.go diff --git a/actions.go b/actions.go index 456cc87e..d808d41c 100644 --- a/actions.go +++ b/actions.go @@ -13,7 +13,7 @@ import ( func install(pkgs []string, flags []string) error { aurs, repos, _ := pac.PackageSlices(pkgs) - err := pac.Install(repos, flags) + err := config.PassToPacman("-S", repos, flags) if err != nil { fmt.Println("Error installing repo packages.") } @@ -25,7 +25,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) + errp := config.PassToPacman("-Syu", nil, flags) erra := aur.Upgrade(flags) if errp != nil { diff --git a/aur/query.go b/aur/query.go index 45ee406c..80b00088 100644 --- a/aur/query.go +++ b/aur/query.go @@ -3,7 +3,7 @@ package aur import ( "fmt" - "github.com/jguer/yay/util" + "github.com/jguer/yay/config" rpc "github.com/mikkeloscar/aur" ) @@ -15,7 +15,7 @@ func (q Query) Len() int { } func (q Query) Less(i, j int) bool { - if util.SortMode == util.BottomUp { + if config.YayConf.SortMode == config.BottomUp { return q[i].NumVotes < q[j].NumVotes } return q[i].NumVotes > q[j].NumVotes diff --git a/aur/result.go b/aur/result.go index db523450..e4efe18a 100644 --- a/aur/result.go +++ b/aur/result.go @@ -7,7 +7,6 @@ import ( "github.com/jguer/yay/config" "github.com/jguer/yay/pacman" - "github.com/jguer/yay/util" rpc "github.com/mikkeloscar/aur" ) @@ -114,14 +113,14 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { } var depArgs []string - if util.NoConfirm { + if config.YayConf.NoConfirm { depArgs = []string{"--asdeps", "--noconfirm"} } else { depArgs = []string{"--asdeps"} } // Repo dependencies if len(repoDeps) != 0 { - errR := pacman.Install(repoDeps, depArgs) + errR := config.PassToPacman("-S", repoDeps, depArgs) if errR != nil { return finalmdeps, errR } diff --git a/config/config.go b/config/config.go index d8dd73da..84ade406 100644 --- a/config/config.go +++ b/config/config.go @@ -12,17 +12,31 @@ import ( alpm "github.com/jguer/go-alpm" ) -// Configuration stores yay's config +// Verbosity settings for search +const ( + NumberMenu = iota + Detailed + Minimal +) + +// Describes Sorting method for numberdisplay +const ( + BottomUp = iota + TopDown +) + +// Configuration stores yay's config. type Configuration struct { - BuildDir string - Editor string - MakepkgBin string - Shell string - noConfirm bool - PacmanBin string - PacmanConf string - SortMode string - TarBin string + BuildDir string `json:"buildDir"` + Editor string `json:"editor"` + MakepkgBin string `json:"makepkgbin"` + Shell string `json:"-"` + NoConfirm bool `json:"noconfirm"` + PacmanBin string `json:"pacmanbin"` + PacmanConf string `json:"pacmanconf"` + SearchMode int `json:"-"` + SortMode int `json:"sortmode"` + TarBin string `json:"tarbin"` } // YayConf holds the current config values for yay. @@ -31,7 +45,7 @@ var YayConf Configuration // AlpmConf holds the current config values for pacman. var AlpmConf alpm.PacmanConfig -// AlpmHandle is the alpm handle used by yay +// AlpmHandle is the alpm handle used by yay. var AlpmHandle *alpm.Handle func init() { @@ -80,14 +94,32 @@ func readAlpmConfig(pacmanconf string) (conf alpm.PacmanConfig, err error) { return } +// SaveConfig writes yay config to file. +func SaveConfig() error { + YayConf.NoConfirm = false + configfile := os.Getenv("HOME") + "/.config/yay/config.json" + marshalledinfo, _ := json.Marshal(YayConf) + in, err := os.OpenFile(configfile, os.O_RDWR|os.O_CREATE, 0755) + if err != nil { + return err + } + defer in.Close() + _, err = in.Write(marshalledinfo) + if err != nil { + return err + } + err = in.Sync() + return err +} + func defaultSettings(config *Configuration) { config.BuildDir = "/tmp/yaytmp/" config.Editor = "" config.MakepkgBin = "/usr/bin/makepkg" - config.noConfirm = false + config.NoConfirm = false config.PacmanBin = "/usr/bin/pacman" config.PacmanConf = "/etc/pacman.conf" - config.SortMode = "BottomUp" + config.SortMode = BottomUp config.TarBin = "/usr/bin/bsdtar" } @@ -142,7 +174,7 @@ func Editor() string { // ContinueTask prompts if user wants to continue task. //If NoConfirm is set the action will continue without user input. func ContinueTask(s string, def string) (cont bool) { - if YayConf.noConfirm { + if YayConf.NoConfirm { return true } var postFix string @@ -219,3 +251,29 @@ func DownloadAndUnpack(url string, path string, trim bool) (err error) { return } + +// PassToPacman outsorces execution to pacman binary without modifications. +func PassToPacman(op string, pkgs []string, flags []string) error { + var cmd *exec.Cmd + var args []string + + args = append(args, op) + if len(pkgs) != 0 { + args = append(args, pkgs...) + } + + if len(flags) != 0 { + args = append(args, flags...) + } + + if strings.Contains(op, "-Q") { + cmd = exec.Command(YayConf.PacmanBin, args...) + } else { + args = append([]string{YayConf.PacmanBin}, args...) + cmd = exec.Command("sudo", args...) + } + + cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr + err := cmd.Run() + return err +} diff --git a/pacman/pacman.go b/pacman/pacman.go index ef63fa92..7b32a878 100644 --- a/pacman/pacman.go +++ b/pacman/pacman.go @@ -3,12 +3,10 @@ package pacman import ( "fmt" "os" - "os/exec" "strings" "github.com/jguer/go-alpm" "github.com/jguer/yay/config" - "github.com/jguer/yay/util" ) // Query describes a Repository search. @@ -24,16 +22,6 @@ type Result struct { Installed bool } -// UpdatePackages handles cache update and upgrade -func UpdatePackages(flags []string) error { - args := append([]string{"pacman", "-Syu"}, flags...) - - cmd := exec.Command("sudo", args...) - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr - err := cmd.Run() - return err -} - // Search handles repo searches. Creates a RepoSearch struct. func Search(pkgInputN []string) (s Query, n int, err error) { localDb, err := config.AlpmHandle.LocalDb() @@ -62,7 +50,7 @@ func Search(pkgInputN []string) (s Query, n int, err error) { } // TopDown functions - if util.SortMode == util.TopDown { + if config.YayConf.SortMode == config.TopDown { initL = func(len int) int { return 0 } @@ -116,13 +104,13 @@ func Search(pkgInputN []string) (s Query, n int, err error) { func (s Query) PrintSearch() { for i, res := range s { var toprint string - if util.SearchVerbosity == util.NumberMenu { - if util.SortMode == util.BottomUp { + if config.YayConf.SearchMode == config.NumberMenu { + if config.YayConf.SortMode == config.BottomUp { toprint += fmt.Sprintf("%d ", len(s)-i-1) } else { toprint += fmt.Sprintf("%d ", i) } - } else if util.SearchVerbosity == util.Minimal { + } else if config.YayConf.SearchMode == config.Minimal { fmt.Println(res.Name) continue } @@ -241,36 +229,14 @@ func DepSatisfier(toCheck []string) (repo []string, notFound []string, err error return } -// Install sends an install command to pacman with the pkgName slice -func Install(pkgName []string, flags []string) (err error) { - if len(pkgName) == 0 { - return nil - } - - args := []string{"pacman", "-S"} - args = append(args, pkgName...) - args = append(args, flags...) - - cmd := exec.Command("sudo", args...) - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr - cmd.Run() - return nil -} - // CleanRemove sends a full removal command to pacman with the pkgName slice func CleanRemove(pkgName []string) (err error) { if len(pkgName) == 0 { return nil } - args := []string{"pacman", "-Rnsc"} - args = append(args, pkgName...) - args = append(args, "--noutil.Conf.rm") - - cmd := exec.Command("sudo", args...) - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr - cmd.Run() - return nil + err = config.PassToPacman("-Rsnc", pkgName, []string{"--noutil.Conf.rm"}) + return err } // ForeignPackages returns a map of foreign packages, with their version and date as values. diff --git a/pacman/pacman_test.go b/pacman/pacman_test.go index 7d4f3a98..9a7ff12b 100644 --- a/pacman/pacman_test.go +++ b/pacman/pacman_test.go @@ -1,8 +1,11 @@ package pacman -import "testing" -import "github.com/jguer/yay/util" -import "os" +import ( + "os" + "testing" + + "github.com/jguer/yay/config" +) func benchmarkPrintSearch(search string, b *testing.B) { old := os.Stdout @@ -17,20 +20,20 @@ func benchmarkPrintSearch(search string, b *testing.B) { } func BenchmarkPrintSearchSimpleTopDown(b *testing.B) { - util.SortMode = util.TopDown + config.YayConf.SortMode = config.TopDown benchmarkPrintSearch("chromium", b) } func BenchmarkPrintSearchComplexTopDown(b *testing.B) { - util.SortMode = util.TopDown + config.YayConf.SortMode = config.TopDown benchmarkPrintSearch("linux", b) } func BenchmarkPrintSearchSimpleBottomUp(b *testing.B) { - util.SortMode = util.BottomUp + config.YayConf.SortMode = config.BottomUp benchmarkPrintSearch("chromium", b) } func BenchmarkPrintSearchComplexBottomUp(b *testing.B) { - util.SortMode = util.BottomUp + config.YayConf.SortMode = config.BottomUp benchmarkPrintSearch("linux", b) } @@ -40,20 +43,20 @@ func benchmarkSearch(search string, b *testing.B) { } } func BenchmarkSearchSimpleTopDown(b *testing.B) { - util.SortMode = util.TopDown + config.YayConf.SortMode = config.TopDown benchmarkSearch("chromium", b) } func BenchmarkSearchSimpleBottomUp(b *testing.B) { - util.SortMode = util.BottomUp + config.YayConf.SortMode = config.BottomUp benchmarkSearch("chromium", b) } func BenchmarkSearchComplexTopDown(b *testing.B) { - util.SortMode = util.TopDown + config.YayConf.SortMode = config.TopDown benchmarkSearch("linux", b) } func BenchmarkSearchComplexBottomUp(b *testing.B) { - util.SortMode = util.BottomUp + config.YayConf.SortMode = config.BottomUp benchmarkSearch("linux", b) } diff --git a/query.go b/query.go index cdb1b252..394380c7 100644 --- a/query.go +++ b/query.go @@ -6,7 +6,6 @@ import ( "github.com/jguer/yay/aur" "github.com/jguer/yay/config" pac "github.com/jguer/yay/pacman" - "github.com/jguer/yay/util" rpc "github.com/mikkeloscar/aur" ) @@ -16,13 +15,13 @@ func printAURSearch(q aur.Query, start int) { for i, res := range q { var toprint string - if util.SearchVerbosity == util.NumberMenu { - if util.SortMode == util.BottomUp { + if config.YayConf.SearchMode == config.NumberMenu { + if config.YayConf.SortMode == config.BottomUp { toprint += fmt.Sprintf("%d ", len(q)+start-i-1) } else { toprint += fmt.Sprintf("%d ", start+i) } - } else if util.SearchVerbosity == util.Minimal { + } else if config.YayConf.SearchMode == config.Minimal { fmt.Println(res.Name) continue } @@ -56,7 +55,7 @@ func syncSearch(pkgS []string) (err error) { return err } - if util.SortMode == util.BottomUp { + if config.YayConf.SortMode == config.BottomUp { printAURSearch(aq, 0) pq.PrintSearch() } else { @@ -84,7 +83,7 @@ func syncInfo(pkgS []string, flags []string) (err error) { } if len(repoS) != 0 { - err = passToPacman("-Si", repoS, flags) + err = config.PassToPacman("-Si", repoS, flags) } return diff --git a/util/util.go b/util/util.go deleted file mode 100644 index 79fc4ebe..00000000 --- a/util/util.go +++ /dev/null @@ -1,26 +0,0 @@ -package util - -// SearchVerbosity determines print method used in PrintSearch -var SearchVerbosity = NumberMenu - -// Verbosity settings for search -const ( - NumberMenu = iota - Detailed - Minimal -) - -// Build controls if packages will be built from ABS. -var Build = false - -// NoConfirm ignores prompts. -var NoConfirm = false - -// SortMode determines top down package or down top package display -var SortMode = BottomUp - -// Describes Sorting method for numberdisplay -const ( - BottomUp = iota - TopDown -) diff --git a/utils.go b/utils.go index d42bab01..29ea4b30 100644 --- a/utils.go +++ b/utils.go @@ -5,8 +5,6 @@ import ( "io" "math" "os" - "os/exec" - "strings" "time" "github.com/jguer/yay/aur" @@ -14,32 +12,6 @@ import ( pac "github.com/jguer/yay/pacman" ) -// PassToPacman outsorces execution to pacman binary without modifications. -func passToPacman(op string, pkgs []string, flags []string) error { - var cmd *exec.Cmd - var args []string - - args = append(args, op) - if len(pkgs) != 0 { - args = append(args, pkgs...) - } - - if len(flags) != 0 { - args = append(args, flags...) - } - - if strings.Contains(op, "-Q") { - cmd = exec.Command("pacman", args...) - } else { - args = append([]string{"pacman"}, args...) - cmd = exec.Command("sudo", args...) - } - - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr - err := cmd.Run() - return err -} - // Complete provides completion info for shells func complete() (err error) { path := os.Getenv("HOME") + "/.cache/yay/aur_" + config.YayConf.Shell + ".cache" diff --git a/yay.go b/yay.go index ec96b8c9..414678d0 100644 --- a/yay.go +++ b/yay.go @@ -10,7 +10,6 @@ import ( "github.com/jguer/yay/aur" "github.com/jguer/yay/config" pac "github.com/jguer/yay/pacman" - "github.com/jguer/yay/util" ) func usage() { @@ -38,20 +37,19 @@ func usage() { `) } -var version = "1.116" +var version = "2.116" -func parser() (op string, options []string, packages []string, err error) { +func parser() (op string, options []string, packages []string, changedConfig bool, err error) { if len(os.Args) < 2 { err = fmt.Errorf("no operation specified") return } + changedConfig = false op = "yogurt" for _, arg := range os.Args[1:] { if arg[0] == '-' && arg[1] != '-' { switch arg { - case "-b": - util.Build = true default: op = arg } @@ -60,13 +58,12 @@ func parser() (op string, options []string, packages []string, err error) { if arg[0] == '-' && arg[1] == '-' { switch arg { - case "--build": - util.Build = true case "--bottomup": - util.SortMode = util.BottomUp + config.YayConf.SortMode = config.BottomUp + changedConfig = true case "--topdown": - util.SortMode = util.TopDown - + config.YayConf.SortMode = config.TopDown + changedConfig = true case "--complete": config.YayConf.Shell = "sh" complete() @@ -79,7 +76,7 @@ func parser() (op string, options []string, packages []string, err error) { usage() os.Exit(0) case "--noconfirm": - util.NoConfirm = true + config.YayConf.NoConfirm = true fallthrough default: options = append(options, arg) @@ -93,7 +90,7 @@ func parser() (op string, options []string, packages []string, err error) { } func main() { - op, options, pkgs, err := parser() + op, options, pkgs, changedConfig, err := parser() if err != nil { fmt.Println(err) os.Exit(1) @@ -113,9 +110,9 @@ func main() { err = localStatistics(version) case "-Ss", "-Ssq", "-Sqs": if op == "-Ss" { - util.SearchVerbosity = util.Detailed + config.YayConf.SearchMode = config.Detailed } else { - util.SearchVerbosity = util.Minimal + config.YayConf.SearchMode = config.Minimal } if pkgs != nil { @@ -128,13 +125,16 @@ func main() { case "-Si": err = syncInfo(pkgs, options) case "yogurt": - util.SearchVerbosity = util.NumberMenu + config.YayConf.SearchMode = config.NumberMenu if pkgs != nil { err = numberMenu(pkgs, options) } default: - err = passToPacman(op, pkgs, options) + err = config.PassToPacman(op, pkgs, options) + } + if changedConfig { + config.SaveConfig() } config.AlpmHandle.Release() @@ -162,7 +162,7 @@ func numberMenu(pkgS []string, flags []string) (err error) { return fmt.Errorf("no packages match search") } - if util.SortMode == util.BottomUp { + if config.YayConf.SortMode == config.BottomUp { printAURSearch(aq, numpq) pq.PrintSearch() } else { @@ -192,13 +192,13 @@ func numberMenu(pkgS []string, flags []string) (err error) { if num > numaq+numpq-1 || num < 0 { continue } else if num > numpq-1 { - if util.SortMode == util.BottomUp { + if config.YayConf.SortMode == config.BottomUp { aurInstall = append(aurInstall, aq[numaq+numpq-num-1].Name) } else { aurInstall = append(aurInstall, aq[num-numpq].Name) } } else { - if util.SortMode == util.BottomUp { + if config.YayConf.SortMode == config.BottomUp { repoInstall = append(repoInstall, pq[numpq-num-1].Name) } else { repoInstall = append(repoInstall, pq[num].Name) @@ -207,7 +207,7 @@ func numberMenu(pkgS []string, flags []string) (err error) { } if len(repoInstall) != 0 { - pac.Install(repoInstall, flags) + config.PassToPacman("-S", repoInstall, flags) } if len(aurInstall) != 0 { From a20646fa246c00b73ddffa520112760e15e9dace Mon Sep 17 00:00:00 2001 From: Jguer Date: Sun, 7 May 2017 03:29:01 +0100 Subject: [PATCH 14/30] Fixed a very subtle bug that hided the first result of every search in bottom up --- aur/result.go | 2 +- pacman/pacman.go | 57 +++++++++++++----------------------------------- yay.go | 4 ++-- 3 files changed, 18 insertions(+), 45 deletions(-) diff --git a/aur/result.go b/aur/result.go index e4efe18a..d9b6910a 100644 --- a/aur/result.go +++ b/aur/result.go @@ -72,7 +72,7 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { } dir := config.YayConf.BuildDir + a.PackageBase + "/" - if _, err = os.Stat(dir); os.IsExist(err) { + if _, err = os.Stat(dir); !os.IsNotExist(err) { if !config.ContinueTask("Directory exists. Clean Build?", "yY") { _ = os.RemoveAll(config.YayConf.BuildDir + a.PackageBase) } diff --git a/pacman/pacman.go b/pacman/pacman.go index 7b32a878..0a59cd4d 100644 --- a/pacman/pacman.go +++ b/pacman/pacman.go @@ -9,40 +9,23 @@ import ( "github.com/jguer/yay/config" ) -// Query describes a Repository search. -type Query []Result - -// Result describes a pkg. -type Result struct { - Name string - Repository string - Version string - Description string - Group string - Installed bool -} +// Query holds the results of a repository search. +type Query []alpm.Package // Search handles repo searches. Creates a RepoSearch struct. func Search(pkgInputN []string) (s Query, n int, err error) { - localDb, err := config.AlpmHandle.LocalDb() - if err != nil { - return - } dbList, err := config.AlpmHandle.SyncDbs() if err != nil { return } - var installed bool - dbS := dbList.Slice() - // BottomUp functions initL := func(len int) int { return len - 1 } compL := func(len int, i int) bool { - return i > 0 + return i > -1 } finalL := func(i int) int { @@ -64,13 +47,12 @@ func Search(pkgInputN []string) (s Query, n int, err error) { } } + dbS := dbList.Slice() lenDbs := len(dbS) for f := initL(lenDbs); compL(lenDbs, f); f = finalL(f) { pkgS := dbS[f].PkgCache().Slice() lenPkgs := len(pkgS) - for i := initL(lenPkgs); compL(lenPkgs, i); i = finalL(i) { - match := true for _, pkgN := range pkgInputN { if !(strings.Contains(pkgS[i].Name(), pkgN) || strings.Contains(strings.ToLower(pkgS[i].Description()), pkgN)) { @@ -80,20 +62,8 @@ func Search(pkgInputN []string) (s Query, n int, err error) { } if match { - installed = false - if r, _ := localDb.PkgByName(pkgS[i].Name()); r != nil { - installed = true - } n++ - - s = append(s, Result{ - Name: pkgS[i].Name(), - Description: pkgS[i].Description(), - Version: pkgS[i].Version(), - Repository: dbS[f].Name(), - Group: strings.Join(pkgS[i].Groups().Slice(), ","), - Installed: installed, - }) + s = append(s, pkgS[i]) } } } @@ -111,21 +81,24 @@ func (s Query) PrintSearch() { toprint += fmt.Sprintf("%d ", i) } } else if config.YayConf.SearchMode == config.Minimal { - fmt.Println(res.Name) + fmt.Println(res.Name()) continue } toprint += fmt.Sprintf("\x1b[1m%s/\x1b[33m%s \x1b[36m%s \x1b[0m", - res.Repository, res.Name, res.Version) + res.DB().Name(), res.Name(), res.Version()) - if len(res.Group) != 0 { - toprint += fmt.Sprintf("(%s) ", res.Group) + if len(res.Groups().Slice()) != 0 { + toprint += fmt.Sprint(res.Groups().Slice(), " ") } - if res.Installed { - toprint += fmt.Sprintf("\x1b[32;40mInstalled\x1b[0m") + localDb, err := config.AlpmHandle.LocalDb() + if err == nil { + if _, err = localDb.PkgByName(res.Name()); err == nil { + toprint += fmt.Sprintf("\x1b[32;40mInstalled\x1b[0m") + } } - toprint += "\n" + res.Description + toprint += "\n" + res.Description() fmt.Println(toprint) } } diff --git a/yay.go b/yay.go index 414678d0..84c59cb6 100644 --- a/yay.go +++ b/yay.go @@ -199,9 +199,9 @@ func numberMenu(pkgS []string, flags []string) (err error) { } } else { if config.YayConf.SortMode == config.BottomUp { - repoInstall = append(repoInstall, pq[numpq-num-1].Name) + repoInstall = append(repoInstall, pq[numpq-num-1].Name()) } else { - repoInstall = append(repoInstall, pq[num].Name) + repoInstall = append(repoInstall, pq[num].Name()) } } } From 1a580178171260d96ced3b2f9186d539951c697f Mon Sep 17 00:00:00 2001 From: Jguer Date: Sun, 7 May 2017 13:52:08 +0100 Subject: [PATCH 15/30] Changed upgrade logic to use alpm.pkg --- aur/aur.go | 17 +++++++++-------- pacman/pacman.go | 47 ++++++++++++++++++++++------------------------- query.go | 7 +++++-- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/aur/aur.go b/aur/aur.go index 96f563db..76bd790a 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -90,11 +90,10 @@ func Install(pkgName []string, flags []string) (err 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() - if err != nil || n == 0 { + foreign, err := pacman.ForeignPackages() + if err != nil { return err } - keys := make([]string, len(foreign)) i := 0 for k := range foreign { @@ -108,12 +107,14 @@ func Upgrade(flags []string) error { } outdated := q[:0] - for _, res := range q { + for i, res := range q { + fmt.Printf("\r Checking %d/%d packages...", i+1, len(q)) + if _, ok := foreign[res.Name]; ok { // Leaving this here for now, warn about downgrades later - if res.LastModified > int(foreign[res.Name].Date) { + if int64(res.LastModified) > foreign[res.Name].BuildDate().UnixNano() { fmt.Printf("\x1b[1m\x1b[32m==>\x1b[33;1m %s: \x1b[0m%s \x1b[33;1m-> \x1b[0m%s\n", - res.Name, foreign[res.Name].Version, res.Version) + res.Name, foreign[res.Name].Version(), res.Version) outdated = append(outdated, res) } } @@ -121,12 +122,12 @@ func Upgrade(flags []string) error { //If there are no outdated packages, don't prompt if len(outdated) == 0 { - fmt.Println(" there is nothing to do") + fmt.Println("\n there is nothing to do") return nil } // Install updated packages - if !config.ContinueTask("Proceed with upgrade?", "nN") { + if !config.ContinueTask("\nProceed with upgrade?", "nN") { return nil } diff --git a/pacman/pacman.go b/pacman/pacman.go index 0a59cd4d..1d0b9e03 100644 --- a/pacman/pacman.go +++ b/pacman/pacman.go @@ -23,11 +23,9 @@ func Search(pkgInputN []string) (s Query, n int, err error) { initL := func(len int) int { return len - 1 } - compL := func(len int, i int) bool { return i > -1 } - finalL := func(i int) int { return i - 1 } @@ -37,11 +35,9 @@ func Search(pkgInputN []string) (s Query, n int, err error) { initL = func(len int) int { return 0 } - compL = func(len int, i int) bool { return i < len } - finalL = func(i int) int { return i + 1 } @@ -202,6 +198,14 @@ func DepSatisfier(toCheck []string) (repo []string, notFound []string, err error return } +// PkgNameSlice returns a slice of package names +// func (s Query) PkgNameSlice() (pkgNames []string) { +// for _, e := range s { +// pkgNames = append(pkgNames, e.Name()) +// } +// return +// } + // CleanRemove sends a full removal command to pacman with the pkgName slice func CleanRemove(pkgName []string) (err error) { if len(pkgName) == 0 { @@ -213,11 +217,7 @@ func CleanRemove(pkgName []string) (err error) { } // ForeignPackages returns a map of foreign packages, with their version and date as values. -func ForeignPackages() (foreign map[string]*struct { - Version string - Date int64 -}, n int, err error) { - +func ForeignPackages() (foreign map[string]alpm.Package, err error) { localDb, err := config.AlpmHandle.LocalDb() if err != nil { return @@ -227,31 +227,28 @@ func ForeignPackages() (foreign map[string]*struct { return } - foreign = make(map[string]*struct { - Version string - Date int64 - }) - // Find foreign packages in system - for _, pkg := range localDb.PkgCache().Slice() { - // Change to more effective method + foreign = make(map[string]alpm.Package) + + f := func(k alpm.Package) error { found := false - for _, db := range dbList.Slice() { - _, err = db.PkgByName(pkg.Name()) + dbList.ForEach(func(d alpm.Db) error { + if found { + return nil + } + _, err = d.PkgByName(k.Name()) if err == nil { found = true - break } - } + return nil + }) if !found { - foreign[pkg.Name()] = &struct { - Version string - Date int64 - }{pkg.Version(), pkg.InstallDate().Unix()} - n++ + foreign[k.Name()] = k } + return nil } + err = localDb.PkgCache().ForEach(f) return } diff --git a/query.go b/query.go index 394380c7..1afa3441 100644 --- a/query.go +++ b/query.go @@ -96,12 +96,15 @@ func localStatistics(version string) error { return err } - foreignS, foreign, _ := pac.ForeignPackages() + foreignS, err := pac.ForeignPackages() + if err != nil { + return err + } fmt.Printf("\n Yay version r%s\n", version) fmt.Println("\x1B[1;34m===========================================\x1B[0m") fmt.Printf("\x1B[1;32mTotal installed packages: \x1B[0;33m%d\x1B[0m\n", info.Totaln) - fmt.Printf("\x1B[1;32mTotal foreign installed packages: \x1B[0;33m%d\x1B[0m\n", foreign) + fmt.Printf("\x1B[1;32mTotal foreign installed packages: \x1B[0;33m%d\x1B[0m\n", len(foreignS)) fmt.Printf("\x1B[1;32mExplicitly installed packages: \x1B[0;33m%d\x1B[0m\n", info.Expln) fmt.Printf("\x1B[1;32mTotal Size occupied by packages: \x1B[0;33m%s\x1B[0m\n", size(info.TotalSize)) fmt.Println("\x1B[1;34m===========================================\x1B[0m") From c06b55d6f1c968d35a852d282bc02f4c0c0ffe17 Mon Sep 17 00:00:00 2001 From: Jguer Date: Sun, 7 May 2017 20:24:18 +0100 Subject: [PATCH 16/30] Refactoring inline functions --- pacman/pacman.go | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/pacman/pacman.go b/pacman/pacman.go index 1d0b9e03..30643322 100644 --- a/pacman/pacman.go +++ b/pacman/pacman.go @@ -108,14 +108,19 @@ func PackageSlices(toCheck []string) (aur []string, repo []string, err error) { for _, pkg := range toCheck { found := false - for _, db := range dbList.Slice() { + + _ = dbList.ForEach(func(db alpm.Db) error { + if found { + return nil + } + _, err = db.PkgByName(pkg) if err == nil { found = true repo = append(repo, pkg) - break } - } + return nil + }) if !found { if _, errdb := dbList.PkgCachebyGroup(pkg); errdb == nil { @@ -231,7 +236,7 @@ func ForeignPackages() (foreign map[string]alpm.Package, err error) { f := func(k alpm.Package) error { found := false - dbList.ForEach(func(d alpm.Db) error { + _ = dbList.ForEach(func(d alpm.Db) error { if found { return nil } @@ -397,25 +402,20 @@ func CreatePackageList(out *os.File) (err error) { return } - p := func(pkg alpm.Package) error { - fmt.Print(pkg.Name()) - out.WriteString(pkg.Name()) - if config.YayConf.Shell == "fish" { - fmt.Print("\t" + pkg.DB().Name() + "\n") - out.WriteString("\t" + pkg.DB().Name() + "\n") - } else { - fmt.Print("\n") - out.WriteString("\n") - } - + _ = dbList.ForEach(func(db alpm.Db) error { + _ = db.PkgCache().ForEach(func(pkg alpm.Package) error { + fmt.Print(pkg.Name()) + out.WriteString(pkg.Name()) + if config.YayConf.Shell == "fish" { + fmt.Print("\t" + pkg.DB().Name() + "\n") + out.WriteString("\t" + pkg.DB().Name() + "\n") + } else { + fmt.Print("\n") + out.WriteString("\n") + } + return nil + }) return nil - } - - f := func(db alpm.Db) error { - db.PkgCache().ForEach(p) - return nil - } - - dbList.ForEach(f) + }) return nil } From 66c4a31b71b3ed72ccc094e76c47794cb81b3063 Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 8 May 2017 18:19:58 +0100 Subject: [PATCH 17/30] More refactoring on pacman --- pacman/pacman.go | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/pacman/pacman.go b/pacman/pacman.go index 30643322..da32b714 100644 --- a/pacman/pacman.go +++ b/pacman/pacman.go @@ -21,25 +21,24 @@ func Search(pkgInputN []string) (s Query, n int, err error) { // BottomUp functions initL := func(len int) int { - return len - 1 + if config.YayConf.SortMode == config.TopDown { + return 0 + } else { + return len - 1 + } } compL := func(len int, i int) bool { - return i > -1 + if config.YayConf.SortMode == config.TopDown { + return i < len + } else { + return i > -1 + } } finalL := func(i int) int { - return i - 1 - } - - // TopDown functions - if config.YayConf.SortMode == config.TopDown { - initL = func(len int) int { - return 0 - } - compL = func(len int, i int) bool { - return i < len - } - finalL = func(i int) int { + if config.YayConf.SortMode == config.TopDown { return i + 1 + } else { + return i - 1 } } From 6206c105a7aacf27bdd131f8f96e01d8543c4eeb Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 9 May 2017 02:09:43 +0100 Subject: [PATCH 18/30] Implemmented github VCS updates. Getting hammered by rate limiting --- aur/aur.go | 44 +++++++++++++++++++++++++++++++++++++++++- aur/result.go | 20 +++++++++++++++++++ aur/vcs/github.go | 31 ++++++++++++++++++++--------- aur/vcs/github_test.go | 6 +++--- config/config.go | 2 ++ yay.go | 25 +++++++++++++++++------- 6 files changed, 108 insertions(+), 20 deletions(-) diff --git a/aur/aur.go b/aur/aur.go index 76bd790a..71527ed8 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -8,6 +8,7 @@ import ( "sort" "strings" + vcs "github.com/jguer/yay/aur/vcs" "github.com/jguer/yay/config" "github.com/jguer/yay/pacman" rpc "github.com/mikkeloscar/aur" @@ -16,6 +17,8 @@ import ( // BaseURL givers the AUR default address. const BaseURL string = "https://aur.archlinux.org" +var specialDBsauce bool = false + // NarrowSearch searches AUR and narrows based on subarguments func NarrowSearch(pkgS []string, sortS bool) (Query, error) { if len(pkgS) == 0 { @@ -67,7 +70,7 @@ func Install(pkgName []string, flags []string) (err error) { } if len(q) != len(pkgName) { - return fmt.Errorf("Some package from list\n%+v\ndoes not exist", pkgName) + fmt.Printf("Some package from list\n%+v\ndoes not exist", pkgName) } var finalrm []string @@ -86,10 +89,49 @@ func Install(pkgName []string, flags []string) (err error) { return err } +// CreateDevelDB forces yay to create a DB of the existing development packages +func CreateDevelDB() error { + foreign, err := pacman.ForeignPackages() + if err != nil { + return err + } + + keys := make([]string, len(foreign)) + i := 0 + for k := range foreign { + keys[i] = k + i++ + } + + config.YayConf.NoConfirm = true + specialDBsauce = true + err = Install(keys, nil) + return err +} + +func DevelUpgrade(flags []string) { + +} // Upgrade tries to update every foreign package installed in the system func Upgrade(flags []string) error { fmt.Println("\x1b[1;36;1m::\x1b[0m\x1b[1m Starting AUR upgrade...\x1b[0m") + if config.YayConf.Devel { + fmt.Println(" Checking development packages...") + develUpdates := vcs.CheckUpdates() + if len(develUpdates) != 0 { + // Install updated packages + if !config.ContinueTask("\nProceed with upgrade?", "nN") { + return nil + } + + err := Install(develUpdates, flags) + if err != nil { + fmt.Println(err) + } + } + } + foreign, err := pacman.ForeignPackages() if err != nil { return err diff --git a/aur/result.go b/aur/result.go index d9b6910a..6c32f648 100644 --- a/aur/result.go +++ b/aur/result.go @@ -5,9 +5,11 @@ import ( "os" "os/exec" + vcs "github.com/jguer/yay/aur/vcs" "github.com/jguer/yay/config" "github.com/jguer/yay/pacman" rpc "github.com/mikkeloscar/aur" + gopkg "github.com/mikkeloscar/gopkgbuild" ) // PkgDependencies returns package dependencies not installed belonging to AUR @@ -88,6 +90,24 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { editcmd.Run() } + pkgb, err := gopkg.ParseSRCINFO(dir + ".SRCINFO") + if err == nil { + for _, pkgsource := range pkgb.Source { + owner, repo := vcs.ParseSource(pkgsource) + if owner != "" && repo != "" { + err = vcs.BranchInfo(a.Name, owner, repo) + if err != nil { + fmt.Println(err) + } + vcs.SaveBranchInfo() + } + } + } + + if specialDBsauce { + return + } + runDeps, makeDeps, err := PkgDependencies(a) if err != nil { return diff --git a/aur/vcs/github.go b/aur/vcs/github.go index 036e0285..c9c4f4f1 100644 --- a/aur/vcs/github.go +++ b/aur/vcs/github.go @@ -10,9 +10,11 @@ import ( // branch contains the information of a repository branch type branch struct { - Name string `json:"name"` - SHA string `json:"sha"` - URL string `json:"url"` + Name string `json:"name"` + Commit struct { + SHA string `json:"sha"` + URL string `json:"url"` + } `json:"commit"` } type branches []branch @@ -29,11 +31,16 @@ type infos []Info var savedInfo infos var configfile string +// Updated returns if database has been updated +var Updated bool + func init() { + Updated = false configfile = os.Getenv("HOME") + "/.config/yay/yay_vcs.json" if _, err := os.Stat(configfile); os.IsNotExist(err) { _ = os.MkdirAll(os.Getenv("HOME")+"/.config/yay", 0755) + return } file, err := os.Open(configfile) @@ -50,6 +57,11 @@ func init() { // ParseSource returns owner and repo from source func ParseSource(source string) (owner string, repo string) { + if !(strings.Contains(source, "git://") || + strings.Contains(source, ".git") || + strings.Contains(source, "git+https://")) { + return + } split := strings.Split(source, "github.com/") if len(split) > 1 { secondSplit := strings.Split(split[1], "/") @@ -81,7 +93,7 @@ func (info *Info) needsUpdate() bool { for _, e := range newRepo { if e.Name == "master" { - if e.SHA != info.SHA { + if e.Commit.SHA != info.SHA { return true } else { return false @@ -100,9 +112,9 @@ func CheckUpdates() (toUpdate []string) { return } -func inStore(pkgname string) *Info { +func inStore(url string) *Info { for i, e := range savedInfo { - if pkgname == e.Package { + if url == e.URL { return &savedInfo[i] } } @@ -111,6 +123,7 @@ func inStore(pkgname string) *Info { // BranchInfo updates saved information func BranchInfo(pkgname string, owner string, repo string) (err error) { + Updated = true var newRepo branches url := "https://api.github.com/repos/" + owner + "/" + repo + "/branches" r, err := http.Get(url) @@ -121,16 +134,16 @@ func BranchInfo(pkgname string, owner string, repo string) (err error) { _ = json.NewDecoder(r.Body).Decode(&newRepo) - packinfo := inStore(pkgname) + packinfo := inStore(url) for _, e := range newRepo { if e.Name == "master" { if packinfo != nil { packinfo.Package = pkgname packinfo.URL = url - packinfo.SHA = e.SHA + packinfo.SHA = e.Commit.SHA } else { - savedInfo = append(savedInfo, Info{Package: pkgname, URL: url, SHA: e.SHA}) + savedInfo = append(savedInfo, Info{Package: pkgname, URL: url, SHA: e.Commit.SHA}) } } } diff --git a/aur/vcs/github_test.go b/aur/vcs/github_test.go index 9895602d..6f6fefec 100644 --- a/aur/vcs/github_test.go +++ b/aur/vcs/github_test.go @@ -12,20 +12,20 @@ func TestParsing(t *testing.T) { } neovim := source{sourceurl: "git+https://github.com/neovim/neovim.git"} - neovim.owner, neovim.repo = parseSource(neovim.sourceurl) + neovim.owner, neovim.repo = ParseSource(neovim.sourceurl) if neovim.owner != "neovim" || neovim.repo != "neovim" { t.Fatalf("Expected to find neovim/neovim, found %+v/%+v", neovim.owner, neovim.repo) } yay := source{sourceurl: "git://github.com/jguer/yay.git#branch=master"} - yay.owner, yay.repo = parseSource(yay.sourceurl) + yay.owner, yay.repo = ParseSource(yay.sourceurl) if yay.owner != "jguer" || yay.repo != "yay" { t.Fatalf("Expected to find jguer/yay, found %+v/%+v", yay.owner, yay.repo) } ack := source{sourceurl: "git://github.com/davidgiven/ack"} - ack.owner, ack.repo = parseSource(ack.sourceurl) + ack.owner, ack.repo = ParseSource(ack.sourceurl) if ack.owner != "davidgiven" || ack.repo != "ack" { t.Fatalf("Expected to find davidgiven/ack, found %+v/%+v", ack.owner, ack.repo) } diff --git a/config/config.go b/config/config.go index 84ade406..b566b105 100644 --- a/config/config.go +++ b/config/config.go @@ -32,6 +32,7 @@ type Configuration struct { MakepkgBin string `json:"makepkgbin"` Shell string `json:"-"` NoConfirm bool `json:"noconfirm"` + Devel bool `json:"devel"` PacmanBin string `json:"pacmanbin"` PacmanConf string `json:"pacmanconf"` SearchMode int `json:"-"` @@ -115,6 +116,7 @@ func SaveConfig() error { func defaultSettings(config *Configuration) { config.BuildDir = "/tmp/yaytmp/" config.Editor = "" + config.Devel = false config.MakepkgBin = "/usr/bin/makepkg" config.NoConfirm = false config.PacmanBin = "/usr/bin/pacman" diff --git a/yay.go b/yay.go index 84c59cb6..7ce900c3 100644 --- a/yay.go +++ b/yay.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/jguer/yay/aur" + vcs "github.com/jguer/yay/aur/vcs" "github.com/jguer/yay/config" pac "github.com/jguer/yay/pacman" ) @@ -57,13 +58,18 @@ func parser() (op string, options []string, packages []string, changedConfig boo } if arg[0] == '-' && arg[1] == '-' { + changedConfig = true switch arg { - case "--bottomup": - config.YayConf.SortMode = config.BottomUp - changedConfig = true + case "--gendb": + aur.CreateDevelDB() + vcs.SaveBranchInfo() + os.Exit(0) + case "--devel": + config.YayConf.Devel = true + case "--nodevel": + config.YayConf.Devel = false case "--topdown": config.YayConf.SortMode = config.TopDown - changedConfig = true case "--complete": config.YayConf.Shell = "sh" complete() @@ -133,6 +139,11 @@ func main() { default: err = config.PassToPacman(op, pkgs, options) } + + if vcs.Updated { + vcs.SaveBranchInfo() + } + if changedConfig { config.SaveConfig() } @@ -207,12 +218,12 @@ func numberMenu(pkgS []string, flags []string) (err error) { } if len(repoInstall) != 0 { - config.PassToPacman("-S", repoInstall, flags) + err = config.PassToPacman("-S", repoInstall, flags) } if len(aurInstall) != 0 { - aur.Install(aurInstall, flags) + err = aur.Install(aurInstall, flags) } - return nil + return err } From d9b793b6954ce28c52111cb50c42977228a04e4c Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 9 May 2017 14:44:34 +0100 Subject: [PATCH 19/30] If github fudges up don't save it --- aur/vcs/github.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/aur/vcs/github.go b/aur/vcs/github.go index c9c4f4f1..1bee875d 100644 --- a/aur/vcs/github.go +++ b/aur/vcs/github.go @@ -152,7 +152,10 @@ func BranchInfo(pkgname string, owner string, repo string) (err error) { } func SaveBranchInfo() error { - marshalledinfo, _ := json.Marshal(savedInfo) + marshalledinfo, err := json.Marshal(savedInfo) + if err != nil || string(marshalledinfo) == "null" { + return err + } in, err := os.OpenFile(configfile, os.O_RDWR|os.O_CREATE, 0755) if err != nil { return err From 457f4ead8c51325efa66ee4d84b7a51d480fa240 Mon Sep 17 00:00:00 2001 From: Jguer Date: Mon, 15 May 2017 11:39:06 +0100 Subject: [PATCH 20/30] Fixed Package versioning bug. Display fix. --- aur/aur.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/aur/aur.go b/aur/aur.go index 71527ed8..2b90bb39 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -2,6 +2,7 @@ package aur import ( "bufio" + "bytes" "fmt" "net/http" "os" @@ -112,6 +113,7 @@ func CreateDevelDB() error { func DevelUpgrade(flags []string) { } + // Upgrade tries to update every foreign package installed in the system func Upgrade(flags []string) error { fmt.Println("\x1b[1;36;1m::\x1b[0m\x1b[1m Starting AUR upgrade...\x1b[0m") @@ -148,28 +150,31 @@ func Upgrade(flags []string) error { return err } + var buffer bytes.Buffer + buffer.WriteString("\n") outdated := q[:0] for i, res := range q { fmt.Printf("\r Checking %d/%d packages...", i+1, len(q)) if _, ok := foreign[res.Name]; ok { // Leaving this here for now, warn about downgrades later - if int64(res.LastModified) > foreign[res.Name].BuildDate().UnixNano() { - fmt.Printf("\x1b[1m\x1b[32m==>\x1b[33;1m %s: \x1b[0m%s \x1b[33;1m-> \x1b[0m%s\n", - res.Name, foreign[res.Name].Version(), res.Version) + if int64(res.LastModified) > foreign[res.Name].BuildDate().Unix() { + buffer.WriteString(fmt.Sprintf("\x1b[1m\x1b[32m==>\x1b[33;1m %s: \x1b[0m%s \x1b[33;1m-> \x1b[0m%s\n", + res.Name, foreign[res.Name].Version(), res.Version)) outdated = append(outdated, res) } } } + fmt.Println(buffer.String()) //If there are no outdated packages, don't prompt if len(outdated) == 0 { - fmt.Println("\n there is nothing to do") + fmt.Println("there is nothing to do") return nil } // Install updated packages - if !config.ContinueTask("\nProceed with upgrade?", "nN") { + if !config.ContinueTask("Proceed with upgrade?", "nN") { return nil } From fd6b2be76b2d03e5d2e727bee68d2541ecf324d5 Mon Sep 17 00:00:00 2001 From: Jguer Date: Tue, 16 May 2017 16:53:15 +0100 Subject: [PATCH 21/30] First version of fully working vcs updates --- README.md | 7 +++++++ aur/aur.go | 44 +++++++++++++++++++++++++++----------------- aur/result.go | 35 +++++++++++++++++++++++------------ aur/vcs/github.go | 32 +++++++++++++++++++++++++++----- yay.go | 3 +++ 5 files changed, 87 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 3fd14d05..1abee1c6 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,13 @@ Yay was created with a few objectives in mind and based on the design of yaourt ### Changelog +#### 2. +- Fetching backend changed to Mikkel Oscar's [Aur](https://github.com/mikkeloscar/aur) +- Added support for development packages from github. +- Pacman backend rewritten and simplified +- Added config framework. + + #### 1.115 - Added AUR completions (updates on first completion every 48h) diff --git a/aur/aur.go b/aur/aur.go index 71527ed8..eaac19c7 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -8,6 +8,7 @@ import ( "sort" "strings" + alpm "github.com/jguer/go-alpm" vcs "github.com/jguer/yay/aur/vcs" "github.com/jguer/yay/config" "github.com/jguer/yay/pacman" @@ -109,29 +110,31 @@ func CreateDevelDB() error { return err } -func DevelUpgrade(flags []string) { +func develUpgrade(foreign map[string]alpm.Package, flags []string) error { + fmt.Println(" Checking development packages...") + develUpdates := vcs.CheckUpdates(foreign) + if len(develUpdates) != 0 { + for _, q := range develUpdates { + fmt.Printf("\x1b[1m\x1b[32m==>\x1b[33;1m %s\x1b[0m\n", q) + } + // Install updated packages + if !config.ContinueTask("Proceed with upgrade?", "nN") { + return nil + } + err := Install(develUpdates, flags) + if err != nil { + fmt.Println(err) + } + } + + return nil } + // Upgrade tries to update every foreign package installed in the system func Upgrade(flags []string) error { fmt.Println("\x1b[1;36;1m::\x1b[0m\x1b[1m Starting AUR upgrade...\x1b[0m") - if config.YayConf.Devel { - fmt.Println(" Checking development packages...") - develUpdates := vcs.CheckUpdates() - if len(develUpdates) != 0 { - // Install updated packages - if !config.ContinueTask("\nProceed with upgrade?", "nN") { - return nil - } - - err := Install(develUpdates, flags) - if err != nil { - fmt.Println(err) - } - } - } - foreign, err := pacman.ForeignPackages() if err != nil { return err @@ -143,6 +146,13 @@ func Upgrade(flags []string) error { i++ } + if config.YayConf.Devel { + err := develUpgrade(foreign, flags) + if err != nil { + fmt.Println(err) + } + } + q, err := rpc.Info(keys) if err != nil { return err diff --git a/aur/result.go b/aur/result.go index 6c32f648..3f4edb0f 100644 --- a/aur/result.go +++ b/aur/result.go @@ -66,12 +66,7 @@ func printDeps(repoDeps []string, aurDeps []string) { } } -// PkgInstall handles install from Info Result. -func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []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") - } +func setupPackageSpace(a *rpc.Pkg) (err error) { dir := config.YayConf.BuildDir + a.PackageBase + "/" if _, err = os.Stat(dir); !os.IsNotExist(err) { @@ -99,11 +94,29 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { if err != nil { fmt.Println(err) } - vcs.SaveBranchInfo() } } } + err = os.Chdir(dir) + if err != nil { + return + } + + return +} + +// PkgInstall handles install from Info Result. +func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []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") + } + + if err = setupPackageSpace(a); err != nil { + return + } + if specialDBsauce { return } @@ -158,16 +171,14 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { } } - err = os.Chdir(dir) - if err != nil { - return - } - args := []string{"-sri"} args = append(args, flags...) makepkgcmd := exec.Command(config.YayConf.MakepkgBin, args...) makepkgcmd.Stdin, makepkgcmd.Stdout, makepkgcmd.Stderr = os.Stdin, os.Stdout, os.Stderr err = makepkgcmd.Run() + if err == nil { + _ = vcs.SaveBranchInfo() + } return } diff --git a/aur/vcs/github.go b/aur/vcs/github.go index 1bee875d..4329d858 100644 --- a/aur/vcs/github.go +++ b/aur/vcs/github.go @@ -6,6 +6,8 @@ import ( "net/http" "os" "strings" + + alpm "github.com/jguer/go-alpm" ) // branch contains the information of a repository branch @@ -103,10 +105,15 @@ func (info *Info) needsUpdate() bool { return false } -func CheckUpdates() (toUpdate []string) { +// CheckUpdates returns list of outdated packages +func CheckUpdates(foreign map[string]alpm.Package) (toUpdate []string) { for _, e := range savedInfo { if e.needsUpdate() { - toUpdate = append(toUpdate, e.Package) + if _, ok := foreign[e.Package]; ok { + toUpdate = append(toUpdate, e.Package) + } else { + RemovePackage([]string{e.Package}) + } } } return @@ -121,8 +128,23 @@ func inStore(url string) *Info { return nil } +// RemovePackage removes package from VCS information +func RemovePackage(pkgs []string) { + for _, pkgName := range pkgs { + for i, e := range savedInfo { + if e.Package == pkgName { + savedInfo[i] = savedInfo[len(savedInfo)-1] + savedInfo = savedInfo[:len(savedInfo)-1] + } + } + } + + _ = SaveBranchInfo() + return +} + // BranchInfo updates saved information -func BranchInfo(pkgname string, owner string, repo string) (err error) { +func BranchInfo(pkgName string, owner string, repo string) (err error) { Updated = true var newRepo branches url := "https://api.github.com/repos/" + owner + "/" + repo + "/branches" @@ -139,11 +161,11 @@ func BranchInfo(pkgname string, owner string, repo string) (err error) { for _, e := range newRepo { if e.Name == "master" { if packinfo != nil { - packinfo.Package = pkgname + packinfo.Package = pkgName packinfo.URL = url packinfo.SHA = e.Commit.SHA } else { - savedInfo = append(savedInfo, Info{Package: pkgname, URL: url, SHA: e.Commit.SHA}) + savedInfo = append(savedInfo, Info{Package: pkgName, URL: url, SHA: e.Commit.SHA}) } } } diff --git a/yay.go b/yay.go index 7ce900c3..f05a981b 100644 --- a/yay.go +++ b/yay.go @@ -137,6 +137,9 @@ func main() { err = numberMenu(pkgs, options) } default: + if op[0] == 'R' { + vcs.RemovePackage(pkgs) + } err = config.PassToPacman(op, pkgs, options) } From 9fa8c9265e740e5762c0c07afbfffe5b7c025669 Mon Sep 17 00:00:00 2001 From: Maxim Baz Date: Sun, 21 May 2017 15:49:29 +0200 Subject: [PATCH 22/30] Improve query list formatting --- pacman/pacman.go | 6 +++--- query.go | 6 +++--- yay.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pacman/pacman.go b/pacman/pacman.go index da32b714..ec801989 100644 --- a/pacman/pacman.go +++ b/pacman/pacman.go @@ -71,9 +71,9 @@ func (s Query) PrintSearch() { var toprint string if config.YayConf.SearchMode == config.NumberMenu { if config.YayConf.SortMode == config.BottomUp { - toprint += fmt.Sprintf("%d ", len(s)-i-1) + toprint += fmt.Sprintf("\x1b[33m%d\x1b[0m ", len(s)-i-1) } else { - toprint += fmt.Sprintf("%d ", i) + toprint += fmt.Sprintf("\x1b[33m%d\x1b[0m ", i) } } else if config.YayConf.SearchMode == config.Minimal { fmt.Println(res.Name()) @@ -93,7 +93,7 @@ func (s Query) PrintSearch() { } } - toprint += "\n" + res.Description() + toprint += "\n " + res.Description() fmt.Println(toprint) } } diff --git a/query.go b/query.go index 1afa3441..3a8e528a 100644 --- a/query.go +++ b/query.go @@ -17,9 +17,9 @@ func printAURSearch(q aur.Query, start int) { var toprint string if config.YayConf.SearchMode == config.NumberMenu { if config.YayConf.SortMode == config.BottomUp { - toprint += fmt.Sprintf("%d ", len(q)+start-i-1) + toprint += fmt.Sprintf("\x1b[33m%d\x1b[0m ", len(q)+start-i-1) } else { - toprint += fmt.Sprintf("%d ", start+i) + toprint += fmt.Sprintf("\x1b[33m%d\x1b[0m ", start+i) } } else if config.YayConf.SearchMode == config.Minimal { fmt.Println(res.Name) @@ -37,7 +37,7 @@ func printAURSearch(q aur.Query, start int) { if _, err := localDb.PkgByName(res.Name); err == nil { toprint += fmt.Sprintf("\x1b[32;40mInstalled\x1b[0m") } - toprint += "\n" + res.Description + toprint += "\n " + res.Description fmt.Println(toprint) } diff --git a/yay.go b/yay.go index f05a981b..568421cb 100644 --- a/yay.go +++ b/yay.go @@ -184,7 +184,7 @@ func numberMenu(pkgS []string, flags []string) (err error) { printAURSearch(aq, numpq) } - fmt.Printf("\x1b[32m%s\x1b[0m\nNumbers:", "Type numbers to install. Separate each number with a space.") + fmt.Printf("\x1b[32m%s\x1b[0m\nNumbers: ", "Type numbers to install. Separate each number with a space.") reader := bufio.NewReader(os.Stdin) numberBuf, overflow, err := reader.ReadLine() if err != nil || overflow { From 3905dd86a4a98d672450c570246212dfedca8e8f Mon Sep 17 00:00:00 2001 From: Jguer Date: Thu, 25 May 2017 00:28:35 +0100 Subject: [PATCH 23/30] By default yay uses Package Version for updates. Use --timeupdates to set updates based on modification time. Closes #9 --- aur/aur.go | 15 +++++++++++++-- config/config.go | 2 ++ yay.go | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/aur/aur.go b/aur/aur.go index 55a954ca..fbeabec8 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -167,7 +167,8 @@ func Upgrade(flags []string) error { if _, ok := foreign[res.Name]; ok { // Leaving this here for now, warn about downgrades later - if int64(res.LastModified) > foreign[res.Name].BuildDate().Unix() { + if (!config.YayConf.TimeUpdate && (int64(res.LastModified) > foreign[res.Name].BuildDate().Unix())) || + alpm.VerCmp(foreign[res.Name].Version(), res.Version) < 0 { buffer.WriteString(fmt.Sprintf("\x1b[1m\x1b[32m==>\x1b[33;1m %s: \x1b[0m%s \x1b[33;1m-> \x1b[0m%s\n", res.Name, foreign[res.Name].Version(), res.Version)) outdated = append(outdated, res) @@ -187,8 +188,18 @@ func Upgrade(flags []string) error { return nil } + var finalmdeps []string for _, pkgi := range outdated { - PkgInstall(&pkgi, flags) + mdeps, err := PkgInstall(&pkgi, flags) + finalmdeps = append(finalmdeps, mdeps...) + if err != nil { + fmt.Println(err) + } + } + + err = pacman.CleanRemove(finalmdeps) + if err != nil { + fmt.Println(err) } return nil diff --git a/config/config.go b/config/config.go index b566b105..f6b914ad 100644 --- a/config/config.go +++ b/config/config.go @@ -38,6 +38,7 @@ type Configuration struct { SearchMode int `json:"-"` SortMode int `json:"sortmode"` TarBin string `json:"tarbin"` + TimeUpdate bool `json:"versionupdate"` } // YayConf holds the current config values for yay. @@ -123,6 +124,7 @@ func defaultSettings(config *Configuration) { config.PacmanConf = "/etc/pacman.conf" config.SortMode = BottomUp config.TarBin = "/usr/bin/bsdtar" + config.TimeUpdate = false } // Editor returns the preferred system editor. diff --git a/yay.go b/yay.go index 568421cb..14666d39 100644 --- a/yay.go +++ b/yay.go @@ -68,6 +68,8 @@ func parser() (op string, options []string, packages []string, changedConfig boo config.YayConf.Devel = true case "--nodevel": config.YayConf.Devel = false + case "--timeupdates": + config.YayConf.TimeUpdate = true case "--topdown": config.YayConf.SortMode = config.TopDown case "--complete": From bdbf9c61071e8b50a48ddc92025d8f2932de831f Mon Sep 17 00:00:00 2001 From: Jguer Date: Thu, 25 May 2017 18:09:43 +0100 Subject: [PATCH 24/30] Fixes #25. --- pacman/pacman.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pacman/pacman.go b/pacman/pacman.go index ec801989..865b7a32 100644 --- a/pacman/pacman.go +++ b/pacman/pacman.go @@ -216,7 +216,7 @@ func CleanRemove(pkgName []string) (err error) { return nil } - err = config.PassToPacman("-Rsnc", pkgName, []string{"--noutil.Conf.rm"}) + err = config.PassToPacman("-Rsnc", pkgName, []string{"--noconfirm"}) return err } From 7a823c50d898a547c79f780f5913c23beadb713f Mon Sep 17 00:00:00 2001 From: Maxim Baz Date: Sun, 11 Jun 2017 22:50:39 +0200 Subject: [PATCH 25/30] Use pkgName to search for saved package info URL is not a unique identifier. Multiple installed packages can refer to the same github URL, like `alacritty-git` and `alacritty-terminfo-git`. The search must be thus based on the package name. --- aur/vcs/github.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aur/vcs/github.go b/aur/vcs/github.go index 4329d858..e4d58751 100644 --- a/aur/vcs/github.go +++ b/aur/vcs/github.go @@ -119,9 +119,9 @@ func CheckUpdates(foreign map[string]alpm.Package) (toUpdate []string) { return } -func inStore(url string) *Info { +func inStore(pkgName string) *Info { for i, e := range savedInfo { - if url == e.URL { + if pkgName == e.Package { return &savedInfo[i] } } @@ -156,7 +156,7 @@ func BranchInfo(pkgName string, owner string, repo string) (err error) { _ = json.NewDecoder(r.Body).Decode(&newRepo) - packinfo := inStore(url) + packinfo := inStore(pkgName) for _, e := range newRepo { if e.Name == "master" { From 5bae8e81a60e29a0b1464c0b0b5643d3e2ef84e9 Mon Sep 17 00:00:00 2001 From: Jguer Date: Wed, 14 Jun 2017 08:47:17 +0100 Subject: [PATCH 26/30] Refactoring --- aur/result.go | 10 +++++----- yay.go | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/aur/result.go b/aur/result.go index 3f4edb0f..03382b3d 100644 --- a/aur/result.go +++ b/aur/result.go @@ -66,7 +66,7 @@ func printDeps(repoDeps []string, aurDeps []string) { } } -func setupPackageSpace(a *rpc.Pkg) (err error) { +func setupPackageSpace(a *rpc.Pkg) (pkgbuild *gopkg.PKGBUILD, err error) { dir := config.YayConf.BuildDir + a.PackageBase + "/" if _, err = os.Stat(dir); !os.IsNotExist(err) { @@ -85,9 +85,9 @@ func setupPackageSpace(a *rpc.Pkg) (err error) { editcmd.Run() } - pkgb, err := gopkg.ParseSRCINFO(dir + ".SRCINFO") + pkgbuild, err = gopkg.ParseSRCINFO(dir + ".SRCINFO") if err == nil { - for _, pkgsource := range pkgb.Source { + for _, pkgsource := range pkgbuild.Source { owner, repo := vcs.ParseSource(pkgsource) if owner != "" && repo != "" { err = vcs.BranchInfo(a.Name, owner, repo) @@ -113,7 +113,8 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { fmt.Println("\x1b[1;31;40m==> Warning:\x1b[0;;40m This package is orphaned.\x1b[0m") } - if err = setupPackageSpace(a); err != nil { + _, err = setupPackageSpace(a) + if err != nil { return } @@ -236,7 +237,6 @@ func PrintInfo(a *rpc.Pkg) { if a.OutOfDate != 0 { fmt.Println("\x1b[1;37mOut-of-date :\x1b[0m", "Yes") } - } // RemoveMakeDeps receives a make dependency list and removes those diff --git a/yay.go b/yay.go index 14666d39..dd408c41 100644 --- a/yay.go +++ b/yay.go @@ -35,6 +35,8 @@ func usage() { --topdown shows repository's packages first and then aur's --bottomup shows aur's packages first and then repository's --noconfirm skip user input on package install + --devel Check -git/-svn/-hg development version + --nodevel Disable development version checking `) } @@ -91,7 +93,6 @@ func parser() (op string, options []string, packages []string, changedConfig boo } continue } - packages = append(packages, arg) } return From bebc82165334ba72ca2390fb8de6be7bae2eced5 Mon Sep 17 00:00:00 2001 From: Maxim Baz Date: Sat, 17 Jun 2017 19:18:44 +0200 Subject: [PATCH 27/30] Fix TimeUpdate param usage TimeUpdate is `false` by default. We want to compare modification time only when user changes this parameter to `true`. The current code seems to have inverted logic at the moment. --- aur/aur.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aur/aur.go b/aur/aur.go index fbeabec8..969d31fa 100644 --- a/aur/aur.go +++ b/aur/aur.go @@ -167,7 +167,7 @@ func Upgrade(flags []string) error { if _, ok := foreign[res.Name]; ok { // Leaving this here for now, warn about downgrades later - if (!config.YayConf.TimeUpdate && (int64(res.LastModified) > foreign[res.Name].BuildDate().Unix())) || + if (config.YayConf.TimeUpdate && (int64(res.LastModified) > foreign[res.Name].BuildDate().Unix())) || alpm.VerCmp(foreign[res.Name].Version(), res.Version) < 0 { buffer.WriteString(fmt.Sprintf("\x1b[1m\x1b[32m==>\x1b[33;1m %s: \x1b[0m%s \x1b[33;1m-> \x1b[0m%s\n", res.Name, foreign[res.Name].Version(), res.Version)) From 72cfd64e3601db61a0b53b45bf2225030bd130da Mon Sep 17 00:00:00 2001 From: Maxim Baz Date: Wed, 21 Jun 2017 09:41:54 +0200 Subject: [PATCH 28/30] Fix config name in json --- config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.go b/config/config.go index f6b914ad..42c35bec 100644 --- a/config/config.go +++ b/config/config.go @@ -38,7 +38,7 @@ type Configuration struct { SearchMode int `json:"-"` SortMode int `json:"sortmode"` TarBin string `json:"tarbin"` - TimeUpdate bool `json:"versionupdate"` + TimeUpdate bool `json:"timeupdate"` } // YayConf holds the current config values for yay. From eea82fb8eede692b7987b7e5dad44977bafb69fc Mon Sep 17 00:00:00 2001 From: Jguer Date: Fri, 23 Jun 2017 09:19:18 +0100 Subject: [PATCH 29/30] Added missing flag to timeupdate --- yay.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yay.go b/yay.go index dd408c41..c1e5e136 100644 --- a/yay.go +++ b/yay.go @@ -70,8 +70,10 @@ func parser() (op string, options []string, packages []string, changedConfig boo config.YayConf.Devel = true case "--nodevel": config.YayConf.Devel = false - case "--timeupdates": + case "--timeupdate": config.YayConf.TimeUpdate = true + case "--notimeupdate": + config.YayConf.TimeUpdate = false case "--topdown": config.YayConf.SortMode = config.TopDown case "--complete": From 812eca3aa55b1179c7b08a012d5efb64561338f0 Mon Sep 17 00:00:00 2001 From: Jguer Date: Fri, 23 Jun 2017 09:43:57 +0100 Subject: [PATCH 30/30] Fixes #29. Changed to MiB and KiB and added simple float --- pacman/pacman.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pacman/pacman.go b/pacman/pacman.go index 865b7a32..b60502cd 100644 --- a/pacman/pacman.go +++ b/pacman/pacman.go @@ -306,7 +306,7 @@ func BiggestPackages() { } for i := 0; i < 10; i++ { - fmt.Printf("%s: \x1B[0;33m%dMB\x1B[0m\n", pkgS[i].Name(), pkgS[i].ISize()/(1024*1024)) + fmt.Printf("%s: \x1B[0;33m%.1fMiB\x1B[0m\n", pkgS[i].Name(), float32(pkgS[i].ISize())/(1024.0*1024.0)) } // Could implement size here as well, but we just want the general idea } @@ -326,7 +326,8 @@ func HangingPackages() (hanging []string, err error) { requiredby := pkg.ComputeRequiredBy() if len(requiredby) == 0 { hanging = append(hanging, pkg.Name()) - fmt.Printf("%s: \x1B[0;33m%dMB\x1B[0m\n", pkg.Name(), pkg.ISize()/(1024*1024)) + fmt.Println(pkg.ISize()) + fmt.Printf("%s: \x1B[0;33m%.2f KiB\x1B[0m\n", pkg.Name(), float32(pkg.ISize())/(1024.0)) } return nil