diff --git a/pkg/cmd/extension/command.go b/pkg/cmd/extension/command.go index 7f2ec0ac1..874eb818b 100644 --- a/pkg/cmd/extension/command.go +++ b/pkg/cmd/extension/command.go @@ -340,9 +340,11 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { } err = m.InstallLocal(wd) - if errors.Is(err, ErrExtensionExecutableNotFound) { + var ErrExtensionExecutableNotFound *ErrExtensionExecutableNotFound + if errors.As(err, &ErrExtensionExecutableNotFound) { + cs := io.ColorScheme() if io.IsStdoutTTY() { - fmt.Fprintln(io.ErrOut, err.Error()) + fmt.Fprintf(io.ErrOut, "%s %s", cs.WarningIcon(), ErrExtensionExecutableNotFound.Error()) } return nil } diff --git a/pkg/cmd/extension/command_test.go b/pkg/cmd/extension/command_test.go index dccd487ea..696f247ae 100644 --- a/pkg/cmd/extension/command_test.go +++ b/pkg/cmd/extension/command_test.go @@ -287,27 +287,38 @@ func TestNewCmdExtension(t *testing.T) { }, }, { - name: "install local extension without executable TTY", + name: "installing local extension without executable with TTY shows warning", args: []string{"install", "."}, managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) { em.InstallLocalFunc = func(dir string) error { - return ErrExtensionExecutableNotFound + return &ErrExtensionExecutableNotFound{ + Dir: tempDir, + Name: "gh-test", + } } em.ListFunc = func() []extensions.Extension { return []extensions.Extension{} } return nil }, - wantStderr: fmt.Sprintln(ErrExtensionExecutableNotFound.Error()), - wantErr: false, - isTTY: true, + wantStderr: fmt.Sprintf( + "! %s", + (&ErrExtensionExecutableNotFound{ + Dir: tempDir, + Name: "gh-test", + }).Error()), + wantErr: false, + isTTY: true, }, { - name: "install local extension without executable no TTY", + name: "install local extension without executable with no TTY shows no warning", args: []string{"install", "."}, managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) { em.InstallLocalFunc = func(dir string) error { - return ErrExtensionExecutableNotFound + return &ErrExtensionExecutableNotFound{ + Dir: tempDir, + Name: "gh-test", + } } em.ListFunc = func() []extensions.Extension { return []extensions.Extension{} diff --git a/pkg/cmd/extension/manager.go b/pkg/cmd/extension/manager.go index 0dd24f5c8..db4bac84e 100644 --- a/pkg/cmd/extension/manager.go +++ b/pkg/cmd/extension/manager.go @@ -28,7 +28,15 @@ import ( // ErrInitialCommitFailed indicates the initial commit when making a new extension failed. var ErrInitialCommitFailed = errors.New("initial commit failed") -var ErrExtensionExecutableNotFound = errors.New("an extension has been installed but there is no executable") + +type ErrExtensionExecutableNotFound struct { + Dir string + Name string +} + +func (e *ErrExtensionExecutableNotFound) Error() string { + return fmt.Sprintf("an extension has been installed but there is no executable: executable file named \"%s\" in %s is required to run the extension after install. Perhaps you need to build it?\n", e.Name, e.Dir) +} const darwinAmd64 = "darwin-amd64" @@ -195,7 +203,6 @@ func (m *Manager) populateLatestVersions(exts []*Extension) { func (m *Manager) InstallLocal(dir string) error { name := filepath.Base(dir) targetLink := filepath.Join(m.installDir(), name) - cs := m.io.ColorScheme() if err := os.MkdirAll(filepath.Dir(targetLink), 0755); err != nil { return err @@ -209,8 +216,10 @@ func (m *Manager) InstallLocal(dir string) error { // it does indicate that the user will not be able to run the extension until // the executable file is built or created manually somehow. if _, err := os.Stat(filepath.Join(dir, name)); os.IsNotExist(err) { - errMsg := fmt.Errorf("%v %w: executable file named \"%s\" in %s is required to run the extension after install. Perhaps you need to build it?", cs.WarningIcon(), ErrExtensionExecutableNotFound, name, dir) - return errMsg + return &ErrExtensionExecutableNotFound{ + Dir: dir, + Name: name, + } } return nil } diff --git a/pkg/cmd/extension/manager_test.go b/pkg/cmd/extension/manager_test.go index 912a55f08..025d6e125 100644 --- a/pkg/cmd/extension/manager_test.go +++ b/pkg/cmd/extension/manager_test.go @@ -771,7 +771,7 @@ func TestManager_Install_local_no_executable_found(t *testing.T) { // to simulate an attempt to install a local extension without an executable err := m.InstallLocal(localDir) - require.ErrorIs(t, err, ErrExtensionExecutableNotFound) + require.ErrorAs(t, err, new(*ErrExtensionExecutableNotFound)) assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) }