fix(parser): add support for stackable parameters. Fixes #1155, Fixes #1280

This commit is contained in:
jguer 2020-07-06 00:28:04 +02:00
parent 5cc47503be
commit 56760e1b7c
No known key found for this signature in database
GPG key ID: 6D6CC9BEA8556B35
3 changed files with 68 additions and 60 deletions

View file

@ -145,7 +145,13 @@ func install(parser *settings.Arguments, alpmHandle *alpm.Handle) (err error) {
if exists { if exists {
ignoreStr += "," + value 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 // conflicts have been checked so answer y for them
if config.UseAsk { if config.UseAsk && cmdArgs.ExistsArg("ask") {
ask, _ := strconv.Atoi(cmdArgs.Globals["ask"]) ask, _ := strconv.Atoi(cmdArgs.Options["ask"].First())
uask := alpm.QuestionType(ask) | alpm.QuestionTypeConflictPkg uask := alpm.QuestionType(ask) | alpm.QuestionTypeConflictPkg
cmdArgs.Globals["ask"] = fmt.Sprint(uask) cmdArgs.Options["ask"].Set(fmt.Sprint(uask))
} else { } else {
for _, split := range base { for _, split := range base {
if _, ok := conflicts[split.Name]; ok { if _, ok := conflicts[split.Name]; ok {

View file

@ -9,26 +9,45 @@ import (
"github.com/leonelquinteros/gotext" "github.com/leonelquinteros/gotext"
rpc "github.com/mikkeloscar/aur" rpc "github.com/mikkeloscar/aur"
"github.com/pkg/errors" "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 // 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. // also in a way that can easily be passed to pacman later on.
type Arguments struct { type Arguments struct {
Op string Op string
Options map[string]string Options map[string]*Option
Globals map[string]string Globals map[string]*Option
Doubles stringset.StringSet // Tracks args passed twice such as -yy and -dd
Targets []string Targets []string
} }
func MakeArguments() *Arguments { func MakeArguments() *Arguments {
return &Arguments{ return &Arguments{
"", "",
make(map[string]string), make(map[string]*Option),
make(map[string]string), make(map[string]*Option),
make(stringset.StringSet),
make([]string, 0), make([]string, 0),
} }
} }
@ -58,10 +77,6 @@ func (parser *Arguments) Copy() (cp *Arguments) {
cp.Targets = make([]string, len(parser.Targets)) cp.Targets = make([]string, len(parser.Targets))
copy(cp.Targets, parser.Targets) copy(cp.Targets, parser.Targets)
for k, v := range parser.Doubles {
cp.Doubles[k] = v
}
return return
} }
@ -69,7 +84,6 @@ func (parser *Arguments) DelArg(options ...string) {
for _, option := range options { for _, option := range options {
delete(parser.Options, option) delete(parser.Options, option)
delete(parser.Globals, option) delete(parser.Globals, option)
delete(parser.Doubles, option)
} }
} }
@ -150,12 +164,16 @@ func (parser *Arguments) addParam(option, arg string) (err error) {
} }
switch { switch {
case parser.ExistsArg(option):
parser.Doubles[option] = struct{}{}
case isGlobal(option): case isGlobal(option):
parser.Globals[option] = arg if parser.Globals[option] == nil {
parser.Globals[option] = &Option{}
}
parser.Globals[option].Add(arg)
default: default:
parser.Options[option] = arg if parser.Options[option] == nil {
parser.Options[option] = &Option{}
}
parser.Options[option].Add(arg)
} }
return return
@ -189,40 +207,21 @@ func (parser *Arguments) ExistsArg(options ...string) bool {
} }
func (parser *Arguments) GetArg(options ...string) (arg string, double, exists bool) { func (parser *Arguments) GetArg(options ...string) (arg string, double, exists bool) {
existCount := 0
for _, option := range options { for _, option := range options {
var value string value, exists := parser.Options[option]
value, exists = parser.Options[option]
if exists { if exists {
arg = value arg = value.First()
existCount++ return arg, len(value.Args) >= 2, len(value.Args) >= 1
_, exists = parser.Doubles[option]
if exists {
existCount++
}
} }
value, exists = parser.Globals[option] value, exists = parser.Globals[option]
if exists { if exists {
arg = value arg = value.First()
existCount++ return arg, len(value.Args) >= 2, len(value.Args) >= 1
_, exists = parser.Doubles[option]
if exists {
existCount++
}
} }
} }
double = existCount >= 2 return arg, false, false
exists = existCount >= 1
return arg, double, exists
} }
func (parser *Arguments) AddTarget(targets ...string) { func (parser *Arguments) AddTarget(targets ...string) {
@ -236,9 +235,14 @@ func (parser *Arguments) ClearTargets() {
// Multiple args acts as an OR operator // Multiple args acts as an OR operator
func (parser *Arguments) ExistsDouble(options ...string) bool { func (parser *Arguments) ExistsDouble(options ...string) bool {
for _, option := range options { for _, option := range options {
_, exists := parser.Doubles[option] value, exists := parser.Options[option]
if exists { 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) formattedOption := formatArg(option)
args = append(args, formattedOption)
if hasParam(option) { for _, value := range arg.Args {
args = append(args, arg)
}
if parser.ExistsDouble(option) {
args = append(args, formattedOption) 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) args = append(args, formattedOption)
if hasParam(option) { if hasParam(option) {
args = append(args, arg) args = append(args, arg.First())
} }
if parser.ExistsDouble(option) { if parser.ExistsDouble(option) {
@ -288,7 +290,7 @@ func (parser *Arguments) FormatGlobals() (args []string) {
} }
} }
return return args
} }
func formatArg(arg string) string { func formatArg(arg string) string {
@ -833,13 +835,13 @@ func (parser *Arguments) ParseCommandLine(config *Configuration) error {
func (parser *Arguments) extractYayOptions(config *Configuration) { func (parser *Arguments) extractYayOptions(config *Configuration) {
for option, value := range parser.Options { for option, value := range parser.Options {
if handleConfig(config, option, value) { if handleConfig(config, option, value.First()) {
parser.DelArg(option) parser.DelArg(option)
} }
} }
for option, value := range parser.Globals { for option, value := range parser.Globals {
if handleConfig(config, option, value) { if handleConfig(config, option, value.First()) {
parser.DelArg(option) parser.DelArg(option)
} }
} }

View file

@ -49,7 +49,7 @@ func MakeRuntime() (*Runtime, error) {
if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" { if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
configHome = filepath.Join(configHome, "yay") configHome = filepath.Join(configHome, "yay")
} else if configHome = os.Getenv("HOME"); configHome != "" { } else if configHome = os.Getenv("HOME"); configHome != "" {
configHome = filepath.Join(configHome, ".config/yay") configHome = filepath.Join(configHome, ".config", "yay")
} else { } else {
return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CONFIG_HOME", "HOME")) 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 != "" { if cacheHome = os.Getenv("XDG_CACHE_HOME"); cacheHome != "" {
cacheHome = filepath.Join(cacheHome, "yay") cacheHome = filepath.Join(cacheHome, "yay")
} else if cacheHome = os.Getenv("HOME"); cacheHome != "" { } else if cacheHome = os.Getenv("HOME"); cacheHome != "" {
cacheHome = filepath.Join(cacheHome, ".cache/yay") cacheHome = filepath.Join(cacheHome, ".cache", "yay")
} else { } else {
return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CACHE_HOME", "HOME")) return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CACHE_HOME", "HOME"))
} }