aboutsummaryrefslogtreecommitdiff
path: root/forged/internal/ipc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--forged/internal/ipc/git2c/client.go (renamed from forged/internal/git2c/client.go)16
-rw-r--r--forged/internal/ipc/git2c/cmd_index.go (renamed from forged/internal/git2c/cmd_index.go)6
-rw-r--r--forged/internal/ipc/git2c/cmd_treeraw.go (renamed from forged/internal/git2c/cmd_treeraw.go)9
-rw-r--r--forged/internal/ipc/git2c/doc.go2
-rw-r--r--forged/internal/ipc/git2c/git_types.go (renamed from forged/internal/git2c/git_types.go)0
-rw-r--r--forged/internal/ipc/git2c/perror.go (renamed from forged/internal/git2c/perror.go)3
-rw-r--r--forged/internal/ipc/irc/bot.go (renamed from forged/internal/irc/bot.go)38
-rw-r--r--forged/internal/ipc/irc/config.go13
-rw-r--r--forged/internal/ipc/irc/conn.go (renamed from forged/internal/irc/conn.go)15
-rw-r--r--forged/internal/ipc/irc/doc.go2
-rw-r--r--forged/internal/ipc/irc/errors.go (renamed from forged/internal/irc/errors.go)0
-rw-r--r--forged/internal/ipc/irc/message.go (renamed from forged/internal/irc/message.go)20
-rw-r--r--forged/internal/ipc/irc/source.go (renamed from forged/internal/irc/source.go)3
13 files changed, 78 insertions, 49 deletions
diff --git a/forged/internal/git2c/client.go b/forged/internal/ipc/git2c/client.go
index ed9390c..8b11035 100644
--- a/forged/internal/git2c/client.go
+++ b/forged/internal/ipc/git2c/client.go
@@ -1,14 +1,14 @@
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
-// Package git2c provides routines to interact with the git2d backend daemon.
package git2c
import (
+ "context"
"fmt"
"net"
- "go.lindenii.runxiyu.org/forge/forged/internal/bare"
+ "go.lindenii.runxiyu.org/forge/forged/internal/common/bare"
)
// Client represents a connection to the git2d backend daemon.
@@ -20,8 +20,9 @@ type Client struct {
}
// 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)
+func NewClient(ctx context.Context, socketPath string) (*Client, error) {
+ dialer := &net.Dialer{} //exhaustruct:ignore
+ conn, err := dialer.DialContext(ctx, "unix", socketPath)
if err != nil {
return nil, fmt.Errorf("git2d connection failed: %w", err)
}
@@ -38,9 +39,12 @@ func NewClient(socketPath string) (*Client, error) {
}
// Close terminates the underlying socket connection.
-func (c *Client) Close() error {
+func (c *Client) Close() (err error) {
if c.conn != nil {
- return c.conn.Close()
+ err = c.conn.Close()
+ if err != nil {
+ return fmt.Errorf("close underlying socket: %w", err)
+ }
}
return nil
}
diff --git a/forged/internal/git2c/cmd_index.go b/forged/internal/ipc/git2c/cmd_index.go
index 8862b2c..e9fc435 100644
--- a/forged/internal/git2c/cmd_index.go
+++ b/forged/internal/ipc/git2c/cmd_index.go
@@ -13,10 +13,12 @@ import (
// 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 {
+ err := c.writer.WriteData([]byte(repoPath))
+ if err != nil {
return nil, nil, fmt.Errorf("sending repo path failed: %w", err)
}
- if err := c.writer.WriteUint(1); err != nil {
+ err = c.writer.WriteUint(1)
+ if err != nil {
return nil, nil, fmt.Errorf("sending command failed: %w", err)
}
diff --git a/forged/internal/git2c/cmd_treeraw.go b/forged/internal/ipc/git2c/cmd_treeraw.go
index 492cb84..89b702c 100644
--- a/forged/internal/git2c/cmd_treeraw.go
+++ b/forged/internal/ipc/git2c/cmd_treeraw.go
@@ -12,13 +12,16 @@ import (
// 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 {
+ err := c.writer.WriteData([]byte(repoPath))
+ if err != nil {
return nil, "", fmt.Errorf("sending repo path failed: %w", err)
}
- if err := c.writer.WriteUint(2); err != nil {
+ err = c.writer.WriteUint(2)
+ if err != nil {
return nil, "", fmt.Errorf("sending command failed: %w", err)
}
- if err := c.writer.WriteData([]byte(pathSpec)); err != nil {
+ err = c.writer.WriteData([]byte(pathSpec))
+ if err != nil {
return nil, "", fmt.Errorf("sending path failed: %w", err)
}
diff --git a/forged/internal/ipc/git2c/doc.go b/forged/internal/ipc/git2c/doc.go
new file mode 100644
index 0000000..e14dae0
--- /dev/null
+++ b/forged/internal/ipc/git2c/doc.go
@@ -0,0 +1,2 @@
+// Package git2c provides routines to interact with the git2d backend daemon.
+package git2c
diff --git a/forged/internal/git2c/git_types.go b/forged/internal/ipc/git2c/git_types.go
index bf13f05..bf13f05 100644
--- a/forged/internal/git2c/git_types.go
+++ b/forged/internal/ipc/git2c/git_types.go
diff --git a/forged/internal/git2c/perror.go b/forged/internal/ipc/git2c/perror.go
index 96bffd5..6bc7595 100644
--- a/forged/internal/git2c/perror.go
+++ b/forged/internal/ipc/git2c/perror.go
@@ -8,7 +8,6 @@ package git2c
import "errors"
var (
- Success error
ErrUnknown = errors.New("git2c: unknown error")
ErrPath = errors.New("git2c: get tree entry by path failed")
ErrRevparse = errors.New("git2c: revparse failed")
@@ -24,7 +23,7 @@ var (
func Perror(errno uint) error {
switch errno {
case 0:
- return Success
+ return nil
case 3:
return ErrPath
case 4:
diff --git a/forged/internal/irc/bot.go b/forged/internal/ipc/irc/bot.go
index 1c6d32f..07008ae 100644
--- a/forged/internal/irc/bot.go
+++ b/forged/internal/ipc/irc/bot.go
@@ -1,31 +1,21 @@
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
-// Package irc provides basic IRC bot functionality.
package irc
import (
+ "context"
"crypto/tls"
+ "fmt"
"log/slog"
"net"
- "go.lindenii.runxiyu.org/forge/forged/internal/misc"
+ "go.lindenii.runxiyu.org/forge/forged/internal/common/misc"
)
-// 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"`
- TLS bool `scfg:"tls"`
- SendQ uint `scfg:"sendq"`
- Nick string `scfg:"nick"`
- 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 {
+ // TODO: Use each config field instead of embedding Config here.
config *Config
ircSendBuffered chan string
ircSendDirectChan chan misc.ErrorBack[string]
@@ -35,24 +25,28 @@ type Bot struct {
func NewBot(c *Config) (b *Bot) {
b = &Bot{
config: c,
- }
+ } //exhaustruct:ignore
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 {
+func (b *Bot) Connect(ctx context.Context) error {
var err error
var underlyingConn net.Conn
if b.config.TLS {
- underlyingConn, err = tls.Dial(b.config.Net, b.config.Addr, nil)
+ dialer := tls.Dialer{} //exhaustruct:ignore
+ underlyingConn, err = dialer.DialContext(ctx, b.config.Net, b.config.Addr)
} else {
- underlyingConn, err = net.Dial(b.config.Net, b.config.Addr)
+ dialer := net.Dialer{} //exhaustruct:ignore
+ underlyingConn, err = dialer.DialContext(ctx, b.config.Net, b.config.Addr)
}
if err != nil {
- return err
+ return fmt.Errorf("dialing irc: %w", err)
}
- defer underlyingConn.Close()
+ defer func() {
+ _ = underlyingConn.Close()
+ }()
conn := NewConn(underlyingConn)
@@ -165,12 +159,12 @@ func (b *Bot) Send(line string) {
// ConnectLoop continuously attempts to maintain an IRC session.
// If the connection drops, it automatically retries with no delay.
-func (b *Bot) ConnectLoop() {
+func (b *Bot) ConnectLoop(ctx context.Context) {
b.ircSendBuffered = make(chan string, b.config.SendQ)
b.ircSendDirectChan = make(chan misc.ErrorBack[string])
for {
- err := b.Connect()
+ err := b.Connect(ctx)
slog.Error("irc session error", "error", err)
}
}
diff --git a/forged/internal/ipc/irc/config.go b/forged/internal/ipc/irc/config.go
new file mode 100644
index 0000000..b1b5703
--- /dev/null
+++ b/forged/internal/ipc/irc/config.go
@@ -0,0 +1,13 @@
+package 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"`
+ TLS bool `scfg:"tls"`
+ SendQ uint `scfg:"sendq"`
+ Nick string `scfg:"nick"`
+ User string `scfg:"user"`
+ Gecos string `scfg:"gecos"`
+}
diff --git a/forged/internal/irc/conn.go b/forged/internal/ipc/irc/conn.go
index b975b72..b9b208c 100644
--- a/forged/internal/irc/conn.go
+++ b/forged/internal/ipc/irc/conn.go
@@ -2,10 +2,11 @@ package irc
import (
"bufio"
+ "fmt"
"net"
"slices"
- "go.lindenii.runxiyu.org/forge/forged/internal/misc"
+ "go.lindenii.runxiyu.org/forge/forged/internal/common/misc"
)
type Conn struct {
@@ -41,9 +42,17 @@ func (c *Conn) ReadMessage() (msg Message, line string, err error) {
}
func (c *Conn) Write(p []byte) (n int, err error) {
- return c.netConn.Write(p)
+ n, err = c.netConn.Write(p)
+ if err != nil {
+ err = fmt.Errorf("write to connection: %w", err)
+ }
+ return n, err
}
func (c *Conn) WriteString(s string) (n int, err error) {
- return c.netConn.Write(misc.StringToBytes(s))
+ n, err = c.netConn.Write(misc.StringToBytes(s))
+ if err != nil {
+ err = fmt.Errorf("write to connection: %w", err)
+ }
+ return n, err
}
diff --git a/forged/internal/ipc/irc/doc.go b/forged/internal/ipc/irc/doc.go
new file mode 100644
index 0000000..dcfca82
--- /dev/null
+++ b/forged/internal/ipc/irc/doc.go
@@ -0,0 +1,2 @@
+// Package irc provides basic IRC bot functionality.
+package irc
diff --git a/forged/internal/irc/errors.go b/forged/internal/ipc/irc/errors.go
index 3506c70..3506c70 100644
--- a/forged/internal/irc/errors.go
+++ b/forged/internal/ipc/irc/errors.go
diff --git a/forged/internal/irc/message.go b/forged/internal/ipc/irc/message.go
index 84b6867..3387bec 100644
--- a/forged/internal/irc/message.go
+++ b/forged/internal/ipc/irc/message.go
@@ -7,7 +7,7 @@ package irc
import (
"bytes"
- "go.lindenii.runxiyu.org/forge/forged/internal/misc"
+ "go.lindenii.runxiyu.org/forge/forged/internal/common/misc"
)
type Message struct {
@@ -24,18 +24,18 @@ func Parse(raw []byte) (msg Message, err error) {
if bytes.HasPrefix(sp[0], []byte{'@'}) { // TODO: Check size manually
if len(sp[0]) < 2 {
err = ErrMalformedMsg
- return
+ return msg, err
}
sp[0] = sp[0][1:]
msg.Tags, err = tagsToMap(sp[0])
if err != nil {
- return
+ return msg, err
}
if len(sp) < 2 {
err = ErrMalformedMsg
- return
+ return msg, err
}
sp = sp[1:]
} else {
@@ -45,7 +45,7 @@ func Parse(raw []byte) (msg Message, err error) {
if bytes.HasPrefix(sp[0], []byte{':'}) { // TODO: Check size manually
if len(sp[0]) < 2 {
err = ErrMalformedMsg
- return
+ return msg, err
}
sp[0] = sp[0][1:]
@@ -53,14 +53,14 @@ func Parse(raw []byte) (msg Message, err error) {
if len(sp) < 2 {
err = ErrMalformedMsg
- return
+ return msg, err
}
sp = sp[1:]
}
msg.Command = misc.BytesToString(sp[0])
if len(sp) < 2 {
- return
+ return msg, err
}
sp = sp[1:]
@@ -81,7 +81,7 @@ func Parse(raw []byte) (msg Message, err error) {
msg.Args = append(msg.Args, misc.BytesToString(sp[i]))
}
- return
+ return msg, err
}
var ircv3TagEscapes = map[byte]byte{ //nolint:gochecknoglobals
@@ -97,7 +97,7 @@ func tagsToMap(raw []byte) (tags map[string]string, err error) {
key, value, found := bytes.Cut(rawTag, []byte{'='})
if !found {
err = ErrInvalidIRCv3Tag
- return
+ return tags, err
}
if len(value) == 0 {
tags[misc.BytesToString(key)] = ""
@@ -122,5 +122,5 @@ func tagsToMap(raw []byte) (tags map[string]string, err error) {
}
}
}
- return
+ return tags, err
}
diff --git a/forged/internal/irc/source.go b/forged/internal/ipc/irc/source.go
index d955f45..938751f 100644
--- a/forged/internal/irc/source.go
+++ b/forged/internal/ipc/irc/source.go
@@ -6,13 +6,14 @@ package irc
import (
"bytes"
- "go.lindenii.runxiyu.org/forge/forged/internal/misc"
+ "go.lindenii.runxiyu.org/forge/forged/internal/common/misc"
)
type Source interface {
AsSourceString() string
}
+//nolint:ireturn
func parseSource(s []byte) Source {
nick, userhost, found := bytes.Cut(s, []byte{'!'})
if !found {