mirror of
https://github.com/Jguer/yay.git
synced 2024-11-06 17:17:22 +01:00
96f499ff44
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.
425 lines
6.9 KiB
Go
425 lines
6.9 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"fmt"
|
|
"strings"
|
|
"io"
|
|
)
|
|
|
|
type stringSet map[string]struct{}
|
|
|
|
func (set stringSet) getAny() string {
|
|
for v := range set {
|
|
return v
|
|
}
|
|
|
|
//maybe should return error instrad
|
|
return ""
|
|
}
|
|
|
|
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(stringSet),
|
|
make(stringSet),
|
|
}
|
|
}
|
|
|
|
func (parser *arguments) delArg(options ...string) {
|
|
for _, option := range options {
|
|
delete(parser.options, option)
|
|
delete(parser.doubles, option)
|
|
}
|
|
}
|
|
|
|
func (parser *arguments) needRoot() bool {
|
|
if parser.existsArg("h", "help") {
|
|
return false
|
|
}
|
|
|
|
if parser.existsArg("p", "print") {
|
|
return false
|
|
}
|
|
|
|
switch parser.op {
|
|
case "V", "version":
|
|
return false
|
|
case "D", "database":
|
|
return true
|
|
case "F", "files":
|
|
if parser.existsArg("y", "refresh") {
|
|
return true
|
|
}
|
|
return false
|
|
case "Q", "query":
|
|
return false
|
|
case "R", "remove":
|
|
return true
|
|
case "S", "sync":
|
|
if parser.existsArg("s", "search") {
|
|
return false
|
|
}
|
|
if parser.existsArg("l", "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 (parser *arguments) addOP(op string) (err error) {
|
|
if parser.op != "" {
|
|
err = fmt.Errorf("only one operation may be used at a time")
|
|
return
|
|
}
|
|
|
|
parser.op = op
|
|
return
|
|
}
|
|
|
|
func (parser *arguments) addParam(option string, arg string) (err error) {
|
|
if isOp(option) {
|
|
err = parser.addOP(option)
|
|
return
|
|
}
|
|
|
|
if parser.existsArg(option) {
|
|
parser.doubles[option] = struct{}{}
|
|
} else {
|
|
parser.options[option] = arg
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (parser *arguments) addArg(options ...string) (err error) {
|
|
for _, option := range options {
|
|
err = parser.addParam(option, "")
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
//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 (parser *arguments) getArg(option string) (arg string, double bool, exists bool) {
|
|
arg, exists = parser.options[option]
|
|
_, double = parser.doubles[option]
|
|
return
|
|
}
|
|
|
|
func (parser *arguments) addTarget(targets ...string) {
|
|
for _, target := range targets {
|
|
parser.targets[target] = struct{}{}
|
|
}
|
|
}
|
|
|
|
func (parser *arguments) delTarget(targets ...string) {
|
|
for _, target := range targets {
|
|
delete(parser.targets, target)
|
|
}
|
|
}
|
|
|
|
//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 *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)
|
|
|
|
for option, arg := range parser.options {
|
|
option = formatArg(option)
|
|
args = append(args, option)
|
|
|
|
if arg != "" {
|
|
args = append(args, arg)
|
|
}
|
|
|
|
if parser.existsDouble(option) {
|
|
args = append(args, option)
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
//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
|
|
}
|
|
}
|
|
|
|
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 *arguments) 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 *arguments) 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 *arguments) 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 *arguments)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
|
|
} |