From 56760e1b7c8e97b980656510d749d094a49c3e60 Mon Sep 17 00:00:00 2001 From: jguer Date: Mon, 6 Jul 2020 00:28:04 +0200 Subject: [PATCH] fix(parser): add support for stackable parameters. Fixes #1155, Fixes #1280 --- install.go | 14 +++-- pkg/settings/parser.go | 110 ++++++++++++++++++++-------------------- pkg/settings/runtime.go | 4 +- 3 files changed, 68 insertions(+), 60 deletions(-) diff --git a/install.go b/install.go index 08201aac..48b58fa9 100644 --- a/install.go +++ b/install.go @@ -145,7 +145,13 @@ func install(parser *settings.Arguments, alpmHandle *alpm.Handle) (err error) { if exists { ignoreStr += "," + value } - arguments.Options["ignore"] = ignoreStr + if arguments.Options["ignore"] == nil { + arguments.Options["ignore"] = &settings.Option{ + Args: []string{ignoreStr}, + } + } else { + arguments.Options["ignore"].Add(ignoreStr) + } } } @@ -1099,10 +1105,10 @@ func buildInstallPkgbuilds( } // conflicts have been checked so answer y for them - if config.UseAsk { - ask, _ := strconv.Atoi(cmdArgs.Globals["ask"]) + if config.UseAsk && cmdArgs.ExistsArg("ask") { + ask, _ := strconv.Atoi(cmdArgs.Options["ask"].First()) uask := alpm.QuestionType(ask) | alpm.QuestionTypeConflictPkg - cmdArgs.Globals["ask"] = fmt.Sprint(uask) + cmdArgs.Options["ask"].Set(fmt.Sprint(uask)) } else { for _, split := range base { if _, ok := conflicts[split.Name]; ok { diff --git a/pkg/settings/parser.go b/pkg/settings/parser.go index 3a4d7088..1c64fba7 100644 --- a/pkg/settings/parser.go +++ b/pkg/settings/parser.go @@ -9,26 +9,45 @@ import ( "github.com/leonelquinteros/gotext" rpc "github.com/mikkeloscar/aur" "github.com/pkg/errors" - - "github.com/Jguer/yay/v10/pkg/stringset" ) +type Option struct { + Args []string +} + +func (o *Option) Add(arg string) { + if o.Args == nil { + o.Args = []string{arg} + return + } + o.Args = append(o.Args, arg) +} + +func (o *Option) First() string { + if o.Args == nil || len(o.Args) == 0 { + return "" + } + return o.Args[0] +} + +func (o *Option) Set(arg string) { + o.Args = []string{arg} +} + // Arguments Parses command line arguments in a way we can interact with programmatically but // also in a way that can easily be passed to pacman later on. type Arguments struct { Op string - Options map[string]string - Globals map[string]string - Doubles stringset.StringSet // Tracks args passed twice such as -yy and -dd + Options map[string]*Option + Globals map[string]*Option Targets []string } func MakeArguments() *Arguments { return &Arguments{ "", - make(map[string]string), - make(map[string]string), - make(stringset.StringSet), + make(map[string]*Option), + make(map[string]*Option), make([]string, 0), } } @@ -58,10 +77,6 @@ func (parser *Arguments) Copy() (cp *Arguments) { cp.Targets = make([]string, len(parser.Targets)) copy(cp.Targets, parser.Targets) - for k, v := range parser.Doubles { - cp.Doubles[k] = v - } - return } @@ -69,7 +84,6 @@ func (parser *Arguments) DelArg(options ...string) { for _, option := range options { delete(parser.Options, option) delete(parser.Globals, option) - delete(parser.Doubles, option) } } @@ -150,12 +164,16 @@ func (parser *Arguments) addParam(option, arg string) (err error) { } switch { - case parser.ExistsArg(option): - parser.Doubles[option] = struct{}{} case isGlobal(option): - parser.Globals[option] = arg + if parser.Globals[option] == nil { + parser.Globals[option] = &Option{} + } + parser.Globals[option].Add(arg) default: - parser.Options[option] = arg + if parser.Options[option] == nil { + parser.Options[option] = &Option{} + } + parser.Options[option].Add(arg) } return @@ -189,40 +207,21 @@ func (parser *Arguments) ExistsArg(options ...string) bool { } func (parser *Arguments) GetArg(options ...string) (arg string, double, exists bool) { - existCount := 0 - for _, option := range options { - var value string - - value, exists = parser.Options[option] - + value, exists := parser.Options[option] if exists { - arg = value - existCount++ - _, exists = parser.Doubles[option] - - if exists { - existCount++ - } + arg = value.First() + return arg, len(value.Args) >= 2, len(value.Args) >= 1 } value, exists = parser.Globals[option] - if exists { - arg = value - existCount++ - _, exists = parser.Doubles[option] - - if exists { - existCount++ - } + arg = value.First() + return arg, len(value.Args) >= 2, len(value.Args) >= 1 } } - double = existCount >= 2 - exists = existCount >= 1 - - return arg, double, exists + return arg, false, false } func (parser *Arguments) AddTarget(targets ...string) { @@ -236,9 +235,14 @@ func (parser *Arguments) ClearTargets() { // Multiple args acts as an OR operator func (parser *Arguments) ExistsDouble(options ...string) bool { for _, option := range options { - _, exists := parser.Doubles[option] + value, exists := parser.Options[option] if exists { - return true + return len(value.Args) >= 2 + } + + value, exists = parser.Globals[option] + if exists { + return len(value.Args) >= 2 } } @@ -260,14 +264,12 @@ func (parser *Arguments) FormatArgs() (args []string) { } formattedOption := formatArg(option) - args = append(args, formattedOption) - if hasParam(option) { - args = append(args, arg) - } - - if parser.ExistsDouble(option) { + for _, value := range arg.Args { args = append(args, formattedOption) + if hasParam(option) { + args = append(args, value) + } } } @@ -280,7 +282,7 @@ func (parser *Arguments) FormatGlobals() (args []string) { args = append(args, formattedOption) if hasParam(option) { - args = append(args, arg) + args = append(args, arg.First()) } if parser.ExistsDouble(option) { @@ -288,7 +290,7 @@ func (parser *Arguments) FormatGlobals() (args []string) { } } - return + return args } func formatArg(arg string) string { @@ -833,13 +835,13 @@ func (parser *Arguments) ParseCommandLine(config *Configuration) error { func (parser *Arguments) extractYayOptions(config *Configuration) { for option, value := range parser.Options { - if handleConfig(config, option, value) { + if handleConfig(config, option, value.First()) { parser.DelArg(option) } } for option, value := range parser.Globals { - if handleConfig(config, option, value) { + if handleConfig(config, option, value.First()) { parser.DelArg(option) } } diff --git a/pkg/settings/runtime.go b/pkg/settings/runtime.go index 6327f0a3..045c1bc7 100644 --- a/pkg/settings/runtime.go +++ b/pkg/settings/runtime.go @@ -49,7 +49,7 @@ func MakeRuntime() (*Runtime, error) { if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" { configHome = filepath.Join(configHome, "yay") } else if configHome = os.Getenv("HOME"); configHome != "" { - configHome = filepath.Join(configHome, ".config/yay") + configHome = filepath.Join(configHome, ".config", "yay") } else { return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CONFIG_HOME", "HOME")) } @@ -61,7 +61,7 @@ func MakeRuntime() (*Runtime, error) { if cacheHome = os.Getenv("XDG_CACHE_HOME"); cacheHome != "" { cacheHome = filepath.Join(cacheHome, "yay") } else if cacheHome = os.Getenv("HOME"); cacheHome != "" { - cacheHome = filepath.Join(cacheHome, ".cache/yay") + cacheHome = filepath.Join(cacheHome, ".cache", "yay") } else { return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CACHE_HOME", "HOME")) }