Skip to content

Commit

Permalink
Merge pull request #1463 from montag451/fix-alias-args-handling
Browse files Browse the repository at this point in the history
incus: Fix alias arguments handling
  • Loading branch information
stgraber authored Dec 5, 2024
2 parents 1b047f0 + 4e58bc9 commit 78d8d53
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 28 deletions.
26 changes: 16 additions & 10 deletions cmd/incus/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,7 @@ func aliases() []string {
return aliases
}

func main() {
// Process aliases
err := execIfAliases()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}

func createApp() (*cobra.Command, *cmdGlobal) {
// Setup the parser
app := &cobra.Command{}
app.Use = "incus"
Expand Down Expand Up @@ -306,8 +299,14 @@ Custom commands can be defined through aliases, use "incus alias" to control tho
app.Flags().BoolVar(&globalCmd.flagHelpAll, "all", false, i18n.G("Show less common commands"))
help.Flags().BoolVar(&globalCmd.flagHelpAll, "all", false, i18n.G("Show less common commands"))

// Deal with --all flag and --sub-commands flag
err = app.ParseFlags(os.Args[1:])
return app, &globalCmd
}

func main() {
app, globalCmd := createApp()

// Deal with --all and --sub-commands flags as well as process aliases.
err := app.ParseFlags(os.Args[1:])
if err == nil {
if globalCmd.flagHelpAll {
// Show all commands
Expand All @@ -325,6 +324,13 @@ Custom commands can be defined through aliases, use "incus alias" to control tho
}
}

// Process aliases
err = execIfAliases(app)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}

// Run the main command and handle errors
err = app.Execute()
if err != nil {
Expand Down
43 changes: 26 additions & 17 deletions cmd/incus/main_aliases.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"

"github.com/kballard/go-shellquote"
"github.com/spf13/cobra"

"github.com/lxc/incus/v6/internal/i18n"
config "github.com/lxc/incus/v6/shared/cliconfig"
Expand Down Expand Up @@ -76,26 +77,36 @@ func findAlias(aliases map[string]string, origArgs []string) ([]string, []string
return aliasKey, aliasValue, foundAlias
}

func expandAlias(conf *config.Config, args []string) ([]string, bool, error) {
var completion = false
var completionFrament string
var newArgs []string
var origArgs []string
func expandAlias(conf *config.Config, args []string, app *cobra.Command) ([]string, bool, error) {
fset := app.Flags()

for _, arg := range args[1:] {
if !strings.HasPrefix(arg, "-") {
break
}
nargs := fset.NArg()
firstArgIndex := 1
firstPosArgIndex := 0
if fset.Arg(0) == "__complete" {
nargs--
firstArgIndex++
firstPosArgIndex++
}

newArgs = append(newArgs, arg)
if nargs == 0 {
return nil, false, nil
}

origArgs = append([]string{args[0]}, args[len(newArgs)+1:]...)
lastFlagIndex := slices.Index(args, fset.Arg(firstPosArgIndex))

// newArgs contains all the flags before the first positional argument
newArgs := args[firstArgIndex:lastFlagIndex]

// origArgs contains everything except the flags in newArgs
origArgs := slices.Concat(args[:firstArgIndex], args[lastFlagIndex:])

// strip out completion subcommand and fragment from end
completion := false
completionFragment := ""
if len(origArgs) >= 3 && origArgs[1] == "__complete" {
completion = true
completionFrament = origArgs[len(origArgs)-1]
completionFragment = origArgs[len(origArgs)-1]
origArgs = append(origArgs[:1], origArgs[2:len(origArgs)-1]...)
}

Expand Down Expand Up @@ -189,7 +200,7 @@ func expandAlias(conf *config.Config, args []string) ([]string, bool, error) {
// add back in completion if it was stripped before
if completion {
newArgs = append([]string{newArgs[0], "__complete"}, newArgs[1:]...)
newArgs = append(newArgs, completionFrament)
newArgs = append(newArgs, completionFragment)
}

// Add the rest of the arguments only if @ARGS@ wasn't used.
Expand All @@ -200,9 +211,7 @@ func expandAlias(conf *config.Config, args []string) ([]string, bool, error) {
return newArgs, true, nil
}

func execIfAliases() error {
args := os.Args

func execIfAliases(app *cobra.Command) error {
// Avoid loops
if os.Getenv("INCUS_ALIASES") == "1" {
return nil
Expand All @@ -214,7 +223,7 @@ func execIfAliases() error {
}

// Expand the aliases
newArgs, expanded, err := expandAlias(conf, args)
newArgs, expanded, err := expandAlias(conf, os.Args, app)
if err != nil {
return err
} else if !expanded {
Expand Down
12 changes: 11 additions & 1 deletion cmd/incus/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,22 @@ func TestExpandAliases(t *testing.T) {
input: []string{"incus", "snapshots", "with", "recursion", "c1", "2"},
expected: []string{"incus", "query", "/1.0/instances/c1/snapshots?recursion=2"},
},
{
input: []string{"incus", "--project", "default", "fizz", "c1", "buzz"},
expected: []string{"incus", "--project", "default", "exec", "c1", "--", "echo", "buzz"},
},
{
input: []string{"incus", "--project=default", "fizz", "c1", "buzz"},
expected: []string{"incus", "--project=default", "exec", "c1", "--", "echo", "buzz"},
},
}

conf := &config.Config{Aliases: aliases}

for _, tc := range testcases {
result, expanded, err := expandAlias(conf, tc.input)
app, _ := createApp()
_ = app.ParseFlags(tc.input[1:])
result, expanded, err := expandAlias(conf, tc.input, app)
if tc.expectErr {
assert.Error(t, err)
continue
Expand Down

0 comments on commit 78d8d53

Please sign in to comment.