Skip to content

Commit

Permalink
fix: #3390 name&shor tag mapping failed to command input object for p…
Browse files Browse the repository at this point in the history
…ackage gcmd (#3429)
  • Loading branch information
gqcn committed Apr 1, 2024
1 parent 509fdf4 commit e0a2645
Show file tree
Hide file tree
Showing 11 changed files with 383 additions and 96 deletions.
4 changes: 2 additions & 2 deletions contrib/drivers/mysql/mysql_z_unit_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4669,13 +4669,13 @@ func TestResult_Structs1(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
r := gdb.Result{
gdb.Record{"id": gvar.New(nil), "name": gvar.New("john")},
gdb.Record{"id": gvar.New(nil), "name": gvar.New("smith")},
gdb.Record{"id": gvar.New(1), "name": gvar.New("smith")},
}
array := make([]*B, 2)
err := r.Structs(&array)
t.AssertNil(err)
t.Assert(array[0].Id, 0)
t.Assert(array[1].Id, 0)
t.Assert(array[1].Id, 1)
t.Assert(array[0].Name, "john")
t.Assert(array[1].Name, "smith")
})
Expand Down
10 changes: 5 additions & 5 deletions internal/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
var (
defaultParsedArgs = make([]string, 0)
defaultParsedOptions = make(map[string]string)
argumentRegex = regexp.MustCompile(`^\-{1,2}([\w\?\.\-]+)(=){0,1}(.*)$`)
argumentOptionRegex = regexp.MustCompile(`^\-{1,2}([\w\?\.\-]+)(=){0,1}(.*)$`)
)

// Init does custom initialization.
Expand All @@ -41,22 +41,22 @@ func ParseUsingDefaultAlgorithm(args ...string) (parsedArgs []string, parsedOpti
parsedArgs = make([]string, 0)
parsedOptions = make(map[string]string)
for i := 0; i < len(args); {
array := argumentRegex.FindStringSubmatch(args[i])
array := argumentOptionRegex.FindStringSubmatch(args[i])
if len(array) > 2 {
if array[2] == "=" {
parsedOptions[array[1]] = array[3]
} else if i < len(args)-1 {
if len(args[i+1]) > 0 && args[i+1][0] == '-' {
// Eg: gf gen -d -n 1
// Example: gf gen -d -n 1
parsedOptions[array[1]] = array[3]
} else {
// Eg: gf gen -n 2
// Example: gf gen -n 2
parsedOptions[array[1]] = args[i+1]
i += 2
continue
}
} else {
// Eg: gf gen -h
// Example: gf gen -h
parsedOptions[array[1]] = array[3]
}
} else {
Expand Down
8 changes: 7 additions & 1 deletion net/gudp/gudp_z_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package gudp_test
import (
"context"
"fmt"
"io"
"testing"
"time"

Expand All @@ -29,9 +30,14 @@ func startUDPServer(addr string) *gudp.Server {
for {
data, err := conn.Recv(-1)
if err != nil {
if err != io.EOF {
glog.Error(context.TODO(), err)
}
break
}
conn.Send(data)
if err = conn.Send(data); err != nil {
glog.Error(context.TODO(), err)
}
}
})
go s.Run()
Expand Down
6 changes: 3 additions & 3 deletions os/gcmd/gcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import (
)

const (
CtxKeyParser gctx.StrKey = `CtxKeyParser`
CtxKeyCommand gctx.StrKey = `CtxKeyCommand`
CtxKeyArguments gctx.StrKey = `CtxKeyArguments`
CtxKeyParser gctx.StrKey = `CtxKeyParser`
CtxKeyCommand gctx.StrKey = `CtxKeyCommand`
CtxKeyArgumentsIndex gctx.StrKey = `CtxKeyArgumentsIndex`
)

const (
Expand Down
21 changes: 17 additions & 4 deletions os/gcmd/gcmd_command_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ func newCommandFromMethod(
return
}

// For input struct converting using priority tag.
var priorityTag = gstr.Join([]string{tagNameName, tagNameShort}, ",")

// =============================================================================================
// Create function that has value return.
// =============================================================================================
Expand All @@ -259,9 +262,16 @@ func newCommandFromMethod(
var (
data = gconv.Map(parser.GetOptAll())
argIndex = 0
arguments = gconv.Strings(ctx.Value(CtxKeyArguments))
arguments = parser.GetArgAll()
inputValues = []reflect.Value{reflect.ValueOf(ctx)}
)
if value := ctx.Value(CtxKeyArgumentsIndex); value != nil {
argIndex = value.(int)
// Use the left args to assign to input struct object.
if argIndex < len(arguments) {
arguments = arguments[argIndex:]
}
}
if data == nil {
data = map[string]interface{}{}
}
Expand All @@ -278,8 +288,11 @@ func newCommandFromMethod(
if arg.Orphan {
if orphanValue := parser.GetOpt(arg.Name); orphanValue != nil {
if orphanValue.String() == "" {
// Eg: gf -f
// Example: gf -f
data[arg.Name] = "true"
if arg.Short != "" {
data[arg.Short] = "true"
}
} else {
// Adapter with common user habits.
// Eg:
Expand All @@ -301,9 +314,9 @@ func newCommandFromMethod(
return fmt.Sprintf(`input command data map: %s`, gjson.MustEncode(data))
})
if inputObject.Kind() == reflect.Ptr {
err = gconv.Scan(data, inputObject.Interface())
err = gconv.StructTag(data, inputObject.Interface(), priorityTag)
} else {
err = gconv.Struct(data, inputObject.Addr().Interface())
err = gconv.StructTag(data, inputObject.Addr().Interface(), priorityTag)
}
intlog.PrintFunc(ctx, func() string {
return fmt.Sprintf(`input object assigned data: %s`, gjson.MustEncode(inputObject.Interface()))
Expand Down
22 changes: 12 additions & 10 deletions os/gcmd/gcmd_command_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (c *Command) RunWithSpecificArgs(ctx context.Context, args []string) (value
parsedArgs = parsedArgs[1:]

// Find the matched command and run it.
lastCmd, foundCmd, newCtx := c.searchCommand(ctx, parsedArgs)
lastCmd, foundCmd, newCtx := c.searchCommand(ctx, parsedArgs, 0)
if foundCmd != nil {
return foundCmd.doRun(newCtx, args, parser)
}
Expand Down Expand Up @@ -215,25 +215,27 @@ func (c *Command) reParse(ctx context.Context, args []string, parser *Parser) (*
}

// searchCommand recursively searches the command according given arguments.
func (c *Command) searchCommand(ctx context.Context, args []string) (lastCmd, foundCmd *Command, newCtx context.Context) {
func (c *Command) searchCommand(
ctx context.Context, args []string, fromArgIndex int,
) (lastCmd, foundCmd *Command, newCtx context.Context) {
if len(args) == 0 {
return c, nil, ctx
}
for _, cmd := range c.commands {
// Recursively searching the command.
// String comparison case-sensitive.
if cmd.Name == args[0] {
leftArgs := args[1:]
// If this command needs argument,
// it then gives all its left arguments to it.
if cmd.hasArgumentFromIndex() {
ctx = context.WithValue(ctx, CtxKeyArguments, leftArgs)
// it then gives all its left arguments to it using arg index marks.
//
// Note that the args here (using default args parsing) could be different with the args
// that are parsed in command.
if cmd.hasArgumentFromIndex() || len(leftArgs) == 0 {
ctx = context.WithValue(ctx, CtxKeyArgumentsIndex, fromArgIndex+1)
return c, cmd, ctx
}
// Recursively searching.
if len(leftArgs) == 0 {
return c, cmd, ctx
}
return cmd.searchCommand(ctx, leftArgs)
return cmd.searchCommand(ctx, leftArgs, fromArgIndex+1)
}
}
return c, nil, ctx
Expand Down
21 changes: 17 additions & 4 deletions os/gcmd/gcmd_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,24 @@ func (p *Parser) isOptionNeedArgument(name string) bool {

// setOptionValue sets the option value for name and according alias.
func (p *Parser) setOptionValue(name, value string) {
// Accurate option name match.
for optionName := range p.passedOptions {
array := gstr.SplitAndTrim(optionName, ",")
for _, v := range array {
if strings.EqualFold(v, name) {
for _, v := range array {
optionNameAndShort := gstr.SplitAndTrim(optionName, ",")
for _, optionNameItem := range optionNameAndShort {
if optionNameItem == name {
for _, v := range optionNameAndShort {
p.parsedOptions[v] = value
}
return
}
}
}
// Fuzzy option name match.
for optionName := range p.passedOptions {
optionNameAndShort := gstr.SplitAndTrim(optionName, ",")
for _, optionNameItem := range optionNameAndShort {
if strings.EqualFold(optionNameItem, name) {
for _, v := range optionNameAndShort {
p.parsedOptions[v] = value
}
return
Expand Down
Loading

0 comments on commit e0a2645

Please sign in to comment.