GitRoot
craft your forge, build your project, grow your community freely
1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
2//
3// SPDX-License-Identifier: EUPL-1.2
4
5package plugin
6
7import (
8 "context"
9 "errors"
10 "os"
11
12 "github.com/go-git/go-git/v5/plumbing/object"
13 "github.com/samber/oops"
14 "gitroot.dev/server/logger"
15)
16
17func (pm *Manager) reloadPlugins() {
18 pm.pluginsLock.Lock()
19 pm.plugins = nil
20 pm.pluginsLock.Unlock()
21}
22
23func (pm *Manager) Availables(ctx context.Context) ([]Plugin, error) {
24 pm.pluginsLock.RLock()
25 needLoad := pm.plugins == nil
26 pm.pluginsLock.RUnlock()
27 if needLoad {
28 errorHandler := oops.With("rootData", pm.conf.PathDataPlugin())
29 forgeRepo, err := pm.repoManager.OpenForgeRepo(logger.AddCaller(ctx, "plugin.Availables"))
30 defer func() {
31 if err := forgeRepo.Close(); err != nil {
32 pm.logger.Error("forgeRepo.Close", err)
33 }
34 }()
35 if err != nil {
36 return nil, errorHandler.Wrapf(err, "can't open forgeRepo")
37 }
38 filecontent, err := forgeRepo.ContentPluginsConf()
39 if errors.Is(err, object.ErrFileNotFound) {
40 return []Plugin{}, nil
41 } else if err != nil {
42 return nil, oops.Wrapf(err, "can't read plugins filecontent from repo")
43 }
44 ps, err := ParsePlugins(filecontent, false)
45 if err != nil {
46 return nil, oops.Wrapf(err, "can't parse plugins from repo")
47 }
48 pm.pluginsLock.Lock()
49 pm.plugins = make([]Plugin, len(ps))
50 //todo can be parallelized and compiled to wazero module
51 for i, cp := range ps {
52 content, err := os.ReadFile(pm.PathWasm(cp))
53 if err != nil {
54 return nil, errorHandler.With("filename", cp.Name).Wrapf(err, "can't read plugin")
55 }
56 if cp.Name == "" {
57 cp = cp.DetermineNameAndVersionFromUrl()
58 }
59 if len(cp.Run) == 0 {
60 conf, err := pm.runtimes.Conf(ctx, Plugin{Name: cp.Name, Version: cp.Version, content: content})
61 if err != nil {
62 pm.logger.Error("can't get default conf", err, logger.NewLoggerPair("filename", cp.Name))
63 }
64 run, err := pluginLibToPlugin(conf)
65 if err != nil {
66 pm.logger.Error("can't pluginLibToPlugin", err, logger.NewLoggerPair("filename", cp.Name))
67 } else {
68 cp.Run = run
69 }
70 }
71 commiter, err := pm.userManager.NewCommiter(cp.Name)
72 if err != nil {
73 pm.logger.Error("NewCommiter", err, logger.NewLoggerPair("pluginName", cp.Name))
74 }
75
76 pm.plugins[i] = Plugin{
77 Url: cp.Url,
78 Crc: cp.Crc,
79 Active: cp.Active,
80 Name: cp.Name,
81 Version: cp.Version,
82 Run: cp.Run,
83 content: content,
84 commiter: commiter,
85 }
86 pm.logger.Info("available plugin", logger.NewLoggerPair("name", cp.Name))
87 }
88 pm.pluginsLock.Unlock()
89 }
90 pm.pluginsLock.RLock()
91 defer pm.pluginsLock.RUnlock()
92 if len(pm.plugins) == 0 {
93 pm.logger.Info("no available plugin", logger.NewLoggerPair("in dir", pm.conf.PathDataPlugin()))
94 }
95 return pm.plugins, nil
96}
97
98func (pm *Manager) usable(ctx context.Context, repoName string) ([]Plugin, error) {
99 repo, err := pm.repoManager.Open(logger.AddCaller(ctx, "plugin.usable"), repoName)
100 if err != nil {
101 return nil, oops.Wrapf(err, "can't open repo")
102 }
103 defer repo.Close()
104 filecontent, err := repo.ContentPluginsConf()
105 if err != nil {
106 return nil, oops.Wrapf(err, "can't read plugins from repo")
107 }
108 confPlugins, err := ParsePlugins(filecontent, true)
109 if err != nil {
110 return nil, oops.Wrapf(err, "can't parse plugins from repo")
111 }
112 if len(confPlugins) == 0 {
113 pm.logger.Debug("no usable plugin in conf")
114 }
115 plugins, err := pm.Availables(ctx)
116 if err != nil {
117 return nil, oops.Wrapf(err, "can't get availables plugin from forgerepo")
118 }
119 usablePlugins := make([]Plugin, 0)
120 for _, p := range plugins {
121 for _, cp := range confPlugins {
122 if p.Name == cp.Name {
123 if cp.Active {
124 goodP := p.OverrideWith(cp).SetActive(cp.Active).SetRun(cp.Run)
125 usablePlugins = append(usablePlugins, goodP)
126 pm.logger.Info("usable plugin", logger.NewLoggerPair("name", cp.Name))
127 }
128 break
129 }
130 }
131 }
132 return usablePlugins, nil
133}