Repository: docker/compose-cli
Pull request #699 (2020-09-30 08:56:16)

Do not fail when constructing error message for commands not implemented, if command flags are not recognized.
Signed-off-by: Guillaume Tardif <guillaume.tardif@docker.com>

**What I did**
* Use metrics GetCommand() that is already used 3 lines above.
* added e2e local test and unit test for this specific case in metrics.GetCommand() (that already worked as expected)

**Related issue**

<!-- optional tests
You can add a / mention to run tests executed by default only on main branch : 
* `test-aci` to run ACI E2E tests
* `test-ecs` to run ECS E2E tests
* `test-windows` to run tests & E2E tests on windows
-->

**(not mandatory) A picture of a cute animal, if possible in relation with what you did**
![](https://zenitube.com/img/posts/2016/0003animal-photoshop/13-hippo-frog.jpg)


Patch:
diff --git a/cli/main.go b/cli/main.go
index 54b0df55..9ea9404f 100644
--- a/cli/main.go
+++ b/cli/main.go
@@ -224,13 +224,9 @@ func exit(root *cobra.Command, ctx string, err error, ctype string) {
 		os.Exit(errdefs.ExitCodeLoginRequired)
 	}
 	if errors.Is(err, errdefs.ErrNotImplemented) {
-		cmd, _, _ := root.Traverse(os.Args[1:])
-		name := cmd.Name()
-		parent := cmd.Parent()
-		if parent != nil && parent.Parent() != nil {
-			name = parent.Name() + " " + name
-		}
+		name := metrics.GetCommand(os.Args[1:], root.PersistentFlags())
 		fmt.Fprintf(os.Stderr, "Command %q not available in current context (%s)\n", name, ctx)
+
 		os.Exit(1)
 	}
 
diff --git a/metrics/metrics.go b/metrics/metrics.go
index 7de8a2bb..05892cd4 100644
--- a/metrics/metrics.go
+++ b/metrics/metrics.go
@@ -78,7 +78,7 @@ const (
 
 // Track sends the tracking analytics to Docker Desktop
 func Track(context string, args []string, flags *flag.FlagSet, status string) {
-	command := getCommand(args, flags)
+	command := GetCommand(args, flags)
 	if command != "" {
 		c := NewClient()
 		c.Send(Command{
@@ -90,7 +90,8 @@ func Track(context string, args []string, flags *flag.FlagSet, status string) {
 	}
 }
 
-func getCommand(args []string, flags *flag.FlagSet) string {
+// GetCommand get the invoked command
+func GetCommand(args []string, flags *flag.FlagSet) string {
 	command := ""
 	strippedArgs := stripFlags(args, flags)
 


Test patch:
diff --git a/metrics/metrics_test.go b/metrics/metrics_test.go
index d2fbc236..cb79f9a5 100644
--- a/metrics/metrics_test.go
+++ b/metrics/metrics_test.go
@@ -25,7 +25,7 @@ import (
 
 func TestFlag(t *testing.T) {
 	root := &cobra.Command{}
-	root.PersistentFlags().BoolP("debug", "d", false, "debug")
+	root.PersistentFlags().BoolP("debug", "D", false, "debug")
 	root.PersistentFlags().String("str", "str", "str")
 
 	testCases := []struct {
@@ -40,7 +40,7 @@ func TestFlag(t *testing.T) {
 		},
 		{
 			name:     "with short flags",
-			args:     []string{"-d", "run"},
+			args:     []string{"-D", "run"},
 			expected: "run",
 		},
 		{
@@ -133,11 +133,26 @@ func TestFlag(t *testing.T) {
 			args:     []string{"create", "--rm", "test"},
 			expected: "create",
 		},
+		{
+			name:     "compose up -f xxx",
+			args:     []string{"compose", "up", "-f", "titi.yaml"},
+			expected: "compose up",
+		},
+		{
+			name:     "compose -f xxx up",
+			args:     []string{"compose", "-f", "titi.yaml", "up"},
+			expected: "compose up",
+		},
+		{
+			name:     "-D compose -f xxx up",
+			args:     []string{"--debug", "compose", "-f", "titi.yaml", "up"},
+			expected: "compose up",
+		},
 	}
 
 	for _, testCase := range testCases {
 		t.Run(testCase.name, func(t *testing.T) {
-			result := getCommand(testCase.args, root.PersistentFlags())
+			result := GetCommand(testCase.args, root.PersistentFlags())
 			assert.Equal(t, testCase.expected, result)
 		})
 	}
@@ -210,7 +225,7 @@ func TestEcs(t *testing.T) {
 
 	for _, testCase := range testCases {
 		t.Run(testCase.name, func(t *testing.T) {
-			result := getCommand(testCase.args, root.PersistentFlags())
+			result := GetCommand(testCase.args, root.PersistentFlags())
 			assert.Equal(t, testCase.expected, result)
 		})
 	}
@@ -258,7 +273,7 @@ func TestScan(t *testing.T) {
 
 	for _, testCase := range testCases {
 		t.Run(testCase.name, func(t *testing.T) {
-			result := getCommand(testCase.args, root.PersistentFlags())
+			result := GetCommand(testCase.args, root.PersistentFlags())
 			assert.Equal(t, testCase.expected, result)
 		})
 	}
diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go
index 7675c07f..4b33c8e8 100644
--- a/tests/e2e/e2e_test.go
+++ b/tests/e2e/e2e_test.go
@@ -56,6 +56,12 @@ func TestComposeNotImplemented(t *testing.T) {
 		ExitCode: 1,
 		Err:      `Command "compose up" not available in current context (default)`,
 	})
+
+	res = c.RunDockerOrExitError("compose", "-f", "titi.yaml", "up")
+	res.Assert(t, icmd.Expected{
+		ExitCode: 1,
+		Err:      `Command "compose up" not available in current context (default)`,
+	})
 }
 
 func TestContextDefault(t *testing.T) {