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: MIT
  4
  5package gitroot
  6
  7// #include <stdlib.h>
  8import "C"
  9
 10import (
 11	"encoding/json"
 12	"errors"
 13	"io/fs"
 14	"os"
 15	"runtime"
 16
 17	"github.com/tidwall/gjson"
 18	"gitroot.dev/libs/golang/plugin/model"
 19)
 20
 21type PluginFactory = func(server model.Server) model.Plugin
 22
 23type pServer struct {
 24	plugin           model.Plugin
 25	run              []model.PluginRun
 26	atLeastOneChange bool
 27}
 28
 29var server = &pServer{
 30	atLeastOneChange: false,
 31}
 32
 33func Register(run []model.PluginRun, p PluginFactory) {
 34	server.run = run
 35	server.plugin = p(server)
 36}
 37
 38func (s *pServer) ForgeConf() (model.ForgeConf, error) {
 39	forgeConf := model.ForgeConf{}
 40	ptrSize := _forgeConf()
 41	if ptrSize == 0 {
 42		return forgeConf, errors.New("can't make diff")
 43	}
 44	ptrDiff := uint32(ptrSize >> 32)
 45	sizeDiff := uint32(ptrSize)
 46	forgeConfJson := gjson.Parse(ptrToString(ptrDiff, sizeDiff))
 47	return model.ForgeConf{
 48		Domain:           forgeConfJson.Get("domain").String(),
 49		ExternalSshAddr:  forgeConfJson.Get("externalSshAddr").String(),
 50		ExternalHttpAddr: forgeConfJson.Get("externalHttpAddr").String(),
 51	}, nil
 52}
 53
 54func (s *pServer) Worktree() fs.FS {
 55	return os.DirFS("/worktree")
 56}
 57
 58func (s *pServer) Webcontent() fs.FS {
 59	return os.DirFS("/webcontent")
 60}
 61
 62func (s *pServer) Cache() fs.FS {
 63	return os.DirFS("/cache")
 64}
 65
 66func (s *pServer) ModifyContent(filepath, content string) {
 67	s.atLeastOneChange = true
 68	ptr, size := stringToPtr(filepath)
 69	ptr2, size2 := stringToPtr(content)
 70	_modifyContent(ptr, size, ptr2, size2)
 71	runtime.KeepAlive(filepath)
 72	runtime.KeepAlive(content)
 73}
 74
 75func (s *pServer) ModifyWebContent(filepath, content string) {
 76	ptr, size := stringToPtr(filepath)
 77	ptr2, size2 := stringToPtr(content)
 78	_modifyWebContent(ptr, size, ptr2, size2)
 79	runtime.KeepAlive(filepath)
 80	runtime.KeepAlive(content)
 81}
 82
 83func (s *pServer) ReplaceWebContent(filepath, oldContent, content string) {
 84	ptr, size := stringToPtr(filepath)
 85	ptr2, size2 := stringToPtr(oldContent)
 86	ptr3, size3 := stringToPtr(content)
 87	_replaceWebContent(ptr, size, ptr2, size2, ptr3, size3)
 88	runtime.KeepAlive(filepath)
 89	runtime.KeepAlive(oldContent)
 90	runtime.KeepAlive(content)
 91}
 92
 93func (s *pServer) ModifyCacheContent(filepath, content string) {
 94	ptr, size := stringToPtr(filepath)
 95	ptr2, size2 := stringToPtr(content)
 96	_modifyCacheContent(ptr, size, ptr2, size2)
 97	runtime.KeepAlive(filepath)
 98	runtime.KeepAlive(content)
 99}
100
101func (s *pServer) CommitAllIfNeeded(message string) {
102	if s.atLeastOneChange {
103		ptr, size := stringToPtr(message)
104		_commitAll(ptr, size)
105		runtime.KeepAlive(message)
106	}
107}
108
109func (s *pServer) DiffWithParent(hash string, oldFilepath string, newFilePath string) (string, error) {
110	ptrHash, sizeHash := stringToPtr(hash)
111	ptrOldFile, sizeOldFile := stringToPtr(oldFilepath)
112	ptrNewFile, sizeNewFile := stringToPtr(newFilePath)
113	ptrSizeDiff := _diffWithParent(ptrHash, sizeHash, ptrOldFile, sizeOldFile, ptrNewFile, sizeNewFile)
114	if ptrSizeDiff == 0 {
115		return "", errors.New("can't make diff")
116	}
117	ptrDiff := uint32(ptrSizeDiff >> 32)
118	sizeDiff := uint32(ptrSizeDiff)
119	return ptrToString(ptrDiff, sizeDiff), nil
120}
121
122func (s *pServer) Log(message string) {
123	ptr, size := stringToPtr(message)
124	_log(ptr, size)
125	runtime.KeepAlive(message)
126}
127
128func (s *pServer) LogError(message string, err error) {
129	ptr, size := stringToPtr(message)
130	errPtr, errSize := stringToPtr(err.Error())
131	_logError(ptr, size, errPtr, errSize)
132	runtime.KeepAlive(message)
133	runtime.KeepAlive(err)
134}
135
136func (s *pServer) Merge(from string, to string) {
137	fromPtr, fromSize := stringToPtr(from)
138	toPtr, toSize := stringToPtr(to)
139	_merge(fromPtr, fromSize, toPtr, toSize)
140	runtime.KeepAlive(from)
141	runtime.KeepAlive(to)
142}
143
144func (s *pServer) Commits(from string, to string) ([]model.Commit, error) {
145	fromPtr, fromSize := stringToPtr(from)
146	toPtr, toSize := stringToPtr(to)
147	ptrSizeDiff := _commits(fromPtr, fromSize, toPtr, toSize)
148	runtime.KeepAlive(from)
149	runtime.KeepAlive(to)
150	if ptrSizeDiff == 0 {
151		return nil, errors.New("can't get commits")
152	}
153	ptrDiff := uint32(ptrSizeDiff >> 32)
154	sizeDiff := uint32(ptrSizeDiff)
155	return model.CommitsFromString(ptrToString(ptrDiff, sizeDiff)), nil
156}
157
158func (s *pServer) Exec(exec []model.Exec) (string, error) {
159	execMarshalled, err := json.Marshal(exec)
160	if err != nil {
161		return "", err
162	}
163	ptr, size := stringToPtr(string(execMarshalled))
164	ptrSize := _exec(ptr, size)
165	if ptrSize == 0 {
166		return "", errors.New("can't exec")
167	}
168	ptrLog := uint32(ptrSize >> 32)
169	sizeLog := uint32(ptrSize)
170	return ptrToString(ptrLog, sizeLog), nil
171}