Merge pull request #273 from Morganamilo/util

Add util.go and main.go
This commit is contained in:
J Guerreiro 2018-03-22 17:49:13 +01:00 committed by GitHub
commit 59b74e1253
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 358 additions and 389 deletions

221
cmd.go
View file

@ -3,16 +3,12 @@ package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"
alpm "github.com/jguer/go-alpm"
)
var cmdArgs = makeArguments()
@ -88,221 +84,6 @@ Yay specific options:
If no operation is provided -Y will be assumed`)
}
func initPaths() {
if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
if info, err := os.Stat(configHome); err == nil && info.IsDir() {
configHome = configHome + "/yay"
} else {
configHome = os.Getenv("HOME") + "/.config/yay"
}
} else {
configHome = os.Getenv("HOME") + "/.config/yay"
}
if cacheHome = os.Getenv("XDG_CACHE_HOME"); cacheHome != "" {
if info, err := os.Stat(cacheHome); err == nil && info.IsDir() {
cacheHome = cacheHome + "/yay"
} else {
cacheHome = os.Getenv("HOME") + "/.cache/yay"
}
} else {
cacheHome = os.Getenv("HOME") + "/.cache/yay"
}
configFile = configHome + "/" + configFileName
vcsFile = cacheHome + "/" + vcsFileName
completionFile = cacheHome + "/" + completionFilePrefix
}
func initConfig() (err error) {
defaultSettings(&config)
if _, err = os.Stat(configFile); os.IsNotExist(err) {
err = os.MkdirAll(filepath.Dir(configFile), 0755)
if err != nil {
err = fmt.Errorf("Unable to create config directory:\n%s\n"+
"The error was:\n%s", filepath.Dir(configFile), err)
return
}
// Save the default config if nothing is found
config.saveConfig()
} else {
cfile, errf := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE, 0644)
if errf != nil {
fmt.Printf("Error reading config: %s\n", err)
} else {
defer cfile.Close()
decoder := json.NewDecoder(cfile)
err = decoder.Decode(&config)
if err != nil {
fmt.Println("Loading default Settings.\nError reading config:",
err)
defaultSettings(&config)
}
}
}
return
}
func initVCS() (err error) {
if _, err = os.Stat(vcsFile); os.IsNotExist(err) {
err = os.MkdirAll(filepath.Dir(vcsFile), 0755)
if err != nil {
err = fmt.Errorf("Unable to create vcs directory:\n%s\n"+
"The error was:\n%s", filepath.Dir(configFile), err)
return
}
} else {
vfile, err := os.OpenFile(vcsFile, os.O_RDONLY|os.O_CREATE, 0644)
if err == nil {
defer vfile.Close()
decoder := json.NewDecoder(vfile)
_ = decoder.Decode(&savedInfo)
}
}
return
}
func initAlpm() (err error) {
var value string
var exists bool
//var double bool
value, _, exists = cmdArgs.getArg("config")
if exists {
config.PacmanConf = value
}
alpmConf, err = readAlpmConfig(config.PacmanConf)
if err != nil {
err = fmt.Errorf("Unable to read Pacman conf: %s", err)
return
}
value, _, exists = cmdArgs.getArg("dbpath", "b")
if exists {
alpmConf.DBPath = value
}
value, _, exists = cmdArgs.getArg("root", "r")
if exists {
alpmConf.RootDir = value
}
value, _, exists = cmdArgs.getArg("arch")
if exists {
alpmConf.Architecture = value
}
value, _, exists = cmdArgs.getArg("ignore")
if exists {
alpmConf.IgnorePkg = append(alpmConf.IgnorePkg, strings.Split(value, ",")...)
}
value, _, exists = cmdArgs.getArg("ignoregroup")
if exists {
alpmConf.IgnoreGroup = append(alpmConf.IgnoreGroup, strings.Split(value, ",")...)
}
//TODO
//current system does not allow duplicate arguments
//but pacman allows multiple cachdirs to be passed
//for now only handle one cache dir
value, _, exists = cmdArgs.getArg("cachdir")
if exists {
alpmConf.CacheDir = []string{value}
}
value, _, exists = cmdArgs.getArg("gpgdir")
if exists {
alpmConf.GPGDir = value
}
alpmHandle, err = alpmConf.CreateHandle()
if err != nil {
err = fmt.Errorf("Unable to CreateHandle: %s", err)
return
}
value, _, exists = cmdArgs.getArg("color")
if value == "always" || value == "auto" {
useColor = true
} else if value == "never" {
useColor = false
} else {
useColor = alpmConf.Options&alpm.ConfColor > 0
}
alpmHandle.SetQuestionCallback(questionCallback)
return
}
func main() {
var status int
var err error
if 0 == os.Geteuid() {
fmt.Println("Please avoid running yay as root/sudo.")
}
err = cmdArgs.parseCommandLine()
if err != nil {
fmt.Println(err)
status = 1
goto cleanup
}
initPaths()
err = initConfig()
if err != nil {
fmt.Println(err)
status = 1
goto cleanup
}
err = initVCS()
if err != nil {
fmt.Println(err)
status = 1
goto cleanup
}
err = initAlpm()
if err != nil {
fmt.Println(err)
status = 1
goto cleanup
}
err = handleCmd()
if err != nil {
fmt.Println(err)
status = 1
goto cleanup
}
cleanup:
//cleanup
//from here on out dont exit if an error occurs
//if we fail to save the configuration
//at least continue on and try clean up other parts
if alpmHandle != nil {
err = alpmHandle.Release()
if err != nil {
fmt.Println(err)
status = 1
}
}
os.Exit(status)
}
func sudoLoopBackground() {
updateSudo()
go sudoLoop()
@ -365,7 +146,7 @@ func handleCmd() (err error) {
case "T", "deptest":
err = passToPacman(cmdArgs)
case "U", "upgrade":
err =passToPacman(cmdArgs)
err = passToPacman(cmdArgs)
case "G", "getpkgbuild":
err = handleGetpkgbuild()
case "P", "print":

View file

@ -12,14 +12,6 @@ import (
// Checks a single conflict against every other to be installed package's
// name and its provides.
func checkInnerConflict(name string, conflict string, conflicts map[string]stringSet, dc *depCatagories) {
add := func(h map[string]stringSet, n string, v string) {
_, ok := h[n]
if !ok {
h[n] = make(stringSet)
}
h[n].set(v)
}
deps, err := gopkg.ParseDeps([]string{conflict})
if err != nil {
return
@ -36,7 +28,7 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin
return
}
if dep.Name == pkg.Name && version.Satisfies(dep) {
add(conflicts, name, pkg.Name)
addMapStringSet(conflicts, name, pkg.Name)
continue
}
@ -65,7 +57,7 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin
}
if version != nil && version.Satisfies(dep) {
add(conflicts, name, pkg.Name)
addMapStringSet(conflicts, name, pkg.Name)
break
}
@ -83,7 +75,7 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin
}
if dep.Name == pkg.Name() && version.Satisfies(dep) {
add(conflicts, name, pkg.Name())
addMapStringSet(conflicts, name, pkg.Name())
continue
}
@ -100,7 +92,7 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin
}
if provide.Mod == alpm.DepModAny {
add(conflicts, name, pkg.Name())
addMapStringSet(conflicts, name, pkg.Name())
return fmt.Errorf("")
}
@ -109,8 +101,8 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin
return nil
}
if version.Satisfies(dep) {
add(conflicts, name, pkg.Name())
if version.Satisfies(dep) {
addMapStringSet(conflicts, name, pkg.Name())
return fmt.Errorf("")
}
@ -121,7 +113,7 @@ func checkInnerConflict(name string, conflict string, conflicts map[string]strin
// Checks every to be installed package's conflicts against every other to be
// installed package and its provides.
func checkForInnerConflicts(dc *depCatagories) (map[string]stringSet) {
func checkForInnerConflicts(dc *depCatagories) map[string]stringSet {
conflicts := make(map[string]stringSet)
for _, pkg := range dc.Aur {
@ -143,14 +135,6 @@ func checkForInnerConflicts(dc *depCatagories) (map[string]stringSet) {
// Checks a provide or packagename from a to be installed package
// against every already installed package's conflicts
func checkReverseConflict(name string, provide string, conflicts map[string]stringSet) error {
add := func(h map[string]stringSet, n string, v string) {
_, ok := h[n]
if !ok {
h[n] = make(stringSet)
}
h[n].set(v)
}
var version *gopkg.CompleteVersion
var err error
@ -167,7 +151,6 @@ func checkReverseConflict(name string, provide string, conflicts map[string]stri
}
}
localDb.PkgCache().ForEach(func(pkg alpm.Package) error {
if name == pkg.Name() {
return nil
@ -191,9 +174,9 @@ func checkReverseConflict(name string, provide string, conflicts map[string]stri
return nil
}
if version == nil || version.Satisfies(dep) {
if version == nil || version.Satisfies(dep) {
// Todo
add(conflicts, name, pkg.Name() + " (" + provide + ")")
addMapStringSet(conflicts, name, pkg.Name()+" ("+provide+")")
return fmt.Errorf("")
}
@ -209,14 +192,6 @@ func checkReverseConflict(name string, provide string, conflicts map[string]stri
// Checks the conflict of a to be installed package against the package name and
// provides of every installed package.
func checkConflict(name string, conflict string, conflicts map[string]stringSet) error {
add := func(h map[string]stringSet, n string, v string) {
_, ok := h[n]
if !ok {
h[n] = make(stringSet)
}
h[n].set(v)
}
localDb, err := alpmHandle.LocalDb()
if err != nil {
return err
@ -240,7 +215,7 @@ func checkConflict(name string, conflict string, conflicts map[string]stringSet)
}
if dep.Name == pkg.Name() && version.Satisfies(dep) {
add(conflicts, name, pkg.Name())
addMapStringSet(conflicts, name, pkg.Name())
return nil
}
@ -257,7 +232,7 @@ func checkConflict(name string, conflict string, conflicts map[string]stringSet)
}
if provide.Mod == alpm.DepModAny {
add(conflicts, name, pkg.Name() + " (" + provide.Name + ")")
addMapStringSet(conflicts, name, pkg.Name()+" ("+provide.Name+")")
return fmt.Errorf("")
}
@ -267,7 +242,7 @@ func checkConflict(name string, conflict string, conflicts map[string]stringSet)
}
if version.Satisfies(dep) {
add(conflicts, name, pkg.Name() + " (" + provide.Name + ")")
addMapStringSet(conflicts, name, pkg.Name()+" ("+provide.Name+")")
return fmt.Errorf("")
}
@ -283,7 +258,7 @@ func checkConflict(name string, conflict string, conflicts map[string]stringSet)
// Checks every to be installed package's conflicts against the names and
// provides of every already installed package and checks every to be installed
// package's name and provides against every already installed package.
func checkForConflicts(dc *depCatagories) (map[string]stringSet, error) {
func checkForConflicts(dc *depCatagories) (map[string]stringSet, error) {
conflicts := make(map[string]stringSet)
for _, pkg := range dc.Aur {
@ -326,13 +301,13 @@ func checkForAllConflicts(dc *depCatagories) error {
var wg sync.WaitGroup
wg.Add(2)
fmt.Println(bold(cyan("::")+ " Checking for conflicts..."))
fmt.Println(bold(cyan("::") + " Checking for conflicts..."))
go func() {
conflicts, err = checkForConflicts(dc)
wg.Done()
}()
fmt.Println(bold(cyan("::")+ " Checking for inner conflicts..."))
fmt.Println(bold(cyan("::") + " Checking for inner conflicts..."))
go func() {
innerConflicts = checkForInnerConflicts(dc)
wg.Done()

View file

@ -472,14 +472,6 @@ func checkVersions(dt *depTree) error {
depStrings := make([]string, 0)
has := make(map[string][]string)
add := func(h map[string][]string, n string, v string) {
_, ok := h[n]
if !ok {
h[n] = make([]string, 0, 1)
}
h[n] = append(h[n], v)
}
for _, pkg := range dt.Aur {
for _, deps := range [3][]string{pkg.Depends, pkg.MakeDepends, pkg.CheckDepends} {
for _, dep := range deps {
@ -490,12 +482,12 @@ func checkVersions(dt *depTree) error {
}
}
add(has, pkg.Name, pkg.Version)
addMapStringSlice(has, pkg.Name, pkg.Version)
for _, name := range pkg.Provides {
_name, _ver := splitNameFromDep(name)
if _ver != "" {
add(has, _name, _ver)
addMapStringSlice(has, _name, _ver)
} else {
delete(has, _name)
}
@ -510,11 +502,11 @@ func checkVersions(dt *depTree) error {
return nil
})
add(has, pkg.Name(), pkg.Version())
addMapStringSlice(has, pkg.Name(), pkg.Version())
pkg.Provides().ForEach(func(dep alpm.Depend) error {
if dep.Mod != alpm.DepModAny {
add(has, dep.Name, dep.Version)
addMapStringSlice(has, dep.Name, dep.Version)
} else {
delete(has, dep.Name)
}

View file

@ -3,7 +3,6 @@ package main
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"os/exec"
"strconv"
@ -676,23 +675,3 @@ func clean(pkgs []*rpc.Pkg) {
os.RemoveAll(dir)
}
}
func completeFileName(dir, name string) (string, error) {
files, err := ioutil.ReadDir(dir)
if err != nil {
return "", err
}
for _, file := range files {
if file.IsDir() {
continue
}
if strings.HasPrefix(file.Name(), name) {
return dir + file.Name(), nil
}
}
return "", nil
}

226
main.go Normal file
View file

@ -0,0 +1,226 @@
package main
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
alpm "github.com/jguer/go-alpm"
)
func initPaths() {
if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
if info, err := os.Stat(configHome); err == nil && info.IsDir() {
configHome = configHome + "/yay"
} else {
configHome = os.Getenv("HOME") + "/.config/yay"
}
} else {
configHome = os.Getenv("HOME") + "/.config/yay"
}
if cacheHome = os.Getenv("XDG_CACHE_HOME"); cacheHome != "" {
if info, err := os.Stat(cacheHome); err == nil && info.IsDir() {
cacheHome = cacheHome + "/yay"
} else {
cacheHome = os.Getenv("HOME") + "/.cache/yay"
}
} else {
cacheHome = os.Getenv("HOME") + "/.cache/yay"
}
configFile = configHome + "/" + configFileName
vcsFile = cacheHome + "/" + vcsFileName
completionFile = cacheHome + "/" + completionFilePrefix
}
func initConfig() (err error) {
defaultSettings(&config)
if _, err = os.Stat(configFile); os.IsNotExist(err) {
err = os.MkdirAll(filepath.Dir(configFile), 0755)
if err != nil {
err = fmt.Errorf("Unable to create config directory:\n%s\n"+
"The error was:\n%s", filepath.Dir(configFile), err)
return
}
// Save the default config if nothing is found
config.saveConfig()
} else {
cfile, errf := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE, 0644)
if errf != nil {
fmt.Printf("Error reading config: %s\n", err)
} else {
defer cfile.Close()
decoder := json.NewDecoder(cfile)
err = decoder.Decode(&config)
if err != nil {
fmt.Println("Loading default Settings.\nError reading config:",
err)
defaultSettings(&config)
}
}
}
return
}
func initVCS() (err error) {
if _, err = os.Stat(vcsFile); os.IsNotExist(err) {
err = os.MkdirAll(filepath.Dir(vcsFile), 0755)
if err != nil {
err = fmt.Errorf("Unable to create vcs directory:\n%s\n"+
"The error was:\n%s", filepath.Dir(configFile), err)
return
}
} else {
vfile, err := os.OpenFile(vcsFile, os.O_RDONLY|os.O_CREATE, 0644)
if err == nil {
defer vfile.Close()
decoder := json.NewDecoder(vfile)
_ = decoder.Decode(&savedInfo)
}
}
return
}
func initAlpm() (err error) {
var value string
var exists bool
//var double bool
value, _, exists = cmdArgs.getArg("config")
if exists {
config.PacmanConf = value
}
alpmConf, err = readAlpmConfig(config.PacmanConf)
if err != nil {
err = fmt.Errorf("Unable to read Pacman conf: %s", err)
return
}
value, _, exists = cmdArgs.getArg("dbpath", "b")
if exists {
alpmConf.DBPath = value
}
value, _, exists = cmdArgs.getArg("root", "r")
if exists {
alpmConf.RootDir = value
}
value, _, exists = cmdArgs.getArg("arch")
if exists {
alpmConf.Architecture = value
}
value, _, exists = cmdArgs.getArg("ignore")
if exists {
alpmConf.IgnorePkg = append(alpmConf.IgnorePkg, strings.Split(value, ",")...)
}
value, _, exists = cmdArgs.getArg("ignoregroup")
if exists {
alpmConf.IgnoreGroup = append(alpmConf.IgnoreGroup, strings.Split(value, ",")...)
}
//TODO
//current system does not allow duplicate arguments
//but pacman allows multiple cachdirs to be passed
//for now only handle one cache dir
value, _, exists = cmdArgs.getArg("cachdir")
if exists {
alpmConf.CacheDir = []string{value}
}
value, _, exists = cmdArgs.getArg("gpgdir")
if exists {
alpmConf.GPGDir = value
}
alpmHandle, err = alpmConf.CreateHandle()
if err != nil {
err = fmt.Errorf("Unable to CreateHandle: %s", err)
return
}
value, _, exists = cmdArgs.getArg("color")
if value == "always" || value == "auto" {
useColor = true
} else if value == "never" {
useColor = false
} else {
useColor = alpmConf.Options&alpm.ConfColor > 0
}
alpmHandle.SetQuestionCallback(questionCallback)
return
}
func main() {
var status int
var err error
if 0 == os.Geteuid() {
fmt.Println("Please avoid running yay as root/sudo.")
}
err = cmdArgs.parseCommandLine()
if err != nil {
fmt.Println(err)
status = 1
goto cleanup
}
initPaths()
err = initConfig()
if err != nil {
fmt.Println(err)
status = 1
goto cleanup
}
err = initVCS()
if err != nil {
fmt.Println(err)
status = 1
goto cleanup
}
err = initAlpm()
if err != nil {
fmt.Println(err)
status = 1
goto cleanup
}
err = handleCmd()
if err != nil {
fmt.Println(err)
status = 1
goto cleanup
}
cleanup:
//cleanup
//from here on out dont exit if an error occurs
//if we fail to save the configuration
//at least continue on and try clean up other parts
if alpmHandle != nil {
err = alpmHandle.Release()
if err != nil {
fmt.Println(err)
status = 1
}
}
os.Exit(status)
}

View file

@ -582,34 +582,6 @@ func (parser *arguments) parseCommandLine() (err error) {
return
}
type intRange struct {
min int
max int
}
func makeIntRange(min, max int) intRange {
return intRange{
min,
max,
}
}
func (r intRange) get(n int) bool {
return n >= r.min && n <= r.max
}
type intRanges []intRange
func (rs intRanges) get(n int) bool {
for _, r := range rs {
if r.get(n) {
return true
}
}
return false
}
//parses input for number menus
//supports individual selection: 1 2 3 4
//supports range selections: 1-4 10-20

View file

@ -333,7 +333,7 @@ func printUpdateList(parser *arguments) error {
}
for pkg := range parser.targets {
fmt.Println(red(bold("error:")), "package '" + pkg + "' was not found")
fmt.Println(red(bold("error:")), "package '"+pkg+"' was not found")
}
return nil

View file

@ -331,20 +331,6 @@ func statistics() (info struct {
return
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a < b {
return b
}
return a
}
// Queries the aur for information about specified packages.
// All packages should be queried in a single rpc request except when the number
// of packages exceeds the number set in config.RequestSplitN.

View file

@ -4,10 +4,9 @@ import (
"bufio"
"fmt"
"os"
"strings"
"sort"
"strings"
"sync"
"unicode"
alpm "github.com/jguer/go-alpm"
pkgb "github.com/mikkeloscar/gopkgbuild"
@ -39,32 +38,6 @@ func (u upSlice) Less(i, j int) bool {
}
}
func lessRunes(iRunes, jRunes []rune) bool {
max := len(iRunes)
if max > len(jRunes) {
max = len(jRunes)
}
for idx := 0; idx < max; idx++ {
ir := iRunes[idx]
jr := jRunes[idx]
lir := unicode.ToLower(ir)
ljr := unicode.ToLower(jr)
if lir != ljr {
return lir < ljr
}
// the lowercase runes are the same, so compare the original
if ir != jr {
return ir < jr
}
}
return len(iRunes) < len(jRunes)
}
func getVersionDiff(oldVersion, newversion string) (left, right string) {
old, errOld := pkgb.NewCompleteVersion(oldVersion)
new, errNew := pkgb.NewCompleteVersion(newversion)
@ -117,7 +90,6 @@ func upList(dt *depTree) (aurUp upSlice, repoUp upSlice, err error) {
wg.Done()
}()
if config.Devel {
fmt.Println(bold(cyan("::") + " Checking development packages..."))
wg.Add(1)
@ -127,7 +99,6 @@ func upList(dt *depTree) (aurUp upSlice, repoUp upSlice, err error) {
}()
}
wg.Wait()
errs := make([]string, 0)
@ -256,29 +227,6 @@ func upRepo(local []alpm.Package) (upSlice, error) {
return slice, nil
}
//Contains returns whether e is present in s
func containsInt(s []int, e int) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
// RemoveIntListFromList removes all src's elements that are present in target
func removeIntListFromList(src, target []int) []int {
max := len(target)
for i := 0; i < max; i++ {
if containsInt(src, target[i]) {
target = append(target[:i], target[i+1:]...)
max--
i--
}
}
return target
}
// upgradePkgs handles updating the cache and installing updates.
func upgradePkgs(dt *depTree) (stringSet, stringSet, error) {
ignore := make(stringSet)

110
utils.go Normal file
View file

@ -0,0 +1,110 @@
package main
import (
"io/ioutil"
"strings"
"unicode"
)
type intRange struct {
min int
max int
}
func makeIntRange(min, max int) intRange {
return intRange{
min,
max,
}
}
func (r intRange) get(n int) bool {
return n >= r.min && n <= r.max
}
type intRanges []intRange
func (rs intRanges) get(n int) bool {
for _, r := range rs {
if r.get(n) {
return true
}
}
return false
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a < b {
return b
}
return a
}
func addMapStringSet(h map[string]stringSet, n string, v string) {
_, ok := h[n]
if !ok {
h[n] = make(stringSet)
}
h[n].set(v)
}
func addMapStringSlice(h map[string][]string, n string, v string) {
_, ok := h[n]
if !ok {
h[n] = make([]string, 0, 1)
}
h[n] = append(h[n], v)
}
func completeFileName(dir, name string) (string, error) {
files, err := ioutil.ReadDir(dir)
if err != nil {
return "", err
}
for _, file := range files {
if file.IsDir() {
continue
}
if strings.HasPrefix(file.Name(), name) {
return dir + file.Name(), nil
}
}
return "", nil
}
func lessRunes(iRunes, jRunes []rune) bool {
max := len(iRunes)
if max > len(jRunes) {
max = len(jRunes)
}
for idx := 0; idx < max; idx++ {
ir := iRunes[idx]
jr := jRunes[idx]
lir := unicode.ToLower(ir)
ljr := unicode.ToLower(jr)
if lir != ljr {
return lir < ljr
}
// the lowercase runes are the same, so compare the original
if ir != jr {
return ir < jr
}
}
return len(iRunes) < len(jRunes)
}