Repository: spf13/cobra
Pull request #1748 (2022-07-02 20:43:37)

Clarify SetContext documentation
Documentation of Context() was fixed in #1639, especially the fact that the underlying ctx is set to context.Background when Execute() is called (otherwise returns nil). 

The documentation of SetContext() states that the ctx is set to context.Background "by default", which is a bit imprecise (and confused some coworker of mine). I think the Context() method provides the needed information when exactly the context is set to Background. I don't see a need to also document this behavior in the comment of SetContext(), as it is only interesting for a caller of Context().




Patch:
diff --git a/README.md b/README.md
index 2bf1520..a672c23 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
 Cobra is a library for creating powerful modern CLI applications.
 
 Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/),
-[Hugo](https://gohugo.io), and [Github CLI](https://github.com/cli/cli) to
+[Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to
 name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra.
 
 [![](https://img.shields.io/github/workflow/status/spf13/cobra/Test?longCache=tru&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest)
diff --git a/bash_completionsV2.go b/bash_completionsV2.go
index 767bf03..351391a 100644
--- a/bash_completionsV2.go
+++ b/bash_completionsV2.go
@@ -150,7 +150,7 @@ __%[1]s_process_completion_results() {
     __%[1]s_handle_special_char "$cur" =
 
     # Print the activeHelp statements before we finish
-    if [ ${#activeHelp} -ne 0 ]; then
+    if [ ${#activeHelp[*]} -ne 0 ]; then
         printf "\n";
         printf "%%s\n" "${activeHelp[@]}"
         printf "\n"
diff --git a/command.go b/command.go
index 675bb13..6e61133 100644
--- a/command.go
+++ b/command.go
@@ -236,8 +236,8 @@ func (c *Command) Context() context.Context {
 	return c.ctx
 }
 
-// SetContext sets context for the command. It is set to context.Background by default and will be overwritten by
-// Command.ExecuteContext or Command.ExecuteContextC
+// SetContext sets context for the command. This context will be overwritten by
+// Command.ExecuteContext or Command.ExecuteContextC.
 func (c *Command) SetContext(ctx context.Context) {
 	c.ctx = ctx
 }
@@ -1505,7 +1505,8 @@ func (c *Command) LocalFlags() *flag.FlagSet {
 	}
 
 	addToLocal := func(f *flag.Flag) {
-		if c.lflags.Lookup(f.Name) == nil && c.parentsPflags.Lookup(f.Name) == nil {
+		// Add the flag if it is not a parent PFlag, or it shadows a parent PFlag
+		if c.lflags.Lookup(f.Name) == nil && f != c.parentsPflags.Lookup(f.Name) {
 			c.lflags.AddFlag(f)
 		}
 	}
diff --git a/doc/yaml_docs.go b/doc/yaml_docs.go
index a79fa40..784c387 100644
--- a/doc/yaml_docs.go
+++ b/doc/yaml_docs.go
@@ -23,7 +23,7 @@ import (
 
 	"github.com/spf13/cobra"
 	"github.com/spf13/pflag"
-	"gopkg.in/yaml.v2"
+	"gopkg.in/yaml.v3"
 )
 
 type cmdOption struct {
@@ -128,7 +128,7 @@ func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) str
 			if !child.IsAvailableCommand() || child.IsAdditionalHelpTopicCommand() {
 				continue
 			}
-			result = append(result, child.Name()+" - "+child.Short)
+			result = append(result, child.CommandPath()+" - "+child.Short)
 		}
 		yamlDoc.SeeAlso = result
 	}
diff --git a/go.mod b/go.mod
index 1d45d9f..a1309e5 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.15
 
 require (
 	github.com/cpuguy83/go-md2man/v2 v2.0.2
-	github.com/inconshreveable/mousetrap v1.0.0
+	github.com/inconshreveable/mousetrap v1.0.1
 	github.com/spf13/pflag v1.0.5
-	gopkg.in/yaml.v2 v2.4.0
+	gopkg.in/yaml.v3 v3.0.1
 )
diff --git a/go.sum b/go.sum
index 8ed2288..a8c544e 100644
--- a/go.sum
+++ b/go.sum
@@ -1,12 +1,12 @@
 github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
-github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
+github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/projects_using_cobra.md b/projects_using_cobra.md
index 9189662..b5b9dbf 100644
--- a/projects_using_cobra.md
+++ b/projects_using_cobra.md
@@ -13,7 +13,7 @@
 - [Gardener](https://github.com/gardener/gardenctl)
 - [Giant Swarm's gsctl](https://github.com/giantswarm/gsctl)
 - [Git Bump](https://github.com/erdaltsksn/git-bump)
-- [Github CLI](https://github.com/cli/cli)
+- [GitHub CLI](https://github.com/cli/cli)
 - [GitHub Labeler](https://github.com/erdaltsksn/gh-label)
 - [Golangci-lint](https://golangci-lint.run)
 - [GopherJS](https://github.com/gopherjs/gopherjs)
@@ -36,6 +36,7 @@
 - [Multi-gitter](https://github.com/lindell/multi-gitter)
 - [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
 - [nFPM](https://nfpm.goreleaser.com)
+- [Okteto](https://github.com/okteto/okteto)
 - [OpenShift](https://www.openshift.com/)
 - [Ory Hydra](https://github.com/ory/hydra)
 - [Ory Kratos](https://github.com/ory/kratos)
@@ -55,3 +56,4 @@
 - [UpCloud CLI (`upctl`)](https://github.com/UpCloudLtd/upcloud-cli)
 - VMware's [Tanzu Community Edition](https://github.com/vmware-tanzu/community-edition) & [Tanzu Framework](https://github.com/vmware-tanzu/tanzu-framework)
 - [Werf](https://werf.io/)
+- [ZITADEL](https://github.com/zitadel/zitadel)


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 0ca8367..e0c2f15 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -15,7 +15,8 @@ jobs:
 
       - uses: actions/setup-go@v3
         with:
-          go-version: '1.17'
+          go-version: '^1.19'
+          check-latest: true
 
       - uses: actions/checkout@v3
 
@@ -37,6 +38,7 @@ jobs:
         - 16
         - 17
         - 18
+        - 19
     name: '${{ matrix.platform }} | 1.${{ matrix.go }}.x'
     runs-on: ${{ matrix.platform }}-latest
     steps:
@@ -56,8 +58,8 @@ jobs:
     - run: |
         export GOBIN=$HOME/go/bin
         case "${{ matrix.go }}" in
-          16|17|18) _version='@latest';;
-          *) _version='';;
+          14|15) _version='';;
+          *) _version='@latest';;
         esac
         go install github.com/kyoh86/richgo"${_version}"
         go install github.com/mitchellh/gox"${_version}"
diff --git a/command_test.go b/command_test.go
index 0446e3c..0b0b821 100644
--- a/command_test.go
+++ b/command_test.go
@@ -707,10 +707,7 @@ func TestEmptyInputs(t *testing.T) {
 	}
 }
 
-func TestOverwrittenFlag(t *testing.T) {
-	// TODO: This test fails, but should work.
-	t.Skip()
-
+func TestChildFlagShadowsParentPersistentFlag(t *testing.T) {
 	parent := &Command{Use: "parent", Run: emptyRun}
 	child := &Command{Use: "child", Run: emptyRun}
 
@@ -732,7 +729,7 @@ func TestOverwrittenFlag(t *testing.T) {
 	}
 
 	if childInherited.Lookup("intf") != nil {
-		t.Errorf(`InheritedFlags should not contain overwritten flag "intf"`)
+		t.Errorf(`InheritedFlags should not contain shadowed flag "intf"`)
 	}
 	if childLocal.Lookup("intf") == nil {
 		t.Error(`LocalFlags expected to contain "intf", got "nil"`)
@@ -887,6 +884,38 @@ func TestHelpCommandExecutedOnChild(t *testing.T) {
 	checkStringContains(t, output, childCmd.Long)
 }
 
+func TestHelpCommandExecutedOnChildWithFlagThatShadowsParentFlag(t *testing.T) {
+	parent := &Command{Use: "parent", Run: emptyRun}
+	child := &Command{Use: "child", Run: emptyRun}
+	parent.AddCommand(child)
+
+	parent.PersistentFlags().Bool("foo", false, "parent foo usage")
+	parent.PersistentFlags().Bool("bar", false, "parent bar usage")
+	child.Flags().Bool("foo", false, "child foo usage") // This shadows parent's foo flag
+	child.Flags().Bool("baz", false, "child baz usage")
+
+	got, err := executeCommand(parent, "help", "child")
+	if err != nil {
+		t.Errorf("Unexpected error: %v", err)
+	}
+
+	expected := `Usage:
+  parent child [flags]
+
+Flags:
+      --baz    child baz usage
+      --foo    child foo usage
+  -h, --help   help for child
+
+Global Flags:
+      --bar   parent bar usage
+`
+
+	if got != expected {
+		t.Errorf("Help text mismatch.\nExpected:\n%s\n\nGot:\n%s\n", expected, got)
+	}
+}
+
 func TestSetHelpCommand(t *testing.T) {
 	c := &Command{Use: "c", Run: emptyRun}
 	c.AddCommand(&Command{Use: "empty", Run: emptyRun})
diff --git a/doc/yaml_docs_test.go b/doc/yaml_docs_test.go
index d08fa4f..9bf5aa6 100644
--- a/doc/yaml_docs_test.go
+++ b/doc/yaml_docs_test.go
@@ -2,6 +2,7 @@ package doc
 
 import (
 	"bytes"
+	"fmt"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -24,6 +25,7 @@ func TestGenYamlDoc(t *testing.T) {
 	checkStringContains(t, output, "rootflag")
 	checkStringContains(t, output, rootCmd.Short)
 	checkStringContains(t, output, echoSubCmd.Short)
+	checkStringContains(t, output, fmt.Sprintf("- %s - %s", echoSubCmd.CommandPath(), echoSubCmd.Short))
 }
 
 func TestGenYamlNoTag(t *testing.T) {