Warn when installing local ext with no executable

This commit is contained in:
bagtoad 2024-11-17 16:44:08 -07:00
parent 9decf1b526
commit b575fe8ebc
2 changed files with 72 additions and 1 deletions

View file

@ -28,6 +28,7 @@ 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")
const darwinAmd64 = "darwin-amd64"
@ -194,10 +195,24 @@ 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
}
return makeSymlink(dir, targetLink)
if err := makeSymlink(dir, targetLink); err != nil {
return err
}
// Check if an executable of the same name exists in the target directory.
// An error here doesn't indicate a failed extension installation, but
// 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)); err != nil {
errMsg := fmt.Errorf("%v %w: expected executable file named \"%s\" in %s, perhaps you need to build it?", cs.WarningIcon(), ErrExtensionExecutableNotFound, name, dir)
return errMsg
}
return nil
}
type binManifest struct {

View file

@ -719,6 +719,62 @@ func TestManager_UpgradeExtension_GitExtension_Pinned(t *testing.T) {
gcOne.AssertExpectations(t)
}
func TestManager_Install_local(t *testing.T) {
extManagerDir := t.TempDir()
ios, _, stdout, stderr := iostreams.Test()
m := newTestManager(extManagerDir, nil, nil, ios)
fakeExtensionName := "local-ext"
// Create a temporary directory to simulate the local extension repo
extensionLocalPath := filepath.Join(extManagerDir, fakeExtensionName)
require.NoError(t, os.MkdirAll(extensionLocalPath, 0755))
// Create a fake executable in the local extension directory
fakeExtensionExecutablePath := filepath.Join(extensionLocalPath, fakeExtensionName)
require.NoError(t, stubExtension(fakeExtensionExecutablePath))
err := m.InstallLocal(extensionLocalPath)
require.NoError(t, err)
// This is the path to a file:
// on windows this is a file whose contents is a string describing the path to the local extension dir.
// on other platforms this file is a real symlink to the local extension dir.
extensionLinkFile := filepath.Join(extManagerDir, "extensions", fakeExtensionName)
if runtime.GOOS == "windows" {
// We don't create symlinks on Windows, so check if we made a file
// with the correct contents
b, err := os.ReadFile(extensionLinkFile)
require.NoError(t, err)
assert.Equal(t, extensionLocalPath, string(b))
} else {
// Verify the created symlink points to the correct directory
linkTarget, err := os.Readlink(extensionLinkFile)
require.NoError(t, err)
assert.Equal(t, extensionLocalPath, linkTarget)
}
assert.Equal(t, "", stdout.String())
assert.Equal(t, "", stderr.String())
}
func TestManager_Install_local_no_executable_found(t *testing.T) {
tempDir := t.TempDir()
ios, _, stdout, _ := iostreams.Test()
m := newTestManager(tempDir, nil, nil, ios)
fakeExtensionName := "local-ext"
// Create a temporary directory to simulate the local extension repo
localDir := filepath.Join(tempDir, fakeExtensionName)
require.NoError(t, os.MkdirAll(localDir, 0755))
// Intentionally not creating an executable in the local extension repo
// to simulate an attempt to install a local extension without an executable
err := m.InstallLocal(localDir)
require.ErrorIs(t, err, ErrExtensionExecutableNotFound)
assert.Equal(t, "", stdout.String())
}
func TestManager_Install_git(t *testing.T) {
tempDir := t.TempDir()