Repository: urfave/cli
Pull request #1457 (2022-08-18 01:22:05)

Fix:(issue_1094) Dont execute Before/After handlers during shell comp…
…letion

<!--
  This template provides some ideas of things to include in your PR description.
  To start, try providing a short summary of your changes in the Title above.
  If a section of the PR template does not apply to this PR, then delete that section.
 -->

## What type of PR is this?

_(REQUIRED)_

<!--
  Delete any of the following that do not apply:
 -->

- bug

## What this PR does / why we need it:

_(REQUIRED)_

<!--
  What goal is this change working towards?
  Provide a bullet pointed summary of how each file was changed.
  Briefly explain any decisions you made with respect to the changes.
  Include anything here that you didn't include in *Release Notes*
  above, such as changes to CI or changes to internal methods.
-->

Updated app.go  to check shell complete before calling before/after handlers. Appropriate test was added in app_test.go

## Which issue(s) this PR fixes:

_(REQUIRED)_

<!--
If this PR fixes one of more issues, list them here.
One line each, like so:

Fixes #1094 
-->

## Special notes for your reviewer:

_(fill-in or delete this section)_

<!--
   Is there any particular feedback you would / wouldn't like?
   Which parts of the code should reviewers focus on?
-->

## Testing

_(fill-in or delete this section)_

<!--
  Describe how you tested this change.
-->

go test -run=TestApp_BeforeAfterFuncShellCompletion

## Release Notes

_(REQUIRED)_
<!--
  If this PR makes user facing changes, please describe them here. This
  description will be copied into the release notes/changelog, whenever the
  next version is released. Keep this section short, and focus on high level
  changes.

  Put your text between the block. To omit notes, use NONE within the block.
-->

```release-note

```



Patch:
diff --git a/app.go b/app.go
index 0b3f45c..b39c8b8 100644
--- a/app.go
+++ b/app.go
@@ -304,7 +304,7 @@ func (a *App) RunContext(ctx context.Context, arguments []string) (err error) {
 		return err
 	}
 
-	if a.After != nil {
+	if a.After != nil && !cCtx.shellComplete {
 		defer func() {
 			if afterErr := a.After(cCtx); afterErr != nil {
 				if err != nil {
@@ -332,7 +332,7 @@ func (a *App) RunContext(ctx context.Context, arguments []string) (err error) {
 		return cerr
 	}
 
-	if a.Before != nil {
+	if a.Before != nil && !cCtx.shellComplete {
 		beforeErr := a.Before(cCtx)
 		if beforeErr != nil {
 			a.handleExitCoder(cCtx, beforeErr)
@@ -499,7 +499,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
 		return cerr
 	}
 
-	if a.After != nil {
+	if a.After != nil && !cCtx.shellComplete {
 		defer func() {
 			afterErr := a.After(cCtx)
 			if afterErr != nil {
@@ -513,7 +513,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
 		}()
 	}
 
-	if a.Before != nil {
+	if a.Before != nil && !cCtx.shellComplete {
 		beforeErr := a.Before(cCtx)
 		if beforeErr != nil {
 			a.handleExitCoder(cCtx, beforeErr)


Test patch:
diff --git a/app_test.go b/app_test.go
index cc77ce3..64316fc 100644
--- a/app_test.go
+++ b/app_test.go
@@ -1245,6 +1245,58 @@ func TestApp_BeforeFunc(t *testing.T) {
 	}
 }
 
+func TestApp_BeforeAfterFuncShellCompletion(t *testing.T) {
+	counts := &opCounts{}
+	var err error
+
+	app := &App{
+		EnableBashCompletion: true,
+		Before: func(c *Context) error {
+			counts.Total++
+			counts.Before = counts.Total
+			return nil
+		},
+		After: func(c *Context) error {
+			counts.Total++
+			counts.After = counts.Total
+			return nil
+		},
+		Commands: []*Command{
+			{
+				Name: "sub",
+				Action: func(c *Context) error {
+					counts.Total++
+					counts.SubCommand = counts.Total
+					return nil
+				},
+			},
+		},
+		Flags: []Flag{
+			&StringFlag{Name: "opt"},
+		},
+		Writer: ioutil.Discard,
+	}
+
+	// run with the Before() func succeeding
+	err = app.Run([]string{"command", "--opt", "succeed", "sub", "--generate-bash-completion"})
+
+	if err != nil {
+		t.Fatalf("Run error: %s", err)
+	}
+
+	if counts.Before != 0 {
+		t.Errorf("Before() executed when not expected")
+	}
+
+	if counts.After != 0 {
+		t.Errorf("After() executed when not expected")
+	}
+
+	if counts.SubCommand != 0 {
+		t.Errorf("Subcommand executed more than expected")
+	}
+}
+
 func TestApp_AfterFunc(t *testing.T) {
 	counts := &opCounts{}
 	afterError := fmt.Errorf("fail")