From 19efb1f1211a61813f26daa82681fa99fcfe6f8a Mon Sep 17 00:00:00 2001 From: morganamilo Date: Sun, 31 Dec 2017 15:18:12 +0000 Subject: [PATCH 01/12] Foundation for re writing the argument parsing system Currently the foundation for a new fuller argument parsing has been implemented in parser.go. Most of the parsing is now done through the argParser object instead of seperate arrays for options and packages. The rest of the code still expects the old system so I have left most of the operations unimplemented for now until I redo it with the new system. Currently only '-S' and number menu have any functionality for testing purposes. This new system parses arguments fully instead of just looking for predefined strings such as: '-Sqi' '-Siq'. This allows: '-Syu', '-S -y -u', '--sync -y -u' to all be parsed as the same. This system tries to be as similar to pacman as possible, eventually aming to fully wrap pacman, allowing yay to be used instead of pacman in all instances. The current implementation is not as strict as pacman when checking arguments. If you pass --someinvalidflag to yay then yay will simply ignore it. The flag should still be passed to pacman which should then cause an error. Although operations '-S' '-R' '-U' ect. are checked to make sure you can not try to use two operations at once. conflicting flags such as: '--quiet' and '--info' will not raise an error and which options gains precedence is depend on the implementation. Another minor issue which is worth noting is. Due to the way double arguments are parsed: '-dd' '-cc' '--deps --deps' if you pass the long version and the short version: '-d --deps' yay will not realize its a double argument. Meanwhile pacman will reconise it when yay calls pacman. Currently there are a few things that need to be done before this new system can be fuly released: Reimplement all operations to use to new parsing system so that the new system is at least as functional as the old one Strip yay specific flags before passing them to pacman Move parts of config into the argument system and only use config for options that are meant to be saved to disk Move yay specific operations into its own operator '-Y' Update documentation to show the altered syntax --- cmd.go | 317 ++++++++++++++++++++++++++++++------------------------ parser.go | 297 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 471 insertions(+), 143 deletions(-) create mode 100644 parser.go diff --git a/cmd.go b/cmd.go index 1884c448..6c6dee23 100644 --- a/cmd.go +++ b/cmd.go @@ -136,174 +136,205 @@ func init() { } } -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 len(arg) < 2 { - continue - } - if arg[0] == '-' && arg[1] != '-' { - switch arg { - case "-V": - arg = "--version" - case "-h": - arg = "--help" - default: - op = arg - continue - } - } - - if strings.HasPrefix(arg, "--") { - changedConfig = true - switch arg { - case "--afterclean": - config.CleanAfter = true - case "--noafterclean": - config.CleanAfter = false - case "--printconfig": - fmt.Printf("%#v", config) - os.Exit(0) - case "--gendb": - err = createDevelDB() - if err != nil { - fmt.Println(err) - } - err = saveVCSInfo() - if err != nil { - fmt.Println(err) - } - os.Exit(0) - case "--devel": - config.Devel = true - case "--nodevel": - config.Devel = false - case "--timeupdate": - config.TimeUpdate = true - case "--notimeupdate": - config.TimeUpdate = false - case "--topdown": - config.SortMode = TopDown - case "--complete": - config.Shell = "sh" - _ = complete() - os.Exit(0) - case "--fcomplete": - config.Shell = fishShell - _ = complete() - os.Exit(0) - case "--help": - usage() - os.Exit(0) - case "--version": - fmt.Printf("yay v%s\n", version) - os.Exit(0) - case "--noconfirm": - config.NoConfirm = true - fallthrough - default: - options = append(options, arg) - } - continue - } - packages = append(packages, arg) - } - return -} - func main() { - op, options, pkgs, changedConfig, err := parser() + var err error + var changedConfig bool + + parser := makeArgParser(); + err = parser.parseCommandLine(); + if err != nil { fmt.Println(err) os.Exit(1) } + + if parser.existsArg("-") { + err = parser.parseStdin(); - 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() - case "-Ss", "-Ssq", "-Sqs": - if op == "-Ss" { - config.SearchMode = Detailed - } else { - config.SearchMode = Minimal - } - - if pkgs != nil { - err = syncSearch(pkgs) - } - case "-S": - err = install(pkgs, options) - case "-Sy": - err = passToPacman("-Sy", nil, nil) if err != nil { - break + fmt.Println(err) + os.Exit(1) } - err = install(pkgs, options) - case "-Syu", "-Suy", "-Su": - if strings.Contains(op, "y") { - err = passToPacman("-Sy", nil, nil) - if err != nil { - break - } - } - err = upgradePkgs(options) - case "-Si": - err = syncInfo(pkgs, options) - case "yogurt": - config.SearchMode = NumberMenu - - if pkgs != nil { - err = numberMenu(pkgs, options) - } - default: - if op[0] == 'R' { - removeVCSPackage(pkgs) - } - err = passToPacman(op, pkgs, options) } - - var erra error + + fmt.Println(parser) + + changedConfig, err = handleCmd(parser) + + if err != nil { + fmt.Println(err) + } + if updated { - erra = saveVCSInfo() - if erra != nil { + err = saveVCSInfo() + + if err != nil { fmt.Println(err) } } if changedConfig { - erra = config.saveConfig() - if erra != nil { + err = config.saveConfig() + + if err != nil { fmt.Println(err) } } - erra = alpmHandle.Release() - if erra != nil { - fmt.Println(err) - } - + err = alpmHandle.Release() if err != nil { fmt.Println(err) - os.Exit(1) } } +func handleCmd(parser *argParser) (changedConfig bool, err error) { + var _changedConfig bool + + for option, _ := range parser.options { + _changedConfig, err = handleConfig(option) + + if err != nil { + return + } + + if _changedConfig { + changedConfig = true + } + } + + switch parser.op { + case "V", "version": + handleVersion() + case "D", "database": + //passToPacman() + case "F", "files": + //passToPacman() + case "Q", "query": + //passToPacman() + case "R", "remove": + // + case "S", "sync": + err = handleSync(parser) + case "T", "deptest": + //passToPacman() + case "U", "upgrade": + //passToPacman() + case "Y", "--yay": + err = handleYogurt(parser) + default: + //this means we allowed an op but not implement it + //if this happens it an error in the code and not the usage + err = fmt.Errorf("unhandled operation") + } + + return +} + +//this function should only set config options +//but currently still uses the switch left over from old code +//eventuall this should be refactored out futher +//my current plan is to have yay specific operations in its own operator +//e.g. yay -Y --gendb +//e.g yay -Yg +func handleConfig(option string) (changedConfig bool, err error) { + switch option { + case "afterclean": + config.CleanAfter = true + case "noafterclean": + config.CleanAfter = false + case "printconfig": + fmt.Printf("%#v", config) + os.Exit(0) + case "gendb": + err = createDevelDB() + if err != nil { + fmt.Println(err) + } + err = saveVCSInfo() + if err != nil { + fmt.Println(err) + } + os.Exit(0) + case "devel": + config.Devel = true + case "nodevel": + config.Devel = false + case "timeupdate": + config.TimeUpdate = true + case "notimeupdate": + config.TimeUpdate = false + case "topdown": + config.SortMode = TopDown + case "complete": + config.Shell = "sh" + complete() + os.Exit(0) + case "fcomplete": + config.Shell = fishShell + complete() + os.Exit(0) + case "help": + usage() + os.Exit(0) + case "version": + fmt.Printf("yay v%s\n", version) + os.Exit(0) + case "noconfirm": + config.NoConfirm = true + default: + return + } + + changedConfig = true + return +} + +func handleVersion() { + usage() +} + +func handleYogurt(parser *argParser) (err error) { + _, options, targets := parser.formatArgs() + + config.SearchMode = NumberMenu + err = numberMenu(targets, options) + + return +} + +func handleSync(parser *argParser) (err error) { + op, options, targets := parser.formatArgs() + + fmt.Println("op", op) + fmt.Println("options", options) + fmt.Println("targets", targets) + + if parser.existsArg("y") { + err = passToPacman("-Sy", nil, nil) + if err != nil { + return + } + } + + if parser.existsArg("s") { + if parser.existsArg("i") { + config.SearchMode = Detailed + } else { + config.SortMode = Minimal + } + + err = syncSearch(targets) + } + + if len(targets) > 0 { + err = install(targets, options) + } + + return +} + + // NumberMenu presents a CLI for selecting packages to install. func numberMenu(pkgS []string, flags []string) (err error) { var num int diff --git a/parser.go b/parser.go new file mode 100644 index 00000000..4cf8ab58 --- /dev/null +++ b/parser.go @@ -0,0 +1,297 @@ +package main + +import ( + "os" + "fmt" + "strings" + "io" +) + +type argParser struct { + op string + options map[string]string + doubles map[string]struct{} //tracks args passed twice such as -yy and -dd + targets map[string]struct{} +} + +func makeArgParser() *argParser { + return &argParser { + "", + make(map[string]string), + make(map[string]struct{}), + make(map[string]struct{}), + } +} + +func (praser *argParser) delArg(option string) { + delete(praser.options, option) + delete(praser.doubles, option) +} + +func (praser *argParser) addOP(op string) (err error) { + if praser.op != "" { + err = fmt.Errorf("only one operation may be used at a time") + return + } + + praser.op = op + return +} + +func (praser *argParser) addParam(option string, arg string) (err error) { + if isOp(option) { + err = praser.addOP(option) + return + } + + if praser.existsArg(option) { + praser.doubles[option] = struct{}{} + } else { + praser.options[option] = arg + } + + return +} + +func (praser *argParser) addArg(option string) (err error) { + err = praser.addParam(option, "") + return +} + +func (praser *argParser) existsArg(option string) (ok bool) { + _, ok = praser.options[option] + return ok +} + +func (praser *argParser) getArg(option string) (arg string, double bool, exists bool) { + arg, exists = praser.options[option] + _, double = praser.doubles[option] + return +} + +func (praser *argParser) addTarget(target string) { + praser.targets[target] = struct{}{} +} + +func (praser *argParser) delTarget(target string) { + delete(praser.targets, target) +} + +func (parser *argParser) existsDouble(option string) bool { + _, ok := parser.doubles[option] + return ok +} + +func (parser *argParser) formatArgs() (op string, options []string, targets []string) { + op = formatArg(parser.op) + + for option, arg := range parser.options { + option = formatArg(option) + options = append(options, option) + + if arg != "" { + options = append(options, arg) + } + + if parser.existsDouble(option) { + options = append(options, option) + } + } + + for target := range parser.targets { + targets = append(targets, target) + } + + return + +} + +func formatArg(arg string) string { + if len(arg) > 1 { + arg = "--" + arg + } else { + arg = "-" + arg + } + + return arg +} + +func isOp(op string) bool { + switch op { + case "V", "version": + return true + case "D", "database": + return true + case "F", "files": + return true + case "Q", "query": + return true + case "R", "remove": + return true + case "S", "sync": + return true + case "T", "deptest": + return true + case "U", "upgrade": + return true + case "Y", "yay": + return true + default: + return false + } +} + +func hasParam(arg string) bool { + switch arg { + case "dbpath", "b": + return true + case "root", "r": + return true + case "sysroot": + return true + case "config": + return true + case "ignore": + return true + case "assume-installed": + return true + case "overwrite": + return true + case "ask": + return true + case "cachedir": + return true + case "hookdir": + return true + case "logfile": + return true + case "ignoregroup": + return true + case "arch": + return true + case "print-format": + return true + case "gpgdir": + return true + case "color": + return true + default: + return false + } +} + +//parses short hand options such as: +//-Syu -b/some/path - +func (parser *argParser) parseShortOption(arg string, param string) (usedNext bool, err error) { + if arg == "-" { + err = parser.addArg("-") + return + } + + arg = arg[1:] + + for k, _char := range arg { + char := string(_char) + + if hasParam(char) { + if k < len(arg) - 2 { + err = parser.addParam(char, arg[k+2:]) + } else { + usedNext = true + err = parser.addParam(char, param) + } + + break + } else { + err = parser.addArg(char) + + if err != nil { + return + } + } + } + + return +} + +//parses full length options such as: +//--sync --refresh --sysupgrade --dbpath /some/path -- +func (parser *argParser) parseLongOption(arg string, param string) (usedNext bool, err error){ + if arg == "--" { + err = parser.addArg(arg) + return + } + + arg = arg[2:] + + if hasParam(arg) { + err = parser.addParam(arg, param) + usedNext = true + } else { + err = parser.addArg(arg) + } + + return +} + +func (parser *argParser) parseStdin() (err error) { + for true { + var target string + _, err = fmt.Scan(&target) + + if err != nil { + if err == io.EOF { + err = nil + } + + return + } + + parser.addTarget(target) + } + + return +} + +func (parser *argParser)parseCommandLine() (err error) { + args := os.Args[1:] + usedNext := false + + if len(args) < 1 { + err = fmt.Errorf("no operation specified (use -h for help)") + return + } + + for k, arg := range args { + var nextArg string + + if usedNext { + usedNext = false + continue + } + + if k + 1 < len(args) { + nextArg = args[k + 1] + } + + if parser.existsArg("--") { + parser.addTarget(arg) + } else if strings.HasPrefix(arg, "--") { + usedNext, err = parser.parseLongOption(arg, nextArg) + } else if strings.HasPrefix(arg, "-") { + usedNext, err = parser.parseShortOption(arg, nextArg) + } else { + parser.addTarget(arg) + } + + if err != nil { + return + } + } + + if parser.op == "" { + parser.op = "Y" + } + + return +} \ No newline at end of file From 765b76733335c442daffbf46f8d0ee429fd7faf8 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 3 Jan 2018 04:55:47 +0000 Subject: [PATCH 02/12] Rework some of the yay specific operations Some of the yay specific operations such as: '-Qstats' '-Cd' Break the standard pacamn has set. Most yay specific specific options have been moved into their own operator: '-Y' '--yay' '-Qstats' -> '-Y --stats' '--Cd' -> '-Y --cleandeps' '--gendb' -> '-Y --gendb' Although: '-G' has been kepts and and alias has been added for is: '--getpkgbuild' This shouldnt feel too different for most people given that yay will default to: '-Y' when no operator has been specified. So calls like: 'yay --gendb' will still work as they did. Internally handleConfig has been partially refactored. Now all that remians in setters for config. All flags that did anything beond setting config have been moved to handleYay(). This means less nasty os.Exit()'s and nicer flow control. The usage has also been updated. The options changes have been added but the layout has also been tweaked a bit. Lastly on the things not done: Man page has not been updated Shell completion has not been updated This will be done in further commits as the usage is not guaranteed to stay the same between now the completion of the argument system. --- cmd.go | 154 ++++++++++++++++++++++++++++++++++-------------------- parser.go | 25 +++++++++ 2 files changed, 121 insertions(+), 58 deletions(-) diff --git a/cmd.go b/cmd.go index 6c6dee23..d3df1ba1 100644 --- a/cmd.go +++ b/cmd.go @@ -13,38 +13,43 @@ import ( ) 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] + fmt.Println(`Usage: + yay [...] + 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 - yay --gendb generates development package DB used for updating. +New operations: + yay {-Y --yay} [options] [package(s)] + yay {-G --getpkgbuild} [package(s)] - Permanent configuration options: - --topdown shows repository's packages first and then aur's - --bottomup shows aur's packages first and then repository's - --devel Check -git/-svn/-hg development version - --nodevel Disable development version checking - --afterclean Clean package sources after successful build - --noafterclean Disable package sources cleaning after successful build - --timeupdate Check package's modification date and version - --notimeupdate Check only package version change +Permanent configuration options: + --topdown Shows repository's packages first and then aur's + --bottomup Shows aur's packages first and then repository's + --devel Check -git/-svn/-hg development version + --nodevel Disable development version checking + --afterclean Clean package sources after successful build + --noafterclean Disable package sources cleaning after successful build + --timeupdate Check package's modification date and version + --notimeupdate Check only package version change - New options: - --noconfirm skip user input on package install - --printconfig Prints current yay configuration - `) +Yay specific options: + --printconfig Prints current yay configuration + --stats Displays system information + --cleandeps Remove unneeded dependencies + --gendb Generates development package DB used for updating. + +If no operation is provided -Y will be assumed +`) } func init() { @@ -221,7 +226,7 @@ func handleCmd(parser *argParser) (changedConfig bool, err error) { case "U", "upgrade": //passToPacman() case "Y", "--yay": - err = handleYogurt(parser) + err = handleYay(parser) default: //this means we allowed an op but not implement it //if this happens it an error in the code and not the usage @@ -243,19 +248,19 @@ func handleConfig(option string) (changedConfig bool, err error) { config.CleanAfter = true case "noafterclean": config.CleanAfter = false - case "printconfig": - fmt.Printf("%#v", config) - os.Exit(0) - case "gendb": - err = createDevelDB() - if err != nil { - fmt.Println(err) - } - err = saveVCSInfo() - if err != nil { - fmt.Println(err) - } - os.Exit(0) +// case "printconfig": +// fmt.Printf("%#v", config) +// os.Exit(0) +// case "gendb": +// err = createDevelDB() +// if err != nil { +// fmt.Println(err) +// } +// err = saveVCSInfo() +// if err != nil { +// fmt.Println(err) +// } +// os.Exit(0) case "devel": config.Devel = true case "nodevel": @@ -266,20 +271,20 @@ func handleConfig(option string) (changedConfig bool, err error) { config.TimeUpdate = false case "topdown": config.SortMode = TopDown - case "complete": - config.Shell = "sh" - complete() - os.Exit(0) - case "fcomplete": - config.Shell = fishShell - complete() - os.Exit(0) - case "help": - usage() - os.Exit(0) - case "version": - fmt.Printf("yay v%s\n", version) - os.Exit(0) +// case "complete": +// config.Shell = "sh" +// complete() +// os.Exit(0) +// case "fcomplete": +// config.Shell = fishShell +// complete() +// os.Exit(0) +// case "help": +// usage() +// os.Exit(0) +// case "version": +// fmt.Printf("yay v%s\n", version) +// os.Exit(0) case "noconfirm": config.NoConfirm = true default: @@ -291,7 +296,40 @@ func handleConfig(option string) (changedConfig bool, err error) { } func handleVersion() { - usage() + fmt.Printf("yay v%s\n", version) +} + +func handleYay(parser *argParser) (err error) { + //_, options, targets := parser.formatArgs() + if parser.existsArg("h") || parser.existsArg("help") { + usage() + } else if parser.existsArg("printconfig") { + fmt.Printf("%#v", config) + } else if parser.existsArg("gendb") { + err = createDevelDB() + if err != nil { + return + } + err = saveVCSInfo() + if err != nil { + return + } + } else if parser.existsArg("complete") { + config.Shell = "sh" + complete() + } else if parser.existsArg("fcomplete") { + config.Shell = "fish" + complete() + } else if parser.existsArg("stats") { + err = localStatistics() + } else if parser.existsArg("cleandeps") { + _,_,targets := parser.formatArgs() + err = cleanDependencies(targets) + } else { + err = handleYogurt(parser) + } + + return } func handleYogurt(parser *argParser) (err error) { diff --git a/parser.go b/parser.go index 4cf8ab58..d3a5b157 100644 --- a/parser.go +++ b/parser.go @@ -134,8 +134,33 @@ func isOp(op string) bool { return true case "U", "upgrade": return true + + //yay specific case "Y", "yay": return true + case "G", "getpkgbuild": + return true + default: + return false + } +} + +func isYayParam(arg string) bool { + switch arg { + case "afterclean": + return true + case "noafterclean": + return true + case "devel": + return true + case "nodevel": + return true + case "timeupdate": + return true + case "notimeupdate": + return true + case "topdown": + return true default: return false } From 2b47a4d9f09873b75e55ea829b2ad282819cce3d Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 3 Jan 2018 05:55:12 +0000 Subject: [PATCH 03/12] Refactor away os.Exit Try to minimise the useage of os.Exit Apart from init, os.Exit is only used once as the final function call. Now we can ensure there are no random exits hidding in the code. We can also allow part of the code to error and continue on while also remembering that we did error and return non 0 when we finally do reach the os.Exit. This comes in very handy for trying to save the vcs info after an error and ensuring that alpmHandle.Release is always called. --- cmd.go | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/cmd.go b/cmd.go index d3df1ba1..4113d82a 100644 --- a/cmd.go +++ b/cmd.go @@ -142,6 +142,18 @@ func init() { } func main() { + status := run() + + err := alpmHandle.Release() + if err != nil { + fmt.Println(err) + status = 1 + } + + os.Exit(status) +} + +func run() (status int) { var err error var changedConfig bool @@ -150,7 +162,8 @@ func main() { if err != nil { fmt.Println(err) - os.Exit(1) + status = 1 + return } if parser.existsArg("-") { @@ -158,16 +171,17 @@ func main() { if err != nil { fmt.Println(err) - os.Exit(1) + status = 1 + return } } - fmt.Println(parser) - changedConfig, err = handleCmd(parser) if err != nil { fmt.Println(err) + status = 1 + //try continue onward } if updated { @@ -175,6 +189,7 @@ func main() { if err != nil { fmt.Println(err) + status = 1 } } @@ -183,16 +198,16 @@ func main() { if err != nil { fmt.Println(err) + status = 1 } } - - err = alpmHandle.Release() - if err != nil { - fmt.Println(err) - } + + return + } + func handleCmd(parser *argParser) (changedConfig bool, err error) { var _changedConfig bool From df27396fa0893c8a6e858c0e0ba38df8713651fd Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 3 Jan 2018 18:42:40 +0000 Subject: [PATCH 04/12] Teach passToPacman how to use argParsers passToPacman now takes and argParser as a paramater. And is implemented for the simple cases in cmd.go. Although passToPacman is now left non working in places which still try to usr the old call format and will need to be reimplemented. --- clean.go | 3 +- cmd.go | 82 ++++++++++++++++++++++++++---------------------------- config.go | 28 +++++++------------ install.go | 18 ++++++------ parser.go | 59 +++++++++++++++++++++++++++++++++++---- query.go | 3 +- upgrade.go | 10 +++---- 7 files changed, 122 insertions(+), 81 deletions(-) diff --git a/clean.go b/clean.go index 1877fbab..99f74ac6 100644 --- a/clean.go +++ b/clean.go @@ -54,6 +54,7 @@ func cleanRemove(pkgName []string) (err error) { return nil } - err = passToPacman("-Rsnc", pkgName, []string{"--noconfirm"}) + //TODO + //err = passToPacman("-Rsnc", pkgName, []string{"--noconfirm"}) return err } diff --git a/cmd.go b/cmd.go index 4113d82a..0130def7 100644 --- a/cmd.go +++ b/cmd.go @@ -225,21 +225,21 @@ func handleCmd(parser *argParser) (changedConfig bool, err error) { switch parser.op { case "V", "version": - handleVersion() + handleVersion(parser) case "D", "database": - //passToPacman() + passToPacman(parser) case "F", "files": - //passToPacman() + passToPacman(parser) case "Q", "query": - //passToPacman() + passToPacman(parser) case "R", "remove": - // + passToPacman(parser) case "S", "sync": err = handleSync(parser) case "T", "deptest": - //passToPacman() + passToPacman(parser) case "U", "upgrade": - //passToPacman() + passToPacman(parser) case "Y", "--yay": err = handleYay(parser) default: @@ -310,7 +310,7 @@ func handleConfig(option string) (changedConfig bool, err error) { return } -func handleVersion() { +func handleVersion(parser *argParser) { fmt.Printf("yay v%s\n", version) } @@ -338,8 +338,9 @@ func handleYay(parser *argParser) (err error) { } else if parser.existsArg("stats") { err = localStatistics() } else if parser.existsArg("cleandeps") { - _,_,targets := parser.formatArgs() - err = cleanDependencies(targets) + //TODO + //_,_,targets := parser.formatArgs() + //err = cleanDependencies(targets) } else { err = handleYogurt(parser) } @@ -348,41 +349,37 @@ func handleYay(parser *argParser) (err error) { } func handleYogurt(parser *argParser) (err error) { - _, options, targets := parser.formatArgs() - - config.SearchMode = NumberMenu - err = numberMenu(targets, options) - +// TODO +// _, options, targets := parser.formatArgs() +// +// config.SearchMode = NumberMenu +// err = numberMenu(targets, options) +// return } func handleSync(parser *argParser) (err error) { - op, options, targets := parser.formatArgs() - - fmt.Println("op", op) - fmt.Println("options", options) - fmt.Println("targets", targets) - - if parser.existsArg("y") { - err = passToPacman("-Sy", nil, nil) - if err != nil { - return - } - } - - if parser.existsArg("s") { - if parser.existsArg("i") { - config.SearchMode = Detailed - } else { - config.SortMode = Minimal - } - - err = syncSearch(targets) - } - - if len(targets) > 0 { - err = install(targets, options) - } +//TODO +// if parser.existsArg("y") || parser.existsArg("refresh") { +// err = passToPacman(parser) +// if err != nil { +// return +// } +// } +// +// if parser.existsArg("s") { +// if parser.existsArg("i") { +// config.SearchMode = Detailed +// } else { +// config.SortMode = Minimal +// } +// +// err = syncSearch(targets) +// } +// +// if len(targets) > 0 { +// err = install(targets, options) +// } return } @@ -451,7 +448,8 @@ func numberMenu(pkgS []string, flags []string) (err error) { } if len(repoI) != 0 { - err = passToPacman("-S", repoI, flags) + //TODO + //err = passToPacman("-S", repoI, flags) } if len(aurI) != 0 { diff --git a/config.go b/config.go index db182548..53710719 100644 --- a/config.go +++ b/config.go @@ -6,7 +6,6 @@ import ( "os" "os/exec" "os/user" - "strings" alpm "github.com/jguer/go-alpm" ) @@ -198,25 +197,18 @@ func continueTask(s string, def string) (cont bool) { } // PassToPacman outsorces execution to pacman binary without modifications. -func passToPacman(op string, pkgs []string, flags []string) error { +func passToPacman(parser *argParser) 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(config.PacmanBin, args...) - } else { - args = append([]string{config.PacmanBin}, args...) - cmd = exec.Command("sudo", args...) + args := make([]string, 0) + + if parser.needRoot() { + args = append(args, "sudo") } + + args = append(args, "pacman") + args = append(args, parser.formatArgs()...) + + cmd = exec.Command(args[0], args[1:]...) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr err := cmd.Run() diff --git a/install.go b/install.go index 23ff8039..9843a9e1 100644 --- a/install.go +++ b/install.go @@ -14,10 +14,11 @@ func install(pkgs []string, flags []string) error { aurs, repos, _ := packageSlices(pkgs) if len(repos) != 0 { - err := passToPacman("-S", repos, flags) - if err != nil { - fmt.Println("Error installing repo packages.") - } +//TODO +// err := passToPacman("-S", repos, flags) +// if err != nil { +// fmt.Println("Error installing repo packages.") +// } } if len(aurs) != 0 { @@ -138,10 +139,11 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { } // Repo dependencies if len(repoDeps) != 0 { - errR := passToPacman("-S", repoDeps, depArgs) - if errR != nil { - return finalmdeps, errR - } +// TODO +// errR := passToPacman("-S", repoDeps, depArgs) +// if errR != nil { +// return finalmdeps, errR +// } } // Handle AUR dependencies diff --git a/parser.go b/parser.go index d3a5b157..1d164a82 100644 --- a/parser.go +++ b/parser.go @@ -28,6 +28,52 @@ func (praser *argParser) delArg(option string) { delete(praser.doubles, option) } +func (parser *argParser) needRoot() bool { + if parser.existsArg("h") || parser.existsArg("help") { + return false + } + + if parser.existsArg("p") || parser.existsArg("print") { + return false + } + + switch parser.op { + case "V", "version": + return false + case "D", "database": + return true + case "F", "files": + if parser.existsArg("y") || parser.existsArg("refresh") { + return true + } + return false + case "Q", "query": + return false + case "R", "remove": + return true + case "S", "sync": + if parser.existsArg("s") || parser.existsArg("search") { + return false + } + if parser.existsArg("l") || parser.existsArg("list") { + return false + } + return true + case "T", "deptest": + return false + case "U", "upgrade": + return true + + //yay specific + case "Y", "yay": + return false + case "G", "getpkgbuild": + return false + default: + return false + } +} + func (praser *argParser) addOP(op string) (err error) { if praser.op != "" { err = fmt.Errorf("only one operation may be used at a time") @@ -82,24 +128,25 @@ func (parser *argParser) existsDouble(option string) bool { return ok } -func (parser *argParser) formatArgs() (op string, options []string, targets []string) { - op = formatArg(parser.op) +func (parser *argParser) formatArgs() (args []string) { + op := formatArg(parser.op) + args = append(args, op) for option, arg := range parser.options { option = formatArg(option) - options = append(options, option) + args = append(args, option) if arg != "" { - options = append(options, arg) + args = append(args, arg) } if parser.existsDouble(option) { - options = append(options, option) + args = append(args, option) } } for target := range parser.targets { - targets = append(targets, target) + args = append(args, target) } return diff --git a/query.go b/query.go index b88c0a02..1bf90aff 100644 --- a/query.go +++ b/query.go @@ -169,7 +169,8 @@ func syncInfo(pkgS []string, flags []string) (err error) { } if len(repoS) != 0 { - err = passToPacman("-Si", repoS, flags) + //TODO + //err = passToPacman("-Si", repoS, flags) } return diff --git a/upgrade.go b/upgrade.go index e77f679b..a1f5f9a5 100644 --- a/upgrade.go +++ b/upgrade.go @@ -332,11 +332,11 @@ func upgradePkgs(flags []string) error { } repoNames = append(repoNames, k.Name) } - - err := passToPacman("-S", repoNames, append(flags, "--noconfirm")) - if err != nil { - fmt.Println("Error upgrading repo packages.") - } +// TODO +// err := passToPacman("-S", repoNames, append(flags, "--noconfirm")) +// if err != nil { +// fmt.Println("Error upgrading repo packages.") +// } } if len(aurUp) != 0 { From 68a97713276ec6615583708bed076e1e6fb3690f Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 3 Jan 2018 19:01:34 +0000 Subject: [PATCH 05/12] Move passToPackman from config.go to cmd.go --- cmd.go | 20 ++++++++++++++++++++ config.go | 21 +-------------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/cmd.go b/cmd.go index 0130def7..721ef4a6 100644 --- a/cmd.go +++ b/cmd.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "os" + "os/exec" "path/filepath" "strconv" "strings" @@ -488,3 +489,22 @@ func complete() error { _, err = io.Copy(os.Stdout, in) return err } + +// PassToPacman outsorces execution to pacman binary without modifications. +func passToPacman(parser *argParser) error { + var cmd *exec.Cmd + args := make([]string, 0) + + if parser.needRoot() { + args = append(args, "sudo") + } + + args = append(args, "pacman") + args = append(args, parser.formatArgs()...) + + cmd = exec.Command(args[0], args[1:]...) + + cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr + err := cmd.Run() + return err +} diff --git a/config.go b/config.go index 53710719..ffe69328 100644 --- a/config.go +++ b/config.go @@ -194,23 +194,4 @@ func continueTask(s string, def string) (cont bool) { } return true -} - -// PassToPacman outsorces execution to pacman binary without modifications. -func passToPacman(parser *argParser) error { - var cmd *exec.Cmd - args := make([]string, 0) - - if parser.needRoot() { - args = append(args, "sudo") - } - - args = append(args, "pacman") - args = append(args, parser.formatArgs()...) - - cmd = exec.Command(args[0], args[1:]...) - - cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr - err := cmd.Run() - return err -} +} \ No newline at end of file From 3084f91ba7c70c4a1735069553f444ff11eaf711 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Wed, 3 Jan 2018 19:17:57 +0000 Subject: [PATCH 06/12] Reimplement getpkgbuild Futre todos: Add option to fetch deps Add option to set download path --- cmd.go | 16 ++++++++++++++++ parser.go | 10 ++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/cmd.go b/cmd.go index 721ef4a6..01fd87c6 100644 --- a/cmd.go +++ b/cmd.go @@ -241,6 +241,8 @@ func handleCmd(parser *argParser) (changedConfig bool, err error) { passToPacman(parser) case "U", "upgrade": passToPacman(parser) + case "G", "getpkgbuild": + err = handleGetpkgbuild(parser) case "Y", "--yay": err = handleYay(parser) default: @@ -349,6 +351,20 @@ func handleYay(parser *argParser) (err error) { return } +func handleGetpkgbuild(parser *argParser) (err error) { + for pkg := range parser.targets { + err = getPkgbuild(pkg) + if err != nil { + //we print the error instead of returning it + //seems as we can handle multiple errors without stoping + //theres no easy way arround this right now + fmt.Println(pkg + ":", err) + } + } + + return +} + func handleYogurt(parser *argParser) (err error) { // TODO // _, options, targets := parser.formatArgs() diff --git a/parser.go b/parser.go index 1d164a82..dd5cab7f 100644 --- a/parser.go +++ b/parser.go @@ -7,19 +7,21 @@ import ( "io" ) +type set map[string]struct{} + type argParser struct { op string options map[string]string - doubles map[string]struct{} //tracks args passed twice such as -yy and -dd - targets map[string]struct{} + doubles set //tracks args passed twice such as -yy and -dd + targets set } func makeArgParser() *argParser { return &argParser { "", make(map[string]string), - make(map[string]struct{}), - make(map[string]struct{}), + make(set), + make(set), } } From 96f499ff44c40692699f55b9a8e718365de7de28 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 4 Jan 2018 00:59:57 +0000 Subject: [PATCH 07/12] Reimplement all previously existing operations This reimplemens all operations yay previously supported: '-S' 'Syu' 'Si' ect. Currently the argument objects are not fully implemented with the code. Theres alot of funky conversion from argument object -> pkg, flags -> argument object This is to just get back to the functionally we had before (almost). I have not looked into it yet but alot of the time pacman flags get passed to makepkg. this cases an error for most commands now because the new system Passes all flags: `yay -Syu` -> flags = '-S' '-y' '-u' while the old system would have done: `yay -Syu` -> op = '-Suy', flags = '' So extra flags are no longer passed at all currently. This means: 'yay -S aic94xx-firmware --noconfirm -b /tmp/pacutilesu2q6hw/tmp-pacman -d' will no longer error and 'aic94xx-firmware' will be installed but the database path change will not apply and the dep checking will not be skipped. --- clean.go | 13 +++-- cmd.go | 109 +++++++++++++++++++++---------------- install.go | 38 +++++++------ parser.go | 156 +++++++++++++++++++++++++++++++++++------------------ query.go | 7 ++- upgrade.go | 15 ++++-- 6 files changed, 212 insertions(+), 126 deletions(-) diff --git a/clean.go b/clean.go index 99f74ac6..d5d211ed 100644 --- a/clean.go +++ b/clean.go @@ -32,7 +32,7 @@ func removeVCSPackage(pkgs []string) { } // CleanDependencies removes all dangling dependencies in system -func cleanDependencies(pkgs []string) error { +func cleanDependencies() error { hanging, err := hangingPackages() if err != nil { return err @@ -49,12 +49,15 @@ func cleanDependencies(pkgs []string) error { } // CleanRemove sends a full removal command to pacman with the pkgName slice -func cleanRemove(pkgName []string) (err error) { - if len(pkgName) == 0 { +func cleanRemove(pkgNames []string) (err error) { + if len(pkgNames) == 0 { return nil } + + arguments := makeArguments() + arguments.addArg("R", "s", "n", "s", "noconfirm") + arguments.addTarget(pkgNames...) - //TODO - //err = passToPacman("-Rsnc", pkgName, []string{"--noconfirm"}) + err = passToPacman(arguments) return err } diff --git a/cmd.go b/cmd.go index 01fd87c6..d152d52d 100644 --- a/cmd.go +++ b/cmd.go @@ -158,7 +158,7 @@ func run() (status int) { var err error var changedConfig bool - parser := makeArgParser(); + parser := makeArguments(); err = parser.parseCommandLine(); if err != nil { @@ -209,7 +209,7 @@ func run() (status int) { } -func handleCmd(parser *argParser) (changedConfig bool, err error) { +func handleCmd(parser *arguments) (changedConfig bool, err error) { var _changedConfig bool for option, _ := range parser.options { @@ -234,7 +234,7 @@ func handleCmd(parser *argParser) (changedConfig bool, err error) { case "Q", "query": passToPacman(parser) case "R", "remove": - passToPacman(parser) + handleRemove(parser) case "S", "sync": err = handleSync(parser) case "T", "deptest": @@ -313,13 +313,13 @@ func handleConfig(option string) (changedConfig bool, err error) { return } -func handleVersion(parser *argParser) { +func handleVersion(parser *arguments) { fmt.Printf("yay v%s\n", version) } -func handleYay(parser *argParser) (err error) { +func handleYay(parser *arguments) (err error) { //_, options, targets := parser.formatArgs() - if parser.existsArg("h") || parser.existsArg("help") { + if parser.existsArg("h", "help") { usage() } else if parser.existsArg("printconfig") { fmt.Printf("%#v", config) @@ -341,9 +341,7 @@ func handleYay(parser *argParser) (err error) { } else if parser.existsArg("stats") { err = localStatistics() } else if parser.existsArg("cleandeps") { - //TODO - //_,_,targets := parser.formatArgs() - //err = cleanDependencies(targets) + err = cleanDependencies() } else { err = handleYogurt(parser) } @@ -351,7 +349,7 @@ func handleYay(parser *argParser) (err error) { return } -func handleGetpkgbuild(parser *argParser) (err error) { +func handleGetpkgbuild(parser *arguments) (err error) { for pkg := range parser.targets { err = getPkgbuild(pkg) if err != nil { @@ -365,45 +363,59 @@ func handleGetpkgbuild(parser *argParser) (err error) { return } -func handleYogurt(parser *argParser) (err error) { -// TODO -// _, options, targets := parser.formatArgs() -// -// config.SearchMode = NumberMenu -// err = numberMenu(targets, options) -// - return -} - -func handleSync(parser *argParser) (err error) { -//TODO -// if parser.existsArg("y") || parser.existsArg("refresh") { -// err = passToPacman(parser) -// if err != nil { -// return -// } -// } -// -// if parser.existsArg("s") { -// if parser.existsArg("i") { -// config.SearchMode = Detailed -// } else { -// config.SortMode = Minimal -// } -// -// err = syncSearch(targets) -// } -// -// if len(targets) > 0 { -// err = install(targets, options) -// } +func handleYogurt(parser *arguments) (err error) { + options := parser.formatArgs() + targets := parser.formatTargets() + + config.SearchMode = NumberMenu + err = numberMenu(targets, options) return } +func handleSync(parser *arguments) (err error) { + targets := parser.formatTargets() + options := parser.formatArgs() + + if parser.existsArg("y", "refresh") { + arguments := makeArguments() + arguments.addArg("S", "y") + err = passToPacman(arguments) + if err != nil { + return + } + } + + if parser.existsArg("s", "search") { + if parser.existsArg("q", "quiet") { + config.SearchMode = Minimal + } else { + config.SearchMode = Detailed + } + + err = syncSearch(targets) + } else if parser.existsArg("c", "clean") { + err = passToPacman(parser) + } else if parser.existsArg("u", "sysupgrade") { + err = upgradePkgs(make([]string,0)) + } else if parser.existsArg("i", "info") { + err = syncInfo(targets, options) + } else if len(parser.targets) > 0 { + err = install(parser) + } + + return +} + +func handleRemove(parser *arguments) (err error){ + removeVCSPackage(parser.formatTargets()) + err = passToPacman(parser) + return +} // NumberMenu presents a CLI for selecting packages to install. func numberMenu(pkgS []string, flags []string) (err error) { +//func numberMenu(parser *arguments) (err error) { var num int aq, err := narrowSearch(pkgS, true) @@ -411,6 +423,7 @@ func numberMenu(pkgS []string, flags []string) (err error) { fmt.Println("Error during AUR search:", err) } numaq := len(aq) + pq, numpq, err := queryRepo(pkgS) if err != nil { return @@ -465,12 +478,14 @@ func numberMenu(pkgS []string, flags []string) (err error) { } if len(repoI) != 0 { - //TODO - //err = passToPacman("-S", repoI, flags) + arguments := makeArguments() + arguments.addArg("S") + arguments.addTarget(repoI...) + err = passToPacman(arguments) } if len(aurI) != 0 { - err = aurInstall(aurI, flags) + err = aurInstall(aurI, make([]string,0)) } return err @@ -507,7 +522,7 @@ func complete() error { } // PassToPacman outsorces execution to pacman binary without modifications. -func passToPacman(parser *argParser) error { +func passToPacman(parser *arguments) error { var cmd *exec.Cmd args := make([]string, 0) @@ -517,9 +532,11 @@ func passToPacman(parser *argParser) error { args = append(args, "pacman") args = append(args, parser.formatArgs()...) + args = append(args, parser.formatTargets()...) cmd = exec.Command(args[0], args[1:]...) + cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr err := cmd.Run() return err diff --git a/install.go b/install.go index 9843a9e1..d9ed502c 100644 --- a/install.go +++ b/install.go @@ -10,19 +10,23 @@ import ( ) // Install handles package installs -func install(pkgs []string, flags []string) error { - aurs, repos, _ := packageSlices(pkgs) +func install(parser *arguments) error { + aurs, repos, _ := packageSlices(parser.targets.toSlice()) + arguments := makeArguments() + arguments.op = parser.op + arguments.options = arguments.options + arguments.addTarget(repos...) + if len(repos) != 0 { -//TODO -// err := passToPacman("-S", repos, flags) -// if err != nil { -// fmt.Println("Error installing repo packages.") -// } + err := passToPacman(arguments) + if err != nil { + fmt.Println("Error installing repo packages.") + } } if len(aurs) != 0 { - err := aurInstall(aurs, flags) + err := aurInstall(aurs, make([]string,0)) if err != nil { fmt.Println("Error installing aur packages.") } @@ -131,19 +135,19 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { } } - var depArgs []string + arguments := makeArguments() + arguments.addArg("S", "asdeps") + depArgs := arguments.formatArgs() + if config.NoConfirm { - depArgs = []string{"--asdeps", "--noconfirm"} - } else { - depArgs = []string{"--asdeps"} + arguments.addArg("noconfirm") } // Repo dependencies if len(repoDeps) != 0 { -// TODO -// errR := passToPacman("-S", repoDeps, depArgs) -// if errR != nil { -// return finalmdeps, errR -// } + errR := passToPacman(arguments) + if errR != nil { + return finalmdeps, errR + } } // Handle AUR dependencies diff --git a/parser.go b/parser.go index dd5cab7f..428aab77 100644 --- a/parser.go +++ b/parser.go @@ -7,35 +7,62 @@ import ( "io" ) -type set map[string]struct{} +type stringSet map[string]struct{} -type argParser struct { - op string - options map[string]string - doubles set //tracks args passed twice such as -yy and -dd - targets set +func (set stringSet) getAny() string { + for v := range set { + return v + } + + //maybe should return error instrad + return "" } -func makeArgParser() *argParser { - return &argParser { +func (set stringSet) toSlice() []string { + slice := make([]string, 0, len(set)) + + for v := range set { + slice = append(slice, v) + } + + return slice +} + +func (set stringSet) removeAny() string { + v := set.removeAny() + delete(set, v) + return v +} + +type arguments struct { + op string + options map[string]string + doubles stringSet //tracks args passed twice such as -yy and -dd + targets stringSet +} + +func makeArguments() *arguments { + return &arguments { "", make(map[string]string), - make(set), - make(set), + make(stringSet), + make(stringSet), } } -func (praser *argParser) delArg(option string) { - delete(praser.options, option) - delete(praser.doubles, option) +func (parser *arguments) delArg(options ...string) { + for _, option := range options { + delete(parser.options, option) + delete(parser.doubles, option) + } } -func (parser *argParser) needRoot() bool { - if parser.existsArg("h") || parser.existsArg("help") { +func (parser *arguments) needRoot() bool { + if parser.existsArg("h", "help") { return false } - if parser.existsArg("p") || parser.existsArg("print") { + if parser.existsArg("p", "print") { return false } @@ -45,7 +72,7 @@ func (parser *argParser) needRoot() bool { case "D", "database": return true case "F", "files": - if parser.existsArg("y") || parser.existsArg("refresh") { + if parser.existsArg("y", "refresh") { return true } return false @@ -54,10 +81,10 @@ func (parser *argParser) needRoot() bool { case "R", "remove": return true case "S", "sync": - if parser.existsArg("s") || parser.existsArg("search") { + if parser.existsArg("s", "search") { return false } - if parser.existsArg("l") || parser.existsArg("list") { + if parser.existsArg("l", "list") { return false } return true @@ -76,61 +103,92 @@ func (parser *argParser) needRoot() bool { } } -func (praser *argParser) addOP(op string) (err error) { - if praser.op != "" { +func (parser *arguments) addOP(op string) (err error) { + if parser.op != "" { err = fmt.Errorf("only one operation may be used at a time") return } - praser.op = op + parser.op = op return } -func (praser *argParser) addParam(option string, arg string) (err error) { +func (parser *arguments) addParam(option string, arg string) (err error) { if isOp(option) { - err = praser.addOP(option) + err = parser.addOP(option) return } - if praser.existsArg(option) { - praser.doubles[option] = struct{}{} + if parser.existsArg(option) { + parser.doubles[option] = struct{}{} } else { - praser.options[option] = arg + parser.options[option] = arg } return } -func (praser *argParser) addArg(option string) (err error) { - err = praser.addParam(option, "") +func (parser *arguments) addArg(options ...string) (err error) { + for _, option := range options { + err = parser.addParam(option, "") + if err != nil { + return + } + } + return } -func (praser *argParser) existsArg(option string) (ok bool) { - _, ok = praser.options[option] - return ok +//multiple args acts as an OR operator +func (parser *arguments) existsArg(options ...string) bool { + for _, option := range options { + _, exists := parser.options[option] + if exists { + return true + } + } + return false } -func (praser *argParser) getArg(option string) (arg string, double bool, exists bool) { - arg, exists = praser.options[option] - _, double = praser.doubles[option] +func (parser *arguments) getArg(option string) (arg string, double bool, exists bool) { + arg, exists = parser.options[option] + _, double = parser.doubles[option] return } -func (praser *argParser) addTarget(target string) { - praser.targets[target] = struct{}{} +func (parser *arguments) addTarget(targets ...string) { + for _, target := range targets { + parser.targets[target] = struct{}{} + } } -func (praser *argParser) delTarget(target string) { - delete(praser.targets, target) +func (parser *arguments) delTarget(targets ...string) { + for _, target := range targets { + delete(parser.targets, target) + } } -func (parser *argParser) existsDouble(option string) bool { - _, ok := parser.doubles[option] - return ok +//multiple args acts as an OR operator +func (parser *arguments) existsDouble(options ...string) bool { + for _, option := range options { + _, exists := parser.doubles[option] + if exists { + return true + } + } + + return false } -func (parser *argParser) formatArgs() (args []string) { +func (parser *arguments) formatTargets() (args []string) { + for target := range parser.targets { + args = append(args, target) + } + + return +} + +func (parser *arguments) formatArgs() (args []string) { op := formatArg(parser.op) args = append(args, op) @@ -147,10 +205,6 @@ func (parser *argParser) formatArgs() (args []string) { } } - for target := range parser.targets { - args = append(args, target) - } - return } @@ -256,7 +310,7 @@ func hasParam(arg string) bool { //parses short hand options such as: //-Syu -b/some/path - -func (parser *argParser) parseShortOption(arg string, param string) (usedNext bool, err error) { +func (parser *arguments) parseShortOption(arg string, param string) (usedNext bool, err error) { if arg == "-" { err = parser.addArg("-") return @@ -290,7 +344,7 @@ func (parser *argParser) parseShortOption(arg string, param string) (usedNext bo //parses full length options such as: //--sync --refresh --sysupgrade --dbpath /some/path -- -func (parser *argParser) parseLongOption(arg string, param string) (usedNext bool, err error){ +func (parser *arguments) parseLongOption(arg string, param string) (usedNext bool, err error){ if arg == "--" { err = parser.addArg(arg) return @@ -308,7 +362,7 @@ func (parser *argParser) parseLongOption(arg string, param string) (usedNext boo return } -func (parser *argParser) parseStdin() (err error) { +func (parser *arguments) parseStdin() (err error) { for true { var target string _, err = fmt.Scan(&target) @@ -327,7 +381,7 @@ func (parser *argParser) parseStdin() (err error) { return } -func (parser *argParser)parseCommandLine() (err error) { +func (parser *arguments)parseCommandLine() (err error) { args := os.Args[1:] usedNext := false diff --git a/query.go b/query.go index 1bf90aff..07818d48 100644 --- a/query.go +++ b/query.go @@ -169,8 +169,11 @@ func syncInfo(pkgS []string, flags []string) (err error) { } if len(repoS) != 0 { - //TODO - //err = passToPacman("-Si", repoS, flags) + arguments := makeArguments() + arguments.addArg("S", "i") + //arguments.addArg(flags...) + arguments.addTarget(repoS...) + err = passToPacman(arguments) } return diff --git a/upgrade.go b/upgrade.go index a1f5f9a5..ff60f149 100644 --- a/upgrade.go +++ b/upgrade.go @@ -332,11 +332,16 @@ func upgradePkgs(flags []string) error { } repoNames = append(repoNames, k.Name) } -// TODO -// err := passToPacman("-S", repoNames, append(flags, "--noconfirm")) -// if err != nil { -// fmt.Println("Error upgrading repo packages.") -// } + + arguments := makeArguments() + arguments.addArg("-S --noconfirm") + arguments.addArg(flags...) + arguments.addTarget(repoNames...) + + err := passToPacman(arguments) + if err != nil { + fmt.Println("Error upgrading repo packages.") + } } if len(aurUp) != 0 { From 44f83e03ea3dea27bc855a92e93a62fd3ae0c65a Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 4 Jan 2018 02:53:19 +0000 Subject: [PATCH 08/12] Move makepkg handling to its own function --- cmd.go | 18 +++++++++++++++++- install.go | 15 ++------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/cmd.go b/cmd.go index d152d52d..8711f3a5 100644 --- a/cmd.go +++ b/cmd.go @@ -521,7 +521,7 @@ func complete() error { return err } -// PassToPacman outsorces execution to pacman binary without modifications. +// passToPacman outsorces execution to pacman binary without modifications. func passToPacman(parser *arguments) error { var cmd *exec.Cmd args := make([]string, 0) @@ -541,3 +541,19 @@ func passToPacman(parser *arguments) error { err := cmd.Run() return err } + +// passToMakepkg outsorces execution to makepkg binary without modifications. +func passToMakepkg(dir string, args ...string) (err error) { + cmd := exec.Command(config.MakepkgBin, args...) + cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr + cmd.Dir = dir + err = cmd.Run() + if err == nil { + _ = saveVCSInfo() + if config.CleanAfter { + fmt.Println("\x1b[1;32m==> CleanAfter enabled. Deleting source folder.\x1b[0m") + os.RemoveAll(dir) + } + } + return +} \ No newline at end of file diff --git a/install.go b/install.go index d9ed502c..002f12f1 100644 --- a/install.go +++ b/install.go @@ -162,18 +162,7 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { } } - args := []string{"-sri"} - args = append(args, flags...) - makepkgcmd := exec.Command(config.MakepkgBin, args...) - makepkgcmd.Stdin, makepkgcmd.Stdout, makepkgcmd.Stderr = os.Stdin, os.Stdout, os.Stderr - makepkgcmd.Dir = dir - err = makepkgcmd.Run() - if err == nil { - _ = saveVCSInfo() - if config.CleanAfter { - fmt.Println("\x1b[1;32m==> CleanAfter enabled. Deleting source folder.\x1b[0m") - os.RemoveAll(dir) - } - } + flags = append(flags, "-sri") + err = passToMakepkg(dir, flags...) return } From 16b747cb2d7e30e6007aa600c5a490af750d78aa Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 4 Jan 2018 06:01:17 +0000 Subject: [PATCH 09/12] Make the parser aware of global pacman arguments Allows globals to be tracked more easily so that thay can be seperated from normal arguments and passed easily while not passing other arguments. Also fixed some missing checks and bugs. --- parser.go | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 109 insertions(+), 7 deletions(-) diff --git a/parser.go b/parser.go index 428aab77..35b71ab6 100644 --- a/parser.go +++ b/parser.go @@ -29,14 +29,16 @@ func (set stringSet) toSlice() []string { } func (set stringSet) removeAny() string { - v := set.removeAny() + v := set.getAny() delete(set, v) return v } + type arguments struct { op string options map[string]string + globals map[string]string doubles stringSet //tracks args passed twice such as -yy and -dd targets stringSet } @@ -45,14 +47,41 @@ func makeArguments() *arguments { return &arguments { "", make(map[string]string), + make(map[string]string), make(stringSet), make(stringSet), } } +func (parser *arguments) copy() (cp *arguments) { + cp = makeArguments() + + cp.op = parser.op + + for k,v := range parser.options { + cp.options[k] = v + } + + for k,v := range parser.globals { + cp.globals[k] = v + } + + for k,v := range parser.targets { + cp.targets[k] = v + } + + for k,v := range parser.doubles { + cp.doubles[k] = v + } + + return +} + + func (parser *arguments) delArg(options ...string) { for _, option := range options { delete(parser.options, option) + delete(parser.globals, option) delete(parser.doubles, option) } } @@ -81,19 +110,28 @@ func (parser *arguments) needRoot() bool { case "R", "remove": return true case "S", "sync": + if parser.existsArg("y", "refresh") { + return true + } + if parser.existsArg("u", "sysupgrade") { + return true + } if parser.existsArg("s", "search") { return false } if parser.existsArg("l", "list") { return false } + if parser.existsArg("i", "info") { + return false + } return true case "T", "deptest": return false case "U", "upgrade": return true - //yay specific + //yay specific case "Y", "yay": return false case "G", "getpkgbuild": @@ -121,6 +159,8 @@ func (parser *arguments) addParam(option string, arg string) (err error) { if parser.existsArg(option) { parser.doubles[option] = struct{}{} + } else if isGlobal(option) { + parser.globals[option] = arg } else { parser.options[option] = arg } @@ -135,7 +175,7 @@ func (parser *arguments) addArg(options ...string) (err error) { return } } - + return } @@ -146,12 +186,24 @@ func (parser *arguments) existsArg(options ...string) bool { if exists { return true } + + _, exists = parser.globals[option] + if exists { + return true + } } return false } func (parser *arguments) getArg(option string) (arg string, double bool, exists bool) { arg, exists = parser.options[option] + + if exists { + _, double = parser.doubles[option] + return + } + + arg, exists = parser.globals[option] _, double = parser.doubles[option] return } @@ -193,15 +245,32 @@ func (parser *arguments) formatArgs() (args []string) { args = append(args, op) for option, arg := range parser.options { - option = formatArg(option) - args = append(args, option) + formatedOption := formatArg(option) + args = append(args, formatedOption) - if arg != "" { + if hasParam(option) { args = append(args, arg) } if parser.existsDouble(option) { - args = append(args, option) + args = append(args, formatedOption) + } + } + + return +} + +func (parser *arguments) formatGlobals() (args []string) { + for option, arg := range parser.globals { + formatedOption := formatArg(option) + args = append(args, formatedOption) + + if hasParam(option) { + args = append(args, arg) + } + + if parser.existsDouble(option) { + args = append(args, formatedOption) } } @@ -248,6 +317,39 @@ func isOp(op string) bool { } } +func isGlobal(op string) bool { + switch op { + case "b", "dbpath": + return true + case "r", "root": + return true + case "v", "verbose": + return true + case "arch": + return true + case "cachedir": + return true + case "color": + return true + case "config": + return true + case "debug": + return true + case "gpgdir": + return true + case "hookdir": + return true + case "logfile": + return true + case "noconfirm": + return true + case "confirm": + return true + default: + return false + } +} + func isYayParam(arg string) bool { switch arg { case "afterclean": From 232edc64a6163e4a3c33b4c33f462679f2f7e300 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 4 Jan 2018 08:13:47 +0000 Subject: [PATCH 10/12] Further integration for the argument system Argument parsing now works mostly as expected for repo packages. AUR packages are a little tricky becauce makepkg cant handle args such as '--dbpath'. Also out alpm handle does not read the commandline options so any arguments relient on alpm will be ignored. For now though it seems yay has gained back the functionality it once had. While also having improved argument handling which should also be expandable and make it easier to handle anything new that might have been missed. --- clean.go | 2 +- cmd.go | 148 +++++++++++++++++++++++++++-------------------------- install.go | 22 +++++--- upgrade.go | 2 +- 4 files changed, 93 insertions(+), 81 deletions(-) diff --git a/clean.go b/clean.go index d5d211ed..65f07193 100644 --- a/clean.go +++ b/clean.go @@ -55,7 +55,7 @@ func cleanRemove(pkgNames []string) (err error) { } arguments := makeArguments() - arguments.addArg("R", "s", "n", "s", "noconfirm") + arguments.addArg("R", "noconfirm") arguments.addTarget(pkgNames...) err = passToPacman(arguments) diff --git a/cmd.go b/cmd.go index 8711f3a5..d1413b12 100644 --- a/cmd.go +++ b/cmd.go @@ -13,6 +13,8 @@ import ( "time" ) +var cmdArgs *arguments = makeArguments() + func usage() { fmt.Println(`Usage: yay [...] @@ -158,8 +160,7 @@ func run() (status int) { var err error var changedConfig bool - parser := makeArguments(); - err = parser.parseCommandLine(); + err = cmdArgs.parseCommandLine(); if err != nil { fmt.Println(err) @@ -167,8 +168,8 @@ func run() (status int) { return } - if parser.existsArg("-") { - err = parser.parseStdin(); + if cmdArgs.existsArg("-") { + err = cmdArgs.parseStdin(); if err != nil { fmt.Println(err) @@ -177,7 +178,7 @@ func run() (status int) { } } - changedConfig, err = handleCmd(parser) + changedConfig, err = handleCmd() if err != nil { fmt.Println(err) @@ -209,47 +210,43 @@ func run() (status int) { } -func handleCmd(parser *arguments) (changedConfig bool, err error) { - var _changedConfig bool +func handleCmd() (changedConfig bool, err error) { + changedConfig = false - for option, _ := range parser.options { - _changedConfig, err = handleConfig(option) - - if err != nil { - return - } - - if _changedConfig { - changedConfig = true - } + for option, _ := range cmdArgs.options { + changedConfig = changedConfig || handleConfig(option) + } + + for option, _ := range cmdArgs.globals { + changedConfig = changedConfig || handleConfig(option) } - switch parser.op { + switch cmdArgs.op { case "V", "version": - handleVersion(parser) + handleVersion() case "D", "database": - passToPacman(parser) + passToPacman(cmdArgs) case "F", "files": - passToPacman(parser) + passToPacman(cmdArgs) case "Q", "query": - passToPacman(parser) + passToPacman(cmdArgs) case "R", "remove": - handleRemove(parser) + handleRemove() case "S", "sync": - err = handleSync(parser) + err = handleSync() case "T", "deptest": - passToPacman(parser) + passToPacman(cmdArgs) case "U", "upgrade": - passToPacman(parser) + passToPacman(cmdArgs) case "G", "getpkgbuild": - err = handleGetpkgbuild(parser) + err = handleGetpkgbuild() case "Y", "--yay": - err = handleYay(parser) + err = handleYay() default: //this means we allowed an op but not implement it //if this happens it an error in the code and not the usage err = fmt.Errorf("unhandled operation") - } + } return } @@ -260,7 +257,7 @@ func handleCmd(parser *arguments) (changedConfig bool, err error) { //my current plan is to have yay specific operations in its own operator //e.g. yay -Y --gendb //e.g yay -Yg -func handleConfig(option string) (changedConfig bool, err error) { +func handleConfig(option string) (changedConfig bool) { switch option { case "afterclean": config.CleanAfter = true @@ -313,17 +310,17 @@ func handleConfig(option string) (changedConfig bool, err error) { return } -func handleVersion(parser *arguments) { +func handleVersion() { fmt.Printf("yay v%s\n", version) } -func handleYay(parser *arguments) (err error) { - //_, options, targets := parser.formatArgs() - if parser.existsArg("h", "help") { +func handleYay() (err error) { + //_, options, targets := cmdArgs.formatArgs() + if cmdArgs.existsArg("h", "help") { usage() - } else if parser.existsArg("printconfig") { + } else if cmdArgs.existsArg("printconfig") { fmt.Printf("%#v", config) - } else if parser.existsArg("gendb") { + } else if cmdArgs.existsArg("gendb") { err = createDevelDB() if err != nil { return @@ -332,25 +329,25 @@ func handleYay(parser *arguments) (err error) { if err != nil { return } - } else if parser.existsArg("complete") { + } else if cmdArgs.existsArg("complete") { config.Shell = "sh" complete() - } else if parser.existsArg("fcomplete") { + } else if cmdArgs.existsArg("fcomplete") { config.Shell = "fish" complete() - } else if parser.existsArg("stats") { + } else if cmdArgs.existsArg("stats") { err = localStatistics() - } else if parser.existsArg("cleandeps") { + } else if cmdArgs.existsArg("cleandeps") { err = cleanDependencies() } else { - err = handleYogurt(parser) + err = handleYogurt() } return } -func handleGetpkgbuild(parser *arguments) (err error) { - for pkg := range parser.targets { +func handleGetpkgbuild() (err error) { + for pkg := range cmdArgs.targets { err = getPkgbuild(pkg) if err != nil { //we print the error instead of returning it @@ -363,9 +360,9 @@ func handleGetpkgbuild(parser *arguments) (err error) { return } -func handleYogurt(parser *arguments) (err error) { - options := parser.formatArgs() - targets := parser.formatTargets() +func handleYogurt() (err error) { + options := cmdArgs.formatArgs() + targets := cmdArgs.formatTargets() config.SearchMode = NumberMenu err = numberMenu(targets, options) @@ -373,49 +370,50 @@ func handleYogurt(parser *arguments) (err error) { return } -func handleSync(parser *arguments) (err error) { - targets := parser.formatTargets() - options := parser.formatArgs() +func handleSync() (err error) { + targets := cmdArgs.formatTargets() + options := cmdArgs.formatArgs() - if parser.existsArg("y", "refresh") { - arguments := makeArguments() - arguments.addArg("S", "y") + if cmdArgs.existsArg("y", "refresh") { + arguments := cmdArgs.copy() + arguments.delArg("u", "sysupgrade") + arguments.targets = make(stringSet) err = passToPacman(arguments) if err != nil { return } } - if parser.existsArg("s", "search") { - if parser.existsArg("q", "quiet") { + if cmdArgs.existsArg("s", "search") { + if cmdArgs.existsArg("q", "quiet") { config.SearchMode = Minimal } else { config.SearchMode = Detailed } err = syncSearch(targets) - } else if parser.existsArg("c", "clean") { - err = passToPacman(parser) - } else if parser.existsArg("u", "sysupgrade") { + } else if cmdArgs.existsArg("c", "clean") { + err = passToPacman(cmdArgs) + } else if cmdArgs.existsArg("u", "sysupgrade") { err = upgradePkgs(make([]string,0)) - } else if parser.existsArg("i", "info") { + } else if cmdArgs.existsArg("i", "info") { err = syncInfo(targets, options) - } else if len(parser.targets) > 0 { - err = install(parser) + } else if len(cmdArgs.targets) > 0 { + err = install(cmdArgs) } return } -func handleRemove(parser *arguments) (err error){ - removeVCSPackage(parser.formatTargets()) - err = passToPacman(parser) +func handleRemove() (err error){ + removeVCSPackage(cmdArgs.formatTargets()) + err = passToPacman(cmdArgs) return } // NumberMenu presents a CLI for selecting packages to install. func numberMenu(pkgS []string, flags []string) (err error) { -//func numberMenu(parser *arguments) (err error) { +//func numberMenu(cmdArgs *arguments) (err error) { var num int aq, err := narrowSearch(pkgS, true) @@ -522,19 +520,25 @@ func complete() error { } // passToPacman outsorces execution to pacman binary without modifications. -func passToPacman(parser *arguments) error { +func passToPacman(args *arguments) error { var cmd *exec.Cmd - args := make([]string, 0) + argArr := make([]string, 0) - if parser.needRoot() { - args = append(args, "sudo") + if args.needRoot() { + argArr = append(argArr, "sudo") } - args = append(args, "pacman") - args = append(args, parser.formatArgs()...) - args = append(args, parser.formatTargets()...) + + argArr = append(argArr, "pacman") + argArr = append(argArr, cmdArgs.formatGlobals()...) + argArr = append(argArr, args.formatArgs()...) + argArr = append(argArr, args.formatTargets()...) - cmd = exec.Command(args[0], args[1:]...) + + fmt.Println(cmdArgs) + fmt.Println(args) + fmt.Println(argArr) + cmd = exec.Command(argArr[0], argArr[1:]...) cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr diff --git a/install.go b/install.go index 002f12f1..d0834e55 100644 --- a/install.go +++ b/install.go @@ -13,9 +13,10 @@ import ( func install(parser *arguments) error { aurs, repos, _ := packageSlices(parser.targets.toSlice()) - arguments := makeArguments() - arguments.op = parser.op - arguments.options = arguments.options + arguments := parser.copy() + arguments.delArg("u", "sysupgrade") + arguments.delArg("y", "refresh") + arguments.targets = make(stringSet) arguments.addTarget(repos...) if len(repos) != 0 { @@ -135,13 +136,20 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { } } - arguments := makeArguments() - arguments.addArg("S", "asdeps") - depArgs := arguments.formatArgs() + arguments := cmdArgs.copy() + arguments.addArg("asdeps") + arguments.delArg("asexplicit", "ase", "asex") + arguments.delArg("u", "sysupgrade") + arguments.delArg("y", "refresh") + arguments.targets = make(stringSet) + var depArgs []string if config.NoConfirm { - arguments.addArg("noconfirm") + depArgs = []string{"--asdeps", "--noconfirm"} + } else { + depArgs = []string{"--asdeps"} } + // Repo dependencies if len(repoDeps) != 0 { errR := passToPacman(arguments) diff --git a/upgrade.go b/upgrade.go index ff60f149..2fe9ed7d 100644 --- a/upgrade.go +++ b/upgrade.go @@ -334,7 +334,7 @@ func upgradePkgs(flags []string) error { } arguments := makeArguments() - arguments.addArg("-S --noconfirm") + arguments.addArg("S", "noconfirm") arguments.addArg(flags...) arguments.addTarget(repoNames...) From c0fc086a07a9b5c1099bb2d5e039e5f1b54c617e Mon Sep 17 00:00:00 2001 From: morganamilo Date: Thu, 4 Jan 2018 21:21:39 +0000 Subject: [PATCH 11/12] Pass command line arguments to alpmConf before init This allows us to use command line options such as '--root' and '-b' when performing operations that use out alom handle. Sadly this does not apply to passToMakepkg which will ignore options such as '--root' and because we pass '-i' to makepkg it installs for us using the default options. Currently I have not planned a solution for this but one which I thought of but not looked into is. Always call makepkg without arguments (except from '--noconfirm' and others which might still be needed) and manage the dependancies and post install outselves. Another option might be to use makepkg's $PACMAN enviroment variable and redirect the pacman calls to yay. Although I am unsure about both stratergys they are just my current thoughts. Also while editing the flow of cmd.go, I managed to refactor away all os.Exit calls apart from the very last so it should be more clear as to where the program exits. --- cmd.go | 124 +++++++++++++++++++++++++++++++++++++----------------- parser.go | 33 +++++++++++---- 2 files changed, 109 insertions(+), 48 deletions(-) diff --git a/cmd.go b/cmd.go index d1413b12..79470d72 100644 --- a/cmd.go +++ b/cmd.go @@ -55,10 +55,9 @@ If no operation is provided -Y will be assumed `) } -func init() { +func initYay() (err error){ var configHome string // configHome handles config directory home var cacheHome string // cacheHome handles cache home - var err error if 0 == os.Geteuid() { fmt.Println("Please avoid running yay as root/sudo.") @@ -96,15 +95,15 @@ func init() { if _, err = os.Stat(configFile); os.IsNotExist(err) { err = os.MkdirAll(filepath.Dir(configFile), 0755) if err != nil { - fmt.Println("Unable to create config directory:", filepath.Dir(configFile), err) - os.Exit(2) + err = fmt.Errorf("Unable to create config directory:", 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.Println("Error reading config:", err) + fmt.Println("Error reading config: %s", err) } else { defer cfile.Close() decoder := json.NewDecoder(cfile) @@ -127,65 +126,110 @@ func init() { decoder := json.NewDecoder(vfile) _ = decoder.Decode(&savedInfo) } + + return +} +func initAlpm() (err error){ ///////////////// // alpm config // ///////////////// + + 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 { - fmt.Println("Unable to read Pacman conf", err) - os.Exit(1) + 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 + } + + //TODO + //current system does not allow duplicate arguments + //but pacman allows multiple cachdirs to be passed + //for now only hanle 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 { - fmt.Println("Unable to CreateHandle", err) - os.Exit(1) + err = fmt.Errorf("Unable to CreateHandle", err) + return } + + return } func main() { - status := run() - - err := alpmHandle.Release() - if err != nil { - fmt.Println(err) - status = 1 - } - - os.Exit(status) -} - -func run() (status int) { + var status int = 0 var err error var changedConfig bool err = cmdArgs.parseCommandLine(); - if err != nil { fmt.Println(err) status = 1 - return + goto cleanup } - if cmdArgs.existsArg("-") { - err = cmdArgs.parseStdin(); + err = initYay() + if err != nil { + fmt.Println(err) + status = 1 + goto cleanup + } - if err != nil { - fmt.Println(err) - status = 1 - return - } + err = initAlpm() + if err != nil { + fmt.Println(err) + status = 1 + goto cleanup } changedConfig, err = handleCmd() - if err != nil { fmt.Println(err) status = 1 - //try continue onward + goto cleanup } + //ive used a goto here + //i think its the best way to do this sort of thing +cleanup: + //cleanup + //from here on out dont exit if an error occurs + //if we fail to save the configuration + //atleast continue on and try clean up other parts + + if updated { err = saveVCSInfo() @@ -205,11 +249,17 @@ func run() (status int) { } - return + if alpmHandle != nil { + err = alpmHandle.Release() + if err != nil { + fmt.Println(err) + status = 1 + } + } + os.Exit(status) } - func handleCmd() (changedConfig bool, err error) { changedConfig = false @@ -534,10 +584,6 @@ func passToPacman(args *arguments) error { argArr = append(argArr, args.formatArgs()...) argArr = append(argArr, args.formatTargets()...) - - fmt.Println(cmdArgs) - fmt.Println(args) - fmt.Println(argArr) cmd = exec.Command(argArr[0], argArr[1:]...) @@ -560,4 +606,4 @@ func passToMakepkg(dir string, args ...string) (err error) { } } return -} \ No newline at end of file +} diff --git a/parser.go b/parser.go index 35b71ab6..3c945093 100644 --- a/parser.go +++ b/parser.go @@ -195,16 +195,23 @@ func (parser *arguments) existsArg(options ...string) bool { return false } -func (parser *arguments) getArg(option string) (arg string, double bool, exists bool) { - arg, exists = parser.options[option] - - if exists { - _, double = parser.doubles[option] - return - } +func (parser *arguments) getArg(options ...string) (arg string, double bool, exists bool) { + for _, option := range options { + arg, exists = parser.options[option] - arg, exists = parser.globals[option] - _, double = parser.doubles[option] + if exists { + _, double = parser.doubles[option] + return + } + + arg, exists = parser.globals[option] + + if exists { + _, double = parser.doubles[option] + return + } + } + return } @@ -523,5 +530,13 @@ func (parser *arguments)parseCommandLine() (err error) { parser.op = "Y" } + if cmdArgs.existsArg("-") { + err = cmdArgs.parseStdin(); + + if err != nil { + return + } + } + return } \ No newline at end of file From 142cb25f958b97237b6a0c5a91957abcd30efa25 Mon Sep 17 00:00:00 2001 From: morganamilo Date: Fri, 5 Jan 2018 22:12:14 +0000 Subject: [PATCH 12/12] Fix deps not being passed to pacman properly --- cmd.go | 4 ++-- install.go | 19 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/cmd.go b/cmd.go index 79470d72..0c323199 100644 --- a/cmd.go +++ b/cmd.go @@ -389,7 +389,7 @@ func handleYay() (err error) { err = localStatistics() } else if cmdArgs.existsArg("cleandeps") { err = cleanDependencies() - } else { + } else if len(cmdArgs.targets) > 0 { err = handleYogurt() } @@ -533,7 +533,7 @@ func numberMenu(pkgS []string, flags []string) (err error) { } if len(aurI) != 0 { - err = aurInstall(aurI, make([]string,0)) + err = aurInstall(aurI, nil) } return err diff --git a/install.go b/install.go index d0834e55..61935576 100644 --- a/install.go +++ b/install.go @@ -18,7 +18,7 @@ func install(parser *arguments) error { arguments.delArg("y", "refresh") arguments.targets = make(stringSet) arguments.addTarget(repos...) - + if len(repos) != 0 { err := passToPacman(arguments) if err != nil { @@ -27,7 +27,7 @@ func install(parser *arguments) error { } if len(aurs) != 0 { - err := aurInstall(aurs, make([]string,0)) + err := aurInstall(aurs, []string{"-S"}) if err != nil { fmt.Println("Error installing aur packages.") } @@ -136,18 +136,15 @@ func PkgInstall(a *rpc.Pkg, flags []string) (finalmdeps []string, err error) { } } - arguments := cmdArgs.copy() - arguments.addArg("asdeps") - arguments.delArg("asexplicit", "ase", "asex") - arguments.delArg("u", "sysupgrade") - arguments.delArg("y", "refresh") - arguments.targets = make(stringSet) - + arguments := makeArguments() + arguments.addArg("S", "asdeps", "noconfirm") + arguments.addTarget(repoDeps...) + var depArgs []string if config.NoConfirm { - depArgs = []string{"--asdeps", "--noconfirm"} + depArgs = []string{"asdeps", "noconfirm"} } else { - depArgs = []string{"--asdeps"} + depArgs = []string{"asdeps"} } // Repo dependencies