/
nickolasfox
/
kek
Обзор
Документация
Войти
/
nickolasfox
/
kek
Код
Запросы
0
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
pkg/plugins/loader.go
150 строк
3 KB
Nickolas Fox
Alpha version
29 мар 2024, 20:17
29 мар 2024, 20:17
f14be9d
Код
Авторство
О чём код?
package plugins import ( "io" "os" "path" "strings" "gopkg.in/yaml.v3" "gitverse.ru/nickolasfox/kek/pkg/tools" ) const ( rootDir = "kek" pluginsDir = "plugins" manifest = "manifest.yaml" prefixLen = 4 // kek- ) var ( // ConfigDir safely returns configuration dir, if it's can not be read // regarding operating system settings `/.kek` directory will be used. ConfigDir = configDir ) // ConfigDir safely returns configuration dir, if it's can not be read // regarding operating system settings `/.kek` directory will be used. func configDir() string { dir := path.Join("/", "."+rootDir) if confDir, err := os.UserConfigDir(); err == nil { dir = path.Join(confDir, rootDir) } return dir } const ( // EnvPath reflects where applications are stored. EnvPath = "PATH" // PluginPrefix reflects which prefix is expected for plugins PluginPrefix = "kek-" ) // collectBySuffix collects applications/scripts stored in PATH directories which name // starts within PluginPrefix. func collectBySuffix() (plugins []*Plugin) { dirs := make(map[string]struct{}) rawPaths, ok := os.LookupEnv(EnvPath) // no PATH is set if !ok { return } paths := strings.Split(rawPaths, string(os.PathListSeparator)) for _, dir := range paths { // skip already traversed paths. if _, found := dirs[dir]; found { continue } entries, err := os.ReadDir(dir) if err != nil { // log -> issue while reading a dir continue } for _, entry := range entries { if strings.HasPrefix(entry.Name(), PluginPrefix) { plugins = append(plugins, rawPlugin(tools.NormPath(path.Join(dir, entry.Name())))) } } dirs[dir] = struct{}{} } return } // LoadPlugins provides loading plugin configuration for the system stored // in a user configuration directory. func LoadPlugins() (plugins []*Plugin) { dir := path.Join(ConfigDir(), pluginsDir) entries, err := os.ReadDir(dir) if err != nil { // log -> could not read plugins dir return } for _, entry := range entries { var plugin *Plugin pluginDir := path.Join(dir, entry.Name()) if !tools.IsDir(pluginDir) { // log -> trace: not dir skipping continue } plugin, err = PluginFromFile(path.Join(pluginDir, manifest)) if err != nil { // log -> trace: could not read from file continue } _ = plugin.Validate() if plugin.IsValid() { plugins = append(plugins, plugin) } } plugins = append(plugins, collectBySuffix()...) return } // PluginFromFile reads plugin configuration from a filename. func PluginFromFile(filename string) (*Plugin, error) { fd, err := os.Open(filename) if err == nil { defer tools.Close(fd) return PluginFromReader(fd) } return nil, err } // PluginFromReader reads plugin from r (io.Reader) interface. func PluginFromReader(r io.Reader) (plugin *Plugin, err error) { var contents []byte if contents, err = io.ReadAll(r); err == nil { if err = yaml.Unmarshal(contents, &plugin); err == nil { // set plugin have been loaded from manifest explicitly plugin.isManifested = true plugin.loadManifest() } } return } func rawPlugin(location string) *Plugin { return &Plugin{ Name: strings.Replace(trim(location), ".exe", "", -1), Command: []string{location}, Version: "runtime", Description: "insert here description", Completion: PluginCompletion{ Enabled: true, }, isValid: true, } } func trim(fullCommand string) string { return path.Base(strings.Replace(fullCommand, "\\", "/", -1))[prefixLen:] }