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 "time"
17)
18
19type PluginFactory = func(server Server) Plugin
20
21type Commit struct {
22 Branch string
23 Hash string
24 Message string
25 Date time.Time
26 Committer string
27}
28
29type Plugin interface {
30 Init(repoName string, confHasChanged bool, serializedConf string) error
31 StartCommit(commit Commit) error
32 AddFile(path string) error
33 ModFile(fromPath string, toPath string) error
34 DelFile(path string) error
35 EndCommit(commit Commit) error
36 Finish() error
37}
38
39type Server interface {
40 Worktree() fs.FS
41 Webcontent() fs.FS
42 Cache() fs.FS
43 ModifyContent(filepath, content string)
44 ModifyWebContent(filepath, content string)
45 ModifyCacheContent(filepath, content string)
46 CommitAllIfNeeded(message string)
47 DiffWithParent(hash string, oldFilepath string, newFilepath string) (string, error)
48 Log(message string)
49 LogError(message string, err error)
50 Merge(from string, to string)
51}
52
53type pServer struct {
54 plugin Plugin
55 run string
56 atLeastOneChange bool
57}
58
59var server = &pServer{
60 atLeastOneChange: false,
61}
62
63func Register(run []PluginRun, p PluginFactory) {
64 if j, err := json.Marshal(run); err == nil {
65 server.run = string(j)
66 } else {
67 server.LogError("can't marshal conf", err)
68 }
69 server.plugin = p(server)
70}
71
72func (s *pServer) Worktree() fs.FS {
73 return os.DirFS("/worktree")
74}
75
76func (s *pServer) Webcontent() fs.FS {
77 return os.DirFS("/webcontent")
78}
79
80func (s *pServer) Cache() fs.FS {
81 return os.DirFS("/cache")
82}
83
84func (s *pServer) ModifyContent(filepath, content string) {
85 s.atLeastOneChange = true
86 ptr, size := stringToPtr(filepath)
87 ptr2, size2 := stringToPtr(content)
88 _modifyContent(ptr, size, ptr2, size2)
89 runtime.KeepAlive(filepath)
90 runtime.KeepAlive(content)
91}
92
93func (s *pServer) ModifyWebContent(filepath, content string) {
94 ptr, size := stringToPtr(filepath)
95 ptr2, size2 := stringToPtr(content)
96 _modifyWebContent(ptr, size, ptr2, size2)
97 runtime.KeepAlive(filepath)
98 runtime.KeepAlive(content)
99}
100
101func (s *pServer) ModifyCacheContent(filepath, content string) {
102 ptr, size := stringToPtr(filepath)
103 ptr2, size2 := stringToPtr(content)
104 _modifyCacheContent(ptr, size, ptr2, size2)
105 runtime.KeepAlive(filepath)
106 runtime.KeepAlive(content)
107}
108
109func (s *pServer) CommitAllIfNeeded(message string) {
110 if s.atLeastOneChange {
111 ptr, size := stringToPtr(message)
112 _commitAll(ptr, size)
113 runtime.KeepAlive(message)
114 }
115}
116
117func (s *pServer) DiffWithParent(hash string, oldFilepath string, newFilePath string) (string, error) {
118 ptrHash, sizeHash := stringToPtr(hash)
119 ptrOldFile, sizeOldFile := stringToPtr(oldFilepath)
120 ptrNewFile, sizeNewFile := stringToPtr(newFilePath)
121 ptrSizeDiff := _diffWithParent(ptrHash, sizeHash, ptrOldFile, sizeOldFile, ptrNewFile, sizeNewFile)
122 if ptrSizeDiff == 0 {
123 return "", errors.New("can't make diff")
124 }
125 ptrDiff := uint32(ptrSizeDiff >> 32)
126 sizeDiff := uint32(ptrSizeDiff)
127 return ptrToString(ptrDiff, sizeDiff), nil
128}
129
130func (s *pServer) Log(message string) {
131 ptr, size := stringToPtr(message)
132 _log(ptr, size)
133 runtime.KeepAlive(message)
134}
135
136func (s *pServer) LogError(message string, err error) {
137 ptr, size := stringToPtr(message)
138 errPtr, errSize := stringToPtr(err.Error())
139 _logError(ptr, size, errPtr, errSize)
140 runtime.KeepAlive(message)
141 runtime.KeepAlive(err)
142}
143
144func (s *pServer) Merge(from string, to string) {
145 fromPtr, fromSize := stringToPtr(from)
146 toPtr, toSize := stringToPtr(to)
147 _merge(fromPtr, fromSize, toPtr, toSize)
148 runtime.KeepAlive(from)
149 runtime.KeepAlive(to)
150}