From 6f5e22e764283262ae8c6519bb030766db0fd35b Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Sun, 06 Apr 2025 09:58:02 +0800 Subject: [PATCH] Add more documentation comments --- forged/internal/database/database.go | 5 +++++ forged/internal/embed/embed.go | 6 ++++++ forged/internal/git2c/client.go | 7 +++++-- forged/internal/git2c/cmd_index.go | 2 ++ forged/internal/git2c/cmd_treeraw.go | 2 ++ forged/internal/git2c/git_types.go | 3 +++ forged/internal/irc/bot.go | 11 ++++++++++- forged/internal/misc/back.go | 2 ++ forged/internal/misc/deploy.go | 2 ++ forged/internal/misc/panic.go | 2 ++ forged/internal/misc/url.go | 1 + forged/internal/oldgit/patch.go | 1 + forged/internal/render/chroma.go | 3 +++ forged/internal/web/error_pages.go | 12 ++++++++++++ diff --git a/forged/internal/database/database.go b/forged/internal/database/database.go index a4826249546c6307e6042eeb9ea8918380a365fd..b995adc8cabbc4b6138468682c3c7022bda6631e 100644 --- a/forged/internal/database/database.go +++ b/forged/internal/database/database.go @@ -10,10 +10,15 @@ "github.com/jackc/pgx/v5/pgxpool" ) +// Database is a wrapper around pgxpool.Pool to provide a common interface for +// other packages in the forge. type Database struct { *pgxpool.Pool } +// Open opens a new database connection pool using the provided connection +// string. It returns a Database instance and an error if any occurs. +// It is run indefinitely in the background. func Open(connString string) (Database, error) { db, err := pgxpool.New(context.Background(), connString) return Database{db}, err diff --git a/forged/internal/embed/embed.go b/forged/internal/embed/embed.go index c9eeeb3899772f32805304dc41243f5423f998e0..1f0dcdfd6a8061ae0ae16bc4538ed20e4a80a0f7 100644 --- a/forged/internal/embed/embed.go +++ b/forged/internal/embed/embed.go @@ -6,9 +6,15 @@ package embed import "embed" +// Source contains the licenses and source tarballs collected at build time. +// It is intended to be served to the user. +// //go:embed LICENSE* source.tar.gz var Source embed.FS +// Resources contains the templates and static files used by the web interface, +// as well as the git backend daemon and the hookc helper. +// //go:embed forged/templates/* forged/static/* //go:embed hookc/hookc git2d/git2d var Resources embed.FS diff --git a/forged/internal/git2c/client.go b/forged/internal/git2c/client.go index d178c47089b5b99eac7680dc503bcadaaee662e4..82454d136a1e58fa04d65b1ad10a89575e37af97 100644 --- a/forged/internal/git2c/client.go +++ b/forged/internal/git2c/client.go @@ -11,13 +11,15 @@ "git.sr.ht/~sircmpwn/go-bare" ) +// Client represents a connection to the git2d backend daemon. type Client struct { - SocketPath string + socketPath string conn net.Conn writer *bare.Writer reader *bare.Reader } +// NewClient establishes a connection to a git2d socket and returns a new Client. func NewClient(socketPath string) (*Client, error) { conn, err := net.Dial("unix", socketPath) if err != nil { @@ -28,13 +30,14 @@ writer := bare.NewWriter(conn) reader := bare.NewReader(conn) return &Client{ - SocketPath: socketPath, + socketPath: socketPath, conn: conn, writer: writer, reader: reader, }, nil } +// Close terminates the underlying socket connection. func (c *Client) Close() error { if c.conn != nil { return c.conn.Close() diff --git a/forged/internal/git2c/cmd_index.go b/forged/internal/git2c/cmd_index.go index a705a63ed09a478b5257014b2c2b64e448337c60..8862b2cd828ee970bdc8d42a54bbefd82aed6c23 100644 --- a/forged/internal/git2c/cmd_index.go +++ b/forged/internal/git2c/cmd_index.go @@ -10,6 +10,8 @@ "fmt" "io" ) +// CmdIndex requests a repository index from git2d and returns the list of commits +// and the contents of a README file if available. func (c *Client) CmdIndex(repoPath string) ([]Commit, *FilenameContents, error) { if err := c.writer.WriteData([]byte(repoPath)); err != nil { return nil, nil, fmt.Errorf("sending repo path failed: %w", err) diff --git a/forged/internal/git2c/cmd_treeraw.go b/forged/internal/git2c/cmd_treeraw.go index c93480a8c5e11fe5dfd8f42e029a3ff4826774ec..492cb849b1672a8d37622d693b2f27db0560e6c0 100644 --- a/forged/internal/git2c/cmd_treeraw.go +++ b/forged/internal/git2c/cmd_treeraw.go @@ -9,6 +9,8 @@ "fmt" "io" ) +// CmdTreeRaw queries git2d for a tree or blob object at the given path within the repository. +// It returns either a directory listing or the contents of a file. func (c *Client) CmdTreeRaw(repoPath, pathSpec string) ([]TreeEntry, string, error) { if err := c.writer.WriteData([]byte(repoPath)); err != nil { return nil, "", fmt.Errorf("sending repo path failed: %w", err) diff --git a/forged/internal/git2c/git_types.go b/forged/internal/git2c/git_types.go index da685bf9a3980119ed586d9ab49c08dad35d62ce..bf13f0593562b2185fd9ac476ae1e22b3624457b 100644 --- a/forged/internal/git2c/git_types.go +++ b/forged/internal/git2c/git_types.go @@ -3,6 +3,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu package git2c +// Commit represents a single commit object retrieved from the git2d daemon. type Commit struct { Hash string Author string @@ -11,11 +12,13 @@ Date string Message string } +// FilenameContents holds the filename and byte contents of a file, such as a README. type FilenameContents struct { Filename string Content []byte } +// TreeEntry represents a file or directory entry within a Git tree object. type TreeEntry struct { Name string Mode string diff --git a/forged/internal/irc/bot.go b/forged/internal/irc/bot.go index 89de024b0eb7909613512abe5025374afcda5849..046799ff07a44f2356e5e3b5ecdef1482e748854 100644 --- a/forged/internal/irc/bot.go +++ b/forged/internal/irc/bot.go @@ -13,6 +13,8 @@ "go.lindenii.runxiyu.org/forge/forged/internal/misc" irc "go.lindenii.runxiyu.org/lindenii-irc" ) +// Config contains IRC connection and identity settings for the bot. +// This should usually be a part of the primary config struct. type Config struct { Net string `scfg:"net"` Addr string `scfg:"addr"` @@ -23,12 +25,14 @@ User string `scfg:"user"` Gecos string `scfg:"gecos"` } +// Bot represents an IRC bot client that handles events and allows for sending messages. type Bot struct { config *Config ircSendBuffered chan string ircSendDirectChan chan misc.ErrorBack[string] } +// NewBot creates a new Bot instance using the provided configuration. func NewBot(c *Config) (b *Bot) { b = &Bot{ config: c, @@ -36,6 +40,8 @@ } return } +// Connect establishes a new IRC session and starts handling incoming and outgoing messages. +// This method blocks until an error occurs or the connection is closed. func (b *Bot) Connect() error { var err error var underlyingConn net.Conn @@ -148,6 +154,8 @@ return <-ech } +// Send queues a message to be sent asynchronously via the buffered send queue. +// If the queue is full, the message is dropped and an error is logged. func (b *Bot) Send(line string) { select { case b.ircSendBuffered <- line: @@ -156,7 +164,8 @@ slog.Error("irc sendq full", "line", line) } } -// TODO: Delay and warnings? +// ConnectLoop continuously attempts to maintain an IRC session. +// If the connection drops, it automatically retries with no delay. func (b *Bot) ConnectLoop() { b.ircSendBuffered = make(chan string, b.config.SendQ) b.ircSendDirectChan = make(chan misc.ErrorBack[string]) diff --git a/forged/internal/misc/back.go b/forged/internal/misc/back.go index ef4ed2270d01067764387f7202f7cbf181c7183e..5351359e1045678f0069bac7ac77d306acf59e9b 100644 --- a/forged/internal/misc/back.go +++ b/forged/internal/misc/back.go @@ -3,6 +3,8 @@ // SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu package misc +// ErrorBack wraps a value and a channel for communicating an associated error. +// Typically used to get an error response after sending data across a channel. type ErrorBack[T any] struct { Content T ErrorChan chan error diff --git a/forged/internal/misc/deploy.go b/forged/internal/misc/deploy.go index 0f24f49a3daa07c306027e69bdf95d588f8752cf..3ee5f927ae510ffe69709009e95b3c0dfe23f769 100644 --- a/forged/internal/misc/deploy.go +++ b/forged/internal/misc/deploy.go @@ -9,6 +9,8 @@ "io/fs" "os" ) +// DeployBinary copies the contents of a binary file to the target destination path. +// The destination file is created with executable permissions. func DeployBinary(src fs.File, dst string) (err error) { var dstFile *os.File if dstFile, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755); err != nil { diff --git a/forged/internal/misc/panic.go b/forged/internal/misc/panic.go index 94cd47ada6bf4725951bf2d1e1cac83131f7ba80..34c49c50d8f6729c20f9ffd9e7060acdd8c17c1b 100644 --- a/forged/internal/misc/panic.go +++ b/forged/internal/misc/panic.go @@ -3,6 +3,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu package misc +// FirstOrPanic returns the value or panics if the error is non-nil. func FirstOrPanic[T any](v T, err error) T { if err != nil { panic(err) @@ -10,6 +11,7 @@ } return v } +// NoneOrPanic panics if the provided error is non-nil. func NoneOrPanic(err error) { if err != nil { panic(err) diff --git a/forged/internal/misc/url.go b/forged/internal/misc/url.go index b77d8ce0a667fdc97cf1f84b02d038a9b77e74f0..0f9dc04415224eab80ec2d0dca1f5b2ebed21ca7 100644 --- a/forged/internal/misc/url.go +++ b/forged/internal/misc/url.go @@ -60,6 +60,7 @@ params, err = url.ParseQuery(paramsStr) return } +// PathToSegments splits a path into unescaped segments. It handles %2F correctly. func PathToSegments(path string) (segments []string, err error) { segments = strings.Split(strings.TrimPrefix(path, "/"), "/") diff --git a/forged/internal/oldgit/patch.go b/forged/internal/oldgit/patch.go index 30bf8e8e8f959f6e03772b82bd0835c9979a1546..fc8ef98737cf94d48e57fa17740ee36dc8e21719 100644 --- a/forged/internal/oldgit/patch.go +++ b/forged/internal/oldgit/patch.go @@ -39,4 +39,5 @@ } return } +// NullTree is a tree object that is empty and has no hash. var NullTree object.Tree //nolint:gochecknoglobals diff --git a/forged/internal/render/chroma.go b/forged/internal/render/chroma.go index c1a1869aecb7983fed2aae02f1aeb645f5446b46..64bfde0398864e7be2f4f1c7b359bbca5eee8790 100644 --- a/forged/internal/render/chroma.go +++ b/forged/internal/render/chroma.go @@ -12,6 +12,9 @@ chromaLexers "github.com/alecthomas/chroma/v2/lexers" chromaStyles "github.com/alecthomas/chroma/v2/styles" ) +// Highlight returns HTML with syntax highlighting for the given file content, +// using Chroma. The lexer is selected based on the filename. +// If tokenization or formatting fails, a fallback
 block is returned with the error.
 func Highlight(filename, content string) template.HTML {
 	lexer := chromaLexers.Match(filename)
 	if lexer == nil {
diff --git a/forged/internal/web/error_pages.go b/forged/internal/web/error_pages.go
index 200e9d371c0391f6fdc53784c509b1e4f2eb3b77..2ba9a1a0e314cdd6f57fad2fdae985a8f887b7e9 100644
--- a/forged/internal/web/error_pages.go
+++ b/forged/internal/web/error_pages.go
@@ -8,40 +8,52 @@ 	"html/template"
 	"net/http"
 )
 
+// ErrorPage404 renders a 404 Not Found error page using the "404" template.
 func ErrorPage404(templates *template.Template, w http.ResponseWriter, params map[string]any) {
 	w.WriteHeader(http.StatusNotFound)
 	_ = templates.ExecuteTemplate(w, "404", params)
 }
 
+// ErrorPage400 renders a 400 Bad Request error page using the "400" template.
+// The error message is passed via the "complete_error_msg" template param.
 func ErrorPage400(templates *template.Template, w http.ResponseWriter, params map[string]any, msg string) {
 	w.WriteHeader(http.StatusBadRequest)
 	params["complete_error_msg"] = msg
 	_ = templates.ExecuteTemplate(w, "400", params)
 }
 
+// ErrorPage400Colon renders a 400 Bad Request error page telling the user
+// that we migrated from : to -.
 func ErrorPage400Colon(templates *template.Template, w http.ResponseWriter, params map[string]any) {
 	w.WriteHeader(http.StatusBadRequest)
 	_ = templates.ExecuteTemplate(w, "400_colon", params)
 }
 
+// ErrorPage403 renders a 403 Forbidden error page using the "403" template.
+// The error message is passed via the "complete_error_msg" template param.
 func ErrorPage403(templates *template.Template, w http.ResponseWriter, params map[string]any, msg string) {
 	w.WriteHeader(http.StatusForbidden)
 	params["complete_error_msg"] = msg
 	_ = templates.ExecuteTemplate(w, "403", params)
 }
 
+// ErrorPage451 renders a 451 Unavailable For Legal Reasons error page using the "451" template.
+// The error message is passed via the "complete_error_msg" template param.
 func ErrorPage451(templates *template.Template, w http.ResponseWriter, params map[string]any, msg string) {
 	w.WriteHeader(http.StatusUnavailableForLegalReasons)
 	params["complete_error_msg"] = msg
 	_ = templates.ExecuteTemplate(w, "451", params)
 }
 
+// ErrorPage500 renders a 500 Internal Server Error page using the "500" template.
+// The error message is passed via the "complete_error_msg" template param.
 func ErrorPage500(templates *template.Template, w http.ResponseWriter, params map[string]any, msg string) {
 	w.WriteHeader(http.StatusInternalServerError)
 	params["complete_error_msg"] = msg
 	_ = templates.ExecuteTemplate(w, "500", params)
 }
 
+// ErrorPage501 renders a 501 Not Implemented error page using the "501" template.
 func ErrorPage501(templates *template.Template, w http.ResponseWriter, params map[string]any) {
 	w.WriteHeader(http.StatusNotImplemented)
 	_ = templates.ExecuteTemplate(w, "501", params)

-- 
2.48.1