Repository: cli/cli
File: pkg/cmd/extension/manager.go (Go)

Code before:
		go func(e *Extension) {
			defer wg.Done()
			e.LatestVersion()
		}(ext)
	}
	wg.Wait()
}

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
	}
	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: 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 nil
}

type binManifest struct {
	Owner    string
	Name     string
	Host     string
	Tag      string
	IsPinned bool
	// TODO I may end up not using this; just thinking ahead to local installs
	Path string
}

// Install installs an extension from repo, and pins to commitish if provided
func (m *Manager) Install(repo ghrepo.Interface, target string) error {
	isBin, err := isBinExtension(m.client, repo)
	if err != nil {
		if errors.Is(err, releaseNotFoundErr) {
			if ok, err := repoExists(m.client, repo); err != nil {
				return err
			} else if !ok {
				return repositoryNotFoundErr
			}

Review comment (suggestion):
Maybe just return `fmt.Errorf`, since the variable is only used once, and it's not really a message, it's an error.

You could also avoid this whole wrapping business and do:

```go
type ErrExtensionExecutableNotFound struct {
 Dir string
 Name string
}
```

And either construct the error in `Error` method, or at the call site, if that's the only place it is used.

No particularly strong feelings here though, just offering an alternative idea.

Code after:

	return results, nil
}

func (m *Manager) populateLatestVersions(exts []*Extension) {
	var wg sync.WaitGroup
	for _, ext := range exts {
		wg.Add(1)
		go func(e *Extension) {
			defer wg.Done()
			e.LatestVersion()
		}(ext)
	}
	wg.Wait()
}

func (m *Manager) InstallLocal(dir string) error {
	name := filepath.Base(dir)
	targetLink := filepath.Join(m.installDir(), name)

	if err := os.MkdirAll(filepath.Dir(targetLink), 0755); err != nil {
		return err
	}
	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 {
		if os.IsNotExist(err) {
			return &ErrExtensionExecutableNotFound{
				Dir:  dir,
				Name: name,
			}
		}
		return err
	}
	return nil
}

type binManifest struct {
	Owner    string
	Name     string
	Host     string
	Tag      string
	IsPinned bool
	// TODO I may end up not using this; just thinking ahead to local installs
	Path string