func (b *BasicPluginManager) GetPathForPlugin(ctx context.Context, path string, version string) (local string, err error) {
	return PathForPlugin(b.storageDir, path, version)
}
GetPathForPlugin is used to get path for plugin executable file
package pluginmanager
import (
	"context"
	"errors"
	"io/fs"
	"os"
	"strings"
	"sync"
	"github.com/storyicon/powerproto/pkg/consts"
	"github.com/storyicon/powerproto/pkg/util"
	"github.com/storyicon/powerproto/pkg/util/logger"
)
type PluginManager interface {
	GetPluginLatestVersion(ctx context.Context, path string) (string, error)
	ListPluginVersions(ctx context.Context, path string) ([]string, error)
	IsPluginInstalled(ctx context.Context, path string, version string) (bool, string, error)
	InstallPlugin(ctx context.Context, path string, version string) (local string, err error)
	GetPathForPlugin(ctx context.Context, path string, version string) (local string, err error)
	GetGitRepoLatestVersion(ctx context.Context, uri string) (string, error)
	InstallGitRepo(ctx context.Context, uri string, commitId string) (local string, err error)
	IsGitRepoInstalled(ctx context.Context, uri string, commitId string) (bool, string, error)
	GitRepoPath(ctx context.Context, commitId string) (string, error)
	GetProtocLatestVersion(ctx context.Context) (string, error)
	ListProtocVersions(ctx context.Context) ([]string, error)
	IsProtocInstalled(ctx context.Context, version string) (bool, string, error)
	InstallProtoc(ctx context.Context, version string) (local string, err error)
	IncludePath(ctx context.Context) (string, error)
	GetPathForProtoc(ctx context.Context, version string) (string, error)
}
type Config struct {
	StorageDir string `json:"storage"`
}
func NewConfig() *Config {
	return &Config{
		StorageDir: consts.GetHomeDir(),
	}
}
func NewPluginManager(cfg *Config, log logger.Logger) (PluginManager, error) {
	return NewBasicPluginManager(cfg.StorageDir, log)
}
type BasicPluginManager struct {
	logger.Logger
	storageDir   string
	versions     map[string][]string
	versionsLock sync.RWMutex
}
func NewBasicPluginManager(storageDir string, log logger.Logger) (*BasicPluginManager, error) {
	return &BasicPluginManager{
		Logger:     log.NewLogger("pluginmanager"),
		storageDir: storageDir,
		versions:   map[string][]string{},
	}, nil
}
func (b *BasicPluginManager) GetPluginLatestVersion(ctx context.Context, path string) (string, error) {
	ctx, cancel := consts.GetContextWithPerCommandTimeout(ctx)
	defer cancel()
	versions, err := b.ListPluginVersions(ctx, path)
	if err != nil {
		return "", err
	}
	if len(versions) == 0 {
		return "", errors.New("no version list")
	}
	return versions[len(versions)-1], nil
}
func (b *BasicPluginManager) ListPluginVersions(ctx context.Context, path string) ([]string, error) {
	ctx, cancel := consts.GetContextWithPerCommandTimeout(ctx)
	defer cancel()
	b.versionsLock.RLock()
	versions, ok := b.versions[path]
	b.versionsLock.RUnlock()
	if ok {
		return versions, nil
	}
	versions, err := ListsGoPackageVersionsAmbiguously(ctx, b.Logger, path)
	if err != nil {
		return nil, err
	}
	b.versionsLock.Lock()
	b.versions[path] = versions
	b.versionsLock.Unlock()
	return versions, nil
}
func (b *BasicPluginManager) IsPluginInstalled(ctx context.Context, path string, version string) (bool, string, error) {
	return IsPluginInstalled(ctx, b.storageDir, path, version)
}