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 "fmt"
10 "io/fs"
11 "slices"
12 "strings"
13
14 "github.com/go-git/go-git/v5/plumbing"
15 pluginLib "gitroot.dev/libs/golang/plugin/model"
16 "gitroot.dev/server/logger"
17 "gitroot.dev/server/repository"
18)
19
20func (r *runtime) worktree(ctx context.Context, repo *repository.GitRootRepository, repoWriter *repository.GitRootRepositoryWrite, plugins []Plugin, cmds []CommandForDiff) error {
21 r.repo = repo
22 r.repoWriter = repoWriter
23 r.command = &cmds[len(cmds)-1] // TODO should not be last cmd see ./manager.go line 65 todo
24
25 filepaths := []string{}
26 fs.WalkDir(repoWriter.ToFs(ctx), ".", func(path string, d fs.DirEntry, err error) error {
27 if !d.IsDir() {
28 filepaths = append(filepaths, path)
29 }
30 return nil
31 })
32 commands, err := repo.GetLastCommits(filepaths)
33 if err != nil {
34 return err
35 }
36 slices.Reverse(commands)
37
38 r.commitHook = func(hash plumbing.Hash) {
39 command, err := repoWriter.GetLastCommit(hash)
40 if err != nil {
41 r.logger.Error("can't GetLastCommit", err)
42 return
43 }
44 commands = append(commands, command)
45 }
46 defer func() {
47 r.commitHook = nil
48 }()
49
50 for _, plugin := range plugins {
51 r.plugin = plugin
52 timerStop := r.logger.Time(fmt.Sprintf("Timer %s", plugin.Name))
53
54 r.logger.Debug("start plugin worktree", logger.NewLoggerPair("name", plugin.Name))
55 m, err := r.loadModule(ctx, plugin)
56 if err != nil {
57 r.logger.Error("loadModule for worktree error", err, logger.NewLoggerPair("name", plugin.Name))
58 continue
59 }
60 l := logger.NewLogger(logger.WASM)
61 l.Debug("memory before worktree", logger.NewLoggerPair("size", m.Memory().Size()), logger.NewLoggerPair("plugin", plugin.Name))
62 startCommit := m.ExportedFunction("startCommit")
63 endCommit := m.ExportedFunction("endCommit")
64 addFile := m.ExportedFunction("addFile")
65 malloc := m.ExportedFunction("malloc")
66 free := m.ExportedFunction("free")
67
68 for _, pluginRun := range plugin.Run {
69 isAuthorized := checkBranch(pluginRun, r.command.branch)
70 if !isAuthorized {
71 continue
72 }
73 r.pluginRun = pluginRun
74 if init := m.ExportedFunction("init"); init != nil {
75 arg, err := pluginRun.Marshal()
76 if err != nil {
77 r.logger.Error("can't marshall pluginRun", err, logger.NewLoggerPair("name", plugin.Name))
78 continue
79 }
80 r.logger.Debug("init plugin worktree", logger.NewLoggerPair("name", plugin.Name), logger.NewLoggerPair("arg", arg))
81 if err := writeMemoryAndCall(ctx, m, init, malloc, free, repo.Name(), "true", string(arg)); err != nil {
82 r.logger.Error("can't writeMemoryAndCall init", err, logger.NewLoggerPair("name", plugin.Name))
83 continue
84 }
85 }
86
87 if slices.Contains(pluginRun.When, pluginLib.PluginRunWhenAdd) {
88 for _, lastCommit := range commands {
89 firstCall := true
90 hasBeenCalled := false
91 com := commitToCommitForDiff(lastCommit.Commit, []commitForDiffFile{})
92 comMarshalled, err := MarshallOne(r.command.branch.Short(), com)
93 if err != nil {
94 r.logger.Error("can't MarshallOne commit", err, logger.NewLoggerPair("name", plugin.Name))
95 continue
96 }
97 for _, path := range lastCommit.Filepath {
98 if pluginRun.glob.Match(path) {
99 if startCommit != nil && firstCall {
100 firstCall = false
101 if err := writeMemoryAndCall(ctx, m, startCommit, malloc, free, comMarshalled); err != nil {
102 r.logger.Error("can't writeMemoryAndCall startCommit", err, logger.NewLoggerPair("name", plugin.Name))
103 continue
104 }
105 }
106 if addFile != nil {
107 if err := writeMemoryAndCall(ctx, m, addFile, malloc, free, strings.TrimPrefix(path, "/")); err != nil {
108 r.logger.Error("can't writeMemoryAndCall addFile", err, logger.NewLoggerPair("name", plugin.Name))
109 continue
110 }
111 hasBeenCalled = true
112 }
113 }
114 }
115 if hasBeenCalled && endCommit != nil {
116 if err := writeMemoryAndCall(ctx, m, endCommit, malloc, free, comMarshalled); err != nil {
117 r.logger.Error("can't writeMemoryAndCall endCommit", err, logger.NewLoggerPair("name", plugin.Name))
118 continue
119 }
120 }
121 }
122 }
123
124 if finish := m.ExportedFunction("finish"); finish != nil {
125 if _, err := finish.Call(ctx); err != nil {
126 r.logger.Error("can't call finish", err, logger.NewLoggerPair("name", plugin.Name))
127 continue
128 }
129 }
130 }
131
132 l.Debug("memory after worktree", logger.NewLoggerPair("size", m.Memory().Size()), logger.NewLoggerPair("plugin", plugin.Name))
133 r.logger.Debug("finish plugin conf", logger.NewLoggerPair("name", plugin.Name))
134 timerStop()
135 }
136
137 return nil
138}