aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-04-05 18:26:51 +0800
committerRunxi Yu <me@runxiyu.org>2025-04-05 18:26:51 +0800
commit4f4f6a25be2625b4bb2cb10e3520f52c4a35c243 (patch)
tree5458da1ee5efa5e46e831c34c1f39ebc67fb71b0
parentRemove renderReadmeAtTree (diff)
downloadforge-4f4f6a25be2625b4bb2cb10e3520f52c4a35c243.tar.gz
forge-4f4f6a25be2625b4bb2cb10e3520f52c4a35c243.tar.zst
forge-4f4f6a25be2625b4bb2cb10e3520f52c4a35c243.zip
Separate code/README rendering and unsafe to their own packages
-rw-r--r--git_hooks_handle_linux.go3
-rw-r--r--git_hooks_handle_other.go3
-rw-r--r--git_plumbing.go6
-rw-r--r--http_handle_repo_index.go3
-rw-r--r--http_handle_repo_tree.go3
-rw-r--r--lmtp_handle_patch.go3
-rw-r--r--misc/unsafe.go (renamed from unsafe.go)10
-rw-r--r--render/chroma.go (renamed from chroma.go)4
-rw-r--r--render/escape.go11
-rw-r--r--render/readme.go (renamed from readme_to_html.go)20
-rw-r--r--resources.go3
-rw-r--r--ssh_server.go5
12 files changed, 45 insertions, 29 deletions
diff --git a/git_hooks_handle_linux.go b/git_hooks_handle_linux.go
index e316bb7..3c556c3 100644
--- a/git_hooks_handle_linux.go
+++ b/git_hooks_handle_linux.go
@@ -22,6 +22,7 @@ import (
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/jackc/pgx/v5"
+ "go.lindenii.runxiyu.org/forge/misc"
"go.lindenii.runxiyu.org/lindenii-common/ansiec"
"go.lindenii.runxiyu.org/lindenii-common/clog"
)
@@ -76,7 +77,7 @@ func hooksHandler(conn net.Conn) {
{
var ok bool
- packPass, ok = packPasses.Load(bytesToString(cookie))
+ packPass, ok = packPasses.Load(misc.BytesToString(cookie))
if !ok {
if _, err = conn.Write([]byte{1}); err != nil {
return
diff --git a/git_hooks_handle_other.go b/git_hooks_handle_other.go
index 4285784..89a4193 100644
--- a/git_hooks_handle_other.go
+++ b/git_hooks_handle_other.go
@@ -20,6 +20,7 @@ import (
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/jackc/pgx/v5"
+ "go.lindenii.runxiyu.org/forge/misc"
"go.lindenii.runxiyu.org/lindenii-common/ansiec"
"go.lindenii.runxiyu.org/lindenii-common/clog"
)
@@ -54,7 +55,7 @@ func hooksHandler(conn net.Conn) {
{
var ok bool
- packPass, ok = packPasses.Load(bytesToString(cookie))
+ packPass, ok = packPasses.Load(misc.BytesToString(cookie))
if !ok {
if _, err = conn.Write([]byte{1}); err != nil {
return
diff --git a/git_plumbing.go b/git_plumbing.go
index 15329ad..74c80ac 100644
--- a/git_plumbing.go
+++ b/git_plumbing.go
@@ -13,6 +13,8 @@ import (
"path"
"sort"
"strings"
+
+ "go.lindenii.runxiyu.org/forge/misc"
)
func writeTree(ctx context.Context, repoPath string, entries []treeEntry) (string, error) {
@@ -76,14 +78,14 @@ func buildTreeRecursive(ctx context.Context, repoPath, baseTree string, updates
if modeEnd < 0 {
return errors.New("invalid tree format")
}
- mode := bytesToString(data[i : i+modeEnd])
+ mode := misc.BytesToString(data[i : i+modeEnd])
i += modeEnd + 1
nameEnd := bytes.IndexByte(data[i:], 0)
if nameEnd < 0 {
return errors.New("missing null after filename")
}
- name := bytesToString(data[i : i+nameEnd])
+ name := misc.BytesToString(data[i : i+nameEnd])
i += nameEnd + 1
if i+20 > len(data) {
diff --git a/http_handle_repo_index.go b/http_handle_repo_index.go
index 182b5df..ef1b76e 100644
--- a/http_handle_repo_index.go
+++ b/http_handle_repo_index.go
@@ -8,6 +8,7 @@ import (
"strings"
"go.lindenii.runxiyu.org/forge/git2c"
+ "go.lindenii.runxiyu.org/forge/render"
)
type commitDisplay struct {
@@ -45,7 +46,7 @@ func httpHandleRepoIndex(w http.ResponseWriter, req *http.Request, params map[st
params["commits"] = commits
params["readme_filename"] = readme.Filename
- _, params["readme"] = renderReadme(readme.Content, readme.Filename)
+ _, params["readme"] = render.Readme(readme.Content, readme.Filename)
params["notes"] = notes
renderTemplate(w, "repo_index", params)
diff --git a/http_handle_repo_tree.go b/http_handle_repo_tree.go
index 889406b..9cdd9cd 100644
--- a/http_handle_repo_tree.go
+++ b/http_handle_repo_tree.go
@@ -9,6 +9,7 @@ import (
"strings"
"go.lindenii.runxiyu.org/forge/git2c"
+ "go.lindenii.runxiyu.org/forge/render"
)
// httpHandleRepoTree provides a friendly, syntax-highlighted view of
@@ -44,7 +45,7 @@ func httpHandleRepoTree(writer http.ResponseWriter, request *http.Request, param
params["readme"] = template.HTML("<p>README rendering here is WIP again</p>") // TODO
renderTemplate(writer, "repo_tree_dir", params)
case content != "":
- rendered := renderHighlightedFile(pathSpec, content)
+ rendered := render.Highlight(pathSpec, content)
params["file_contents"] = rendered
renderTemplate(writer, "repo_tree_file", params)
default:
diff --git a/lmtp_handle_patch.go b/lmtp_handle_patch.go
index 6bcb272..45d146a 100644
--- a/lmtp_handle_patch.go
+++ b/lmtp_handle_patch.go
@@ -16,6 +16,7 @@ import (
"github.com/bluekeyes/go-gitdiff/gitdiff"
"github.com/go-git/go-git/v5"
+ "go.lindenii.runxiyu.org/forge/misc"
)
func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string, mbox io.Reader) (err error) {
@@ -63,7 +64,7 @@ func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string,
return fmt.Errorf("failed to get contents: %w", err)
}
- sourceBuf := bytes.NewReader(stringToBytes(sourceString))
+ sourceBuf := bytes.NewReader(misc.StringToBytes(sourceString))
var patchedBuf bytes.Buffer
if err := gitdiff.Apply(&patchedBuf, sourceBuf, diffFile); err != nil {
return fmt.Errorf("failed to apply patch: %w", err)
diff --git a/unsafe.go b/misc/unsafe.go
index a4e9ac8..6c2192f 100644
--- a/unsafe.go
+++ b/misc/unsafe.go
@@ -1,20 +1,20 @@
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
-package main
+package misc
import "unsafe"
-// stringToBytes converts a string to a byte slice without copying the string.
+// StringToBytes converts a string to a byte slice without copying the string.
// Memory is borrowed from the string.
// The resulting byte slice must not be modified in any form.
-func stringToBytes(s string) (bytes []byte) {
+func StringToBytes(s string) (bytes []byte) {
return unsafe.Slice(unsafe.StringData(s), len(s))
}
-// bytesToString converts a byte slice to a string without copying the bytes.
+// BytesToString converts a byte slice to a string without copying the bytes.
// Memory is borrowed from the byte slice.
// The source byte slice must not be modified.
-func bytesToString(b []byte) string {
+func BytesToString(b []byte) string {
return unsafe.String(unsafe.SliceData(b), len(b))
}
diff --git a/chroma.go b/render/chroma.go
index 0d904b7..c7d64ec 100644
--- a/chroma.go
+++ b/render/chroma.go
@@ -1,4 +1,4 @@
-package main
+package render
import (
"bytes"
@@ -9,7 +9,7 @@ import (
chromaStyles "github.com/alecthomas/chroma/v2/styles"
)
-func renderHighlightedFile(filename, content string) template.HTML {
+func Highlight(filename, content string) template.HTML {
lexer := chromaLexers.Match(filename)
if lexer == nil {
lexer = chromaLexers.Fallback
diff --git a/render/escape.go b/render/escape.go
new file mode 100644
index 0000000..44c56f3
--- /dev/null
+++ b/render/escape.go
@@ -0,0 +1,11 @@
+package render
+
+import (
+ "html"
+ "html/template"
+)
+
+// EscapeHTML just escapes a string and wraps it in [template.HTML].
+func EscapeHTML(s string) template.HTML {
+ return template.HTML(html.EscapeString(s)) //#nosec G203
+}
diff --git a/readme_to_html.go b/render/readme.go
index 6d3f6f3..1a153fb 100644
--- a/readme_to_html.go
+++ b/render/readme.go
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
-package main
+package render
import (
"bytes"
@@ -13,33 +13,29 @@ import (
"github.com/niklasfasching/go-org/org"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
+ "go.lindenii.runxiyu.org/forge/misc"
)
var markdownConverter = goldmark.New(goldmark.WithExtensions(extension.GFM))
-// escapeHTML just escapes a string and wraps it in [template.HTML].
-func escapeHTML(s string) template.HTML {
- return template.HTML(html.EscapeString(s)) //#nosec G203
-}
-
// renderReadme renders and sanitizes README content from a byte slice and filename.
-func renderReadme(data []byte, filename string) (string, template.HTML) {
+func Readme(data []byte, filename string) (string, template.HTML) {
switch strings.ToLower(filename) {
case "readme":
- return "README", template.HTML("<pre>" + html.EscapeString(bytesToString(data)) + "</pre>") //#nosec G203
+ return "README", template.HTML("<pre>" + html.EscapeString(misc.BytesToString(data)) + "</pre>") //#nosec G203
case "readme.md":
var buf bytes.Buffer
if err := markdownConverter.Convert(data, &buf); err != nil {
- return "Error fetching README", escapeHTML("Unable to render README: " + err.Error())
+ return "Error fetching README", EscapeHTML("Unable to render README: " + err.Error())
}
return "README.md", template.HTML(bluemonday.UGCPolicy().SanitizeBytes(buf.Bytes())) //#nosec G203
case "readme.org":
- htmlStr, err := org.New().Parse(strings.NewReader(bytesToString(data)), filename).Write(org.NewHTMLWriter())
+ htmlStr, err := org.New().Parse(strings.NewReader(misc.BytesToString(data)), filename).Write(org.NewHTMLWriter())
if err != nil {
- return "Error fetching README", escapeHTML("Unable to render README: " + err.Error())
+ return "Error fetching README", EscapeHTML("Unable to render README: " + err.Error())
}
return "README.org", template.HTML(bluemonday.UGCPolicy().Sanitize(htmlStr)) //#nosec G203
default:
- return filename, template.HTML("<pre>" + html.EscapeString(bytesToString(data)) + "</pre>") //#nosec G203
+ return filename, template.HTML("<pre>" + html.EscapeString(misc.BytesToString(data)) + "</pre>") //#nosec G203
}
}
diff --git a/resources.go b/resources.go
index 0bb033a..00d7b66 100644
--- a/resources.go
+++ b/resources.go
@@ -11,6 +11,7 @@ import (
"github.com/tdewolff/minify/v2"
"github.com/tdewolff/minify/v2/html"
+ "go.lindenii.runxiyu.org/forge/misc"
)
//go:embed LICENSE source.tar.gz
@@ -59,7 +60,7 @@ func loadTemplates() (err error) {
return err
}
- _, err = templates.Parse(bytesToString(minified))
+ _, err = templates.Parse(misc.BytesToString(minified))
if err != nil {
return err
}
diff --git a/ssh_server.go b/ssh_server.go
index a3b69e4..1408a2a 100644
--- a/ssh_server.go
+++ b/ssh_server.go
@@ -10,6 +10,7 @@ import (
"strings"
gliderSSH "github.com/gliderlabs/ssh"
+ "go.lindenii.runxiyu.org/forge/misc"
"go.lindenii.runxiyu.org/lindenii-common/ansiec"
"go.lindenii.runxiyu.org/lindenii-common/clog"
goSSH "golang.org/x/crypto/ssh"
@@ -39,7 +40,7 @@ func serveSSH(listener net.Listener) error {
}
serverPubkey = hostKey.PublicKey()
- serverPubkeyString = bytesToString(goSSH.MarshalAuthorizedKey(serverPubkey))
+ serverPubkeyString = misc.BytesToString(goSSH.MarshalAuthorizedKey(serverPubkey))
serverPubkeyFP = goSSH.FingerprintSHA256(serverPubkey)
server = &gliderSSH.Server{
@@ -47,7 +48,7 @@ func serveSSH(listener net.Listener) error {
clientPubkey := session.PublicKey()
var clientPubkeyStr string
if clientPubkey != nil {
- clientPubkeyStr = strings.TrimSuffix(bytesToString(goSSH.MarshalAuthorizedKey(clientPubkey)), "\n")
+ clientPubkeyStr = strings.TrimSuffix(misc.BytesToString(goSSH.MarshalAuthorizedKey(clientPubkey)), "\n")
}
clog.Info("Incoming SSH: " + session.RemoteAddr().String() + " " + clientPubkeyStr + " " + session.RawCommand())