-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cobra Command Fails to remove flag when runs in a Interactive mode #1419
Comments
You have to use the Line 185 in 4590150
I hope this helps. |
thanks for the quick response, I believe when we execute rootCmd.Execute() then cobra should do it automatically because if I need to set nonPersistentFlag.Changed = false, then I have to do for all the commands and their subcommands |
@marckhouzam I tried var testCmd = &cobra.Command{ |
I think we need to take a step back and look at why you would want to do this @debankur1. The uses of Cobra that I've seen do a single What is your scenario that would require you to reset the flags manually? |
@marckhouzam The scenario is simple, let us consider user want to use Interactive Shell (https://github.com/abiosoft/ishell) func main(){ and user wants to run the cobra command from the interactive shell i.e. rootCmd.Execute() , but the problem is rootCmd.Execute() holds a reference to the memory once it is executed that is not correct. This is a pretty valid case where users may like to use the power of Cobra in an interactive way. Maybe post rootCmd.Execute() it should initialize once again so that all the flags are reset or it should behave as if a user is running a new command. |
@marckhouzam I have found a workaround to reset the flag (in my case it is help) func (c *Command) ExecuteC() (cmd *Command, err error){ |
This issue is being marked as stale due to a long period of inactivity |
@marckhouzam I stumbled on the same problem, in my case is in testing. I created a small example to show the problem. main.go: package main
import (
"github.com/spf13/cobra"
)
var (
cmd *cobra.Command
shouldContinue bool
)
func init() {
cmd = &cobra.Command{
Use: "debug",
Run: func(cmd *cobra.Command, args []string) {
cmd.Print("Step 1")
if shouldContinue {
cmd.Print("Step 2")
return
}
},
}
cmd.Flags().BoolVar(&shouldContinue, "continue", false, "test")
}
func main() {
cmd.Execute()
} main_test.go: package main
import (
"strings"
"testing"
"github.com/g14a/metana/pkg"
"github.com/stretchr/testify/assert"
)
func TestFull(t *testing.T) {
test := []struct {
args []string
output string
}{
{
args: []string{"--continue"},
output: strings.Join([]string{"Step 1", "Step 2"}, ""),
},
{
args: []string{},
output: strings.Join([]string{"Step 1"}, ""),
},
}
for i, tt := range test {
_, out, _ := pkg.ExecuteCommandC(cmd, tt.args...)
t.Log(i, out, tt.args)
assert.NotEmpty(t, out)
assert.Equal(t, tt.output, out)
}
} PS.: I'm aware that changing the order in this test case would fix the problem, however in complex commands that might no be possible. |
If the executable is run from Windows Explorer, then the program will enter a mode that allows commands to be used interactively. NOTE: Cobra commands are currently not designed to be run more than once. Because of this, the behavior is locked behind the "interactive_commands" build tag. Progress on a solution can be tracked here: spf13/cobra#1419
I'am facing the same issue in my tests. 😢 |
I've run into the same thing in my tests. I believe the issue is caused by the way Cobra uses global variables. I've tried which has the workaround: https://github.com/cli/cli/blob/c0c28622bd62b273b32838dfdfa7d5ffc739eeeb/command/pr_test.go#L55-L67 The alternative is to restructure each command into a factory and don't use the magic |
When cobra command is executed via API e.g. rootCmd.Execute() in an interactive mode, it keeps the flags that were persisted from the previous command here are the code snippet and test results.
package main
import (
"bufio"
"fmt"
"github.com/spf13/cobra"
"os"
"strings"
)
func main() {
for {
reader := bufio.NewReader(os.Stdin)
input, _, _ := reader.ReadLine()
args := strings.Split(string(input), " ")
rootCmd.SetArgs(args)
rootCmd.Execute()
fmt.Println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
}
var rootCmd = &cobra.Command{
Use: "cli",
Short: "test app to test iShell like usage in cobra",
}
var testCmd = &cobra.Command{
Use: "tcmd",
Short: "test cmd for cobra command",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hello World")
},
}
func init() {
rootCmd.AddCommand(testCmd)
}
tcmd
Hello World
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
tcmd -h
test cmd for cobra command
Usage:
cli tcmd [flags]
Flags:
-h, --help help for tcmd
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
tcmd
test cmd for cobra command
Usage:
cli tcmd [flags]
Flags:
-h, --help help for tcmd
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
As it can be clearly seen that after running the command with a flag -h or --help next time it uses the same flag , instead running the entire command.
Same thing I have testes with iShell
func main(){
shell := ishell.New()
shell.Println("Sample Interactive Shell")
shell.AddCmd(&ishell.Cmd{
Name: "test",
Help: "Test Command Help",
Func: func(c *ishell.Context) {
rootCmd.SetArgs(c.RawArgs)
rootCmd.Execute()
},
})
shell.Run()
}
Have also tried the cmd.RestFlags() it didn't work.
Any help is really appreciated.
The text was updated successfully, but these errors were encountered: