Hi, I've been reading the documentation on the readme that says that the When the subcommand is executed, it will run the root command's PersistentPreRun but not the root command's PersistentPostRun , but the PersistentPreRun isn't getting executed.
package main
import (
"fmt"
"github.com/spf13/cobra"
)
func main() {
var rootCmd = &cobra.Command{
Use: "root [sub]",
Short: "My root command",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args)
},
PreRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside rootCmd PreRun with args: %v\n", args)
},
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside rootCmd Run with args: %v\n", args)
},
PostRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside rootCmd PostRun with args: %v\n", args)
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args)
},
}
var subCmd = &cobra.Command{
Use: "sub [no options!]",
Short: "My subcommand",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside subCmd PersistentPreRun with args: %v\n", args)
},
PreRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside subCmd PreRun with args: %v\n", args)
},
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside subCmd Run with args: %v\n", args)
},
PostRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside subCmd PostRun with args: %v\n", args)
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args)
},
}
rootCmd.AddCommand(subCmd)
_ = rootCmd.Execute()
}
root@vagrant-ubuntu-vivid-64:/tmp# go version
go version go1.5.2 linux/amd64
root@vagrant-ubuntu-vivid-64:/tmp# go build test.go
root@vagrant-ubuntu-vivid-64:/tmp# ./test
Inside rootCmd PersistentPreRun with args: []
Inside rootCmd PreRun with args: []
Inside rootCmd Run with args: []
Inside rootCmd PostRun with args: []
Inside rootCmd PersistentPostRun with args: []
root@vagrant-ubuntu-vivid-64:/tmp# ./test sub arg1 arg2 arg3
Inside subCmd PersistentPreRun with args: [arg1 arg2 arg3]
Inside subCmd PreRun with args: [arg1 arg2 arg3]
Inside subCmd Run with args: [arg1 arg2 arg3]
Inside subCmd PostRun with args: [arg1 arg2 arg3]
Inside subCmd PersistentPostRun with args: [arg1 arg2 arg3]
the second example should have also had the output "Inside rootCmd PersistentPreRun" right ?
No, you overwrote the PersistentPreRun in the subcommand. If you didn't define a PersistentPreRun in the subcommand, as in the README, then the root PersistentPreRun would be run...
@eparis Is there any way of chaining PersistentPreRuns ? I'd like it to run the parent and then the child.
Today the only option is to call the parent pre run in your pre run. Patches to cobra to allow persistent chaining would be welcome :)
@eparis thank you. I've already got something working.I would like to know what would gel well with your existing naming convention.
Right now I have PreRunChain and PreRunChainE and PostRunChain and PostRunChainE
Just fell into this trap too. As the commands are structured into a tree, it makes unnatural not calling {Pre, Post}*Run() during a tree walk. So at least it should be documented as ""do it yourself ;)
Came across this issue myself.
This suggestion is the way to go:
Today the only option is to call the parent pre run in your pre run. Patches to cobra to allow persistent chaining would be welcome :)
As an example, I added this to my child command's PersistentPreRun:
// Call parent pre-run
if rootCmd.PersistentPreRun != nil {
rootCmd.PersistentPreRun(cmd, args)
}
Just got caught out on this as well and found this thread. I didn't want my subcommand to have direct knowledge of an ancestor command so I did something like this:
func callPersistentPreRun(cmd *cobra.Command, args []string) {
if parent := cmd.Parent(); parent != nil {
if parent.PersistentPreRun != nil {
parent.PersistentPreRun(parent, args)
}
}
}
sub := &cobra.Command{
...
PersistentPreRun: func(cmd *cobra.Command, args []string) {
callPersistentPreRun(cmd, args)
...
},
},
Most helpful comment
Just fell into this trap too. As the commands are structured into a tree, it makes unnatural not calling
{Pre, Post}*Run()during a tree walk. So at least it should be documented as ""do it yourself ;)