aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md11
-rw-r--r--forged/internal/common/scfg/reader.go3
-rw-r--r--forged/internal/common/scfg/scfg.go7
-rw-r--r--forged/internal/common/scfg/struct.go17
-rw-r--r--forged/internal/common/scfg/unmarshal.go16
-rw-r--r--forged/internal/common/scfg/writer.go5
-rw-r--r--forged/internal/config/config.go94
-rw-r--r--go.mod10
-rw-r--r--go.sum11
9 files changed, 99 insertions, 75 deletions
diff --git a/README.md b/README.md
index a9b023f..5dee90f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,15 @@
# Lindenii Forge
-**Work in progress.**
+Lindenii Forge has been superseded.
+
+Further development will be on Villosa, which is temporarily hosted on
+[Codeberg](https://codeberg.org/lindenii/villosa).
+
+The `master` branch of Lindenii Forge doesn't have much. If you want to read
+the code of, I suppose most active instances of Lindenii Forge, see the
+`pre-refactor` branch.
+
+---
Lindenii Forge aims to be an uncomplicated yet featured software forge,
primarily designed for self-hosting by small organizations and individuals.
diff --git a/forged/internal/common/scfg/reader.go b/forged/internal/common/scfg/reader.go
index b0e2cc0..3ec45e4 100644
--- a/forged/internal/common/scfg/reader.go
+++ b/forged/internal/common/scfg/reader.go
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright (c) 2020 Simon Ser <https://emersion.fr>
+// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
-package scfg
+package scfgs
import (
"bufio"
diff --git a/forged/internal/common/scfg/scfg.go b/forged/internal/common/scfg/scfg.go
index 4533e63..3128b1c 100644
--- a/forged/internal/common/scfg/scfg.go
+++ b/forged/internal/common/scfg/scfg.go
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright (c) 2020 Simon Ser <https://emersion.fr>
+// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
-// Package scfg parses and formats configuration files.
-// Note that this fork of scfg behaves differently from upstream scfg.
-package scfg
+// Package scfgs parses and formats configuration files.
+// Note that this fork of scfgs behaves differently from upstream scfg.
+package scfgs
import (
"fmt"
diff --git a/forged/internal/common/scfg/struct.go b/forged/internal/common/scfg/struct.go
index 98ec943..c222385 100644
--- a/forged/internal/common/scfg/struct.go
+++ b/forged/internal/common/scfg/struct.go
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright (c) 2020 Simon Ser <https://emersion.fr>
+// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
-package scfg
+package scfgs
import (
"fmt"
@@ -10,7 +11,7 @@ import (
"sync"
)
-// structInfo contains scfg metadata for structs.
+// structInfo contains scfgs metadata for structs.
type structInfo struct {
param int // index of field storing parameters
children map[string]int // indices of fields storing child directives
@@ -37,12 +38,12 @@ func getStructInfo(t reflect.Type) (*structInfo, error) {
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.Anonymous {
- return nil, fmt.Errorf("scfg: anonymous struct fields are not supported")
+ return nil, fmt.Errorf("scfgs: anonymous struct fields are not supported")
} else if !f.IsExported() {
continue
}
- tag := f.Tag.Get("scfg")
+ tag := f.Tag.Get("scfgs")
parts := strings.Split(tag, ",")
k, options := parts[0], parts[1:]
if k == "-" {
@@ -57,21 +58,21 @@ func getStructInfo(t reflect.Type) (*structInfo, error) {
case "param":
isParam = true
default:
- return nil, fmt.Errorf("scfg: invalid option %q in struct tag", opt)
+ return nil, fmt.Errorf("scfgs: invalid option %q in struct tag", opt)
}
}
if isParam {
if info.param >= 0 {
- return nil, fmt.Errorf("scfg: param option specified multiple times in struct tag in %v", t)
+ return nil, fmt.Errorf("scfgs: param option specified multiple times in struct tag in %v", t)
}
if parts[0] != "" {
- return nil, fmt.Errorf("scfg: name must be empty when param option is specified in struct tag in %v", t)
+ return nil, fmt.Errorf("scfgs: name must be empty when param option is specified in struct tag in %v", t)
}
info.param = i
} else {
if _, ok := info.children[k]; ok {
- return nil, fmt.Errorf("scfg: key %q specified multiple times in struct tag in %v", k, t)
+ return nil, fmt.Errorf("scfgs: key %q specified multiple times in struct tag in %v", k, t)
}
info.children[k] = i
}
diff --git a/forged/internal/common/scfg/unmarshal.go b/forged/internal/common/scfg/unmarshal.go
index 8befc10..e60bcc7 100644
--- a/forged/internal/common/scfg/unmarshal.go
+++ b/forged/internal/common/scfg/unmarshal.go
@@ -2,7 +2,7 @@
// SPDX-FileCopyrightText: Copyright (c) 2020 Simon Ser <https://emersion.fr>
// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
-package scfg
+package scfgs
import (
"encoding"
@@ -12,7 +12,7 @@ import (
"strconv"
)
-// Decoder reads and decodes an scfg document from an input stream.
+// Decoder reads and decodes an scfgs document from an input stream.
type Decoder struct {
r io.Reader
unknownDirectives []*Directive
@@ -29,7 +29,7 @@ func (dec *Decoder) UnknownDirectives() []*Directive {
return dec.unknownDirectives
}
-// Decode reads scfg document from the input and stores it in the value pointed
+// Decode reads scfgs document from the input and stores it in the value pointed
// to by v.
//
// If v is nil or not a pointer, Decode returns an error.
@@ -60,7 +60,7 @@ func (dec *Decoder) UnknownDirectives() []*Directive {
// unmarshaled into the value. Children blocks are not allowed.
//
// The decoding of each struct field can be customized by the format string
-// stored under the "scfg" key in the struct field's tag. The tag contains the
+// stored under the "scfgs" key in the struct field's tag. The tag contains the
// name of the field possibly followed by a comma-separated list of options.
// The name may be empty in order to specify options without overriding the
// default field name. As a special case, if the field name is "-", the field
@@ -74,7 +74,7 @@ func (dec *Decoder) Decode(v interface{}) error {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
- return fmt.Errorf("scfg: invalid value for unmarshaling")
+ return fmt.Errorf("scfgs: invalid value for unmarshaling")
}
return dec.unmarshalBlock(block, rv)
@@ -92,7 +92,7 @@ func (dec *Decoder) unmarshalBlock(block Block, v reflect.Value) error {
switch v.Kind() {
case reflect.Map:
if t.Key().Kind() != reflect.String {
- return fmt.Errorf("scfg: map key type must be string")
+ return fmt.Errorf("scfgs: map key type must be string")
}
if v.IsNil() {
v.Set(reflect.MakeMap(t))
@@ -134,12 +134,12 @@ func (dec *Decoder) unmarshalBlock(block Block, v reflect.Value) error {
continue
}
if _, ok := seen[fieldIndex]; !ok {
- return fmt.Errorf("scfg: missing required directive %q", name)
+ return fmt.Errorf("scfgs: missing required directive %q", name)
}
}
default:
- return fmt.Errorf("scfg: unsupported type for unmarshaling blocks: %v", t)
+ return fmt.Errorf("scfgs: unsupported type for unmarshaling blocks: %v", t)
}
return nil
diff --git a/forged/internal/common/scfg/writer.go b/forged/internal/common/scfg/writer.go
index 02a07fe..979d71f 100644
--- a/forged/internal/common/scfg/writer.go
+++ b/forged/internal/common/scfg/writer.go
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright (c) 2020 Simon Ser <https://emersion.fr>
+// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org>
-package scfg
+package scfgs
import (
"errors"
@@ -9,7 +10,7 @@ import (
"strings"
)
-var errDirEmptyName = errors.New("scfg: directive with empty name")
+var errDirEmptyName = errors.New("scfgs: directive with empty name")
// Write writes a parsed configuration to the provided io.Writer.
func Write(w io.Writer, blk Block) error {
diff --git a/forged/internal/config/config.go b/forged/internal/config/config.go
index 1825882..414a811 100644
--- a/forged/internal/config/config.go
+++ b/forged/internal/config/config.go
@@ -10,79 +10,79 @@ import (
)
type Config struct {
- DB DB `scfg:"db"`
- Web Web `scfg:"web"`
- Hooks Hooks `scfg:"hooks"`
- LMTP LMTP `scfg:"lmtp"`
- SSH SSH `scfg:"ssh"`
- IRC IRC `scfg:"irc"`
- Git Git `scfg:"git"`
- General General `scfg:"general"`
- Pprof Pprof `scfg:"pprof"`
+ DB DB `scfgs:"db"`
+ Web Web `scfgs:"web"`
+ Hooks Hooks `scfgs:"hooks"`
+ LMTP LMTP `scfgs:"lmtp"`
+ SSH SSH `scfgs:"ssh"`
+ IRC IRC `scfgs:"irc"`
+ Git Git `scfgs:"git"`
+ General General `scfgs:"general"`
+ Pprof Pprof `scfgs:"pprof"`
}
type DB struct {
- Conn string `scfg:"conn"`
+ Conn string `scfgs:"conn"`
}
type Web struct {
- Net string `scfg:"net"`
- Addr string `scfg:"addr"`
- Root string `scfg:"root"`
- CookieExpiry int `scfg:"cookie_expiry"`
- ReadTimeout uint32 `scfg:"read_timeout"`
- WriteTimeout uint32 `scfg:"write_timeout"`
- IdleTimeout uint32 `scfg:"idle_timeout"`
- MaxHeaderBytes int `scfg:"max_header_bytes"`
- ReverseProxy bool `scfg:"reverse_proxy"`
- ShutdownTimeout uint32 `scfg:"shutdown_timeout"`
- TemplatesPath string `scfg:"templates_path"`
- StaticPath string `scfg:"static_path"`
+ Net string `scfgs:"net"`
+ Addr string `scfgs:"addr"`
+ Root string `scfgs:"root"`
+ CookieExpiry int `scfgs:"cookie_expiry"`
+ ReadTimeout uint32 `scfgs:"read_timeout"`
+ WriteTimeout uint32 `scfgs:"write_timeout"`
+ IdleTimeout uint32 `scfgs:"idle_timeout"`
+ MaxHeaderBytes int `scfgs:"max_header_bytes"`
+ ReverseProxy bool `scfgs:"reverse_proxy"`
+ ShutdownTimeout uint32 `scfgs:"shutdown_timeout"`
+ TemplatesPath string `scfgs:"templates_path"`
+ StaticPath string `scfgs:"static_path"`
}
type Hooks struct {
- Socket string `scfg:"socket"`
- Execs string `scfg:"execs"`
+ Socket string `scfgs:"socket"`
+ Execs string `scfgs:"execs"`
}
type LMTP struct {
- Socket string `scfg:"socket"`
- Domain string `scfg:"domain"`
- MaxSize int64 `scfg:"max_size"`
- WriteTimeout uint32 `scfg:"write_timeout"`
- ReadTimeout uint32 `scfg:"read_timeout"`
+ Socket string `scfgs:"socket"`
+ Domain string `scfgs:"domain"`
+ MaxSize int64 `scfgs:"max_size"`
+ WriteTimeout uint32 `scfgs:"write_timeout"`
+ ReadTimeout uint32 `scfgs:"read_timeout"`
}
type SSH struct {
- Net string `scfg:"net"`
- Addr string `scfg:"addr"`
- Key string `scfg:"key"`
- Root string `scfg:"root"`
- ShutdownTimeout uint32 `scfg:"shutdown_timeout"`
+ Net string `scfgs:"net"`
+ Addr string `scfgs:"addr"`
+ Key string `scfgs:"key"`
+ Root string `scfgs:"root"`
+ ShutdownTimeout uint32 `scfgs:"shutdown_timeout"`
}
type IRC 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"`
+ Net string `scfgs:"net"`
+ Addr string `scfgs:"addr"`
+ TLS bool `scfgs:"tls"`
+ SendQ uint `scfgs:"sendq"`
+ Nick string `scfgs:"nick"`
+ User string `scfgs:"user"`
+ Gecos string `scfgs:"gecos"`
}
type Git struct {
- RepoDir string `scfg:"repo_dir"`
- Socket string `scfg:"socket"`
+ RepoDir string `scfgs:"repo_dir"`
+ Socket string `scfgs:"socket"`
}
type General struct {
- Title string `scfg:"title"`
+ Title string `scfgs:"title"`
}
type Pprof struct {
- Net string `scfg:"net"`
- Addr string `scfg:"addr"`
+ Net string `scfgs:"net"`
+ Addr string `scfgs:"addr"`
}
func Open(path string) (config Config, err error) {
@@ -97,7 +97,7 @@ func Open(path string) (config Config, err error) {
_ = configFile.Close()
}()
- decoder := scfg.NewDecoder(bufio.NewReader(configFile))
+ decoder := scfgs.NewDecoder(bufio.NewReader(configFile))
err = decoder.Decode(&config)
if err != nil {
err = fmt.Errorf("decode config file: %w", err)
diff --git a/go.mod b/go.mod
index 7b10d50..86b0b01 100644
--- a/go.mod
+++ b/go.mod
@@ -4,10 +4,10 @@ go 1.24.1
require (
github.com/gliderlabs/ssh v0.3.8
- github.com/jackc/pgx/v5 v5.7.5
+ github.com/jackc/pgx/v5 v5.7.6
github.com/yuin/goldmark v1.7.13
- golang.org/x/crypto v0.41.0
- golang.org/x/sync v0.16.0
+ golang.org/x/crypto v0.43.0
+ golang.org/x/sync v0.17.0
)
require (
@@ -16,6 +16,6 @@ require (
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/stretchr/testify v1.10.0 // indirect
- golang.org/x/sys v0.35.0 // indirect
- golang.org/x/text v0.28.0 // indirect
+ golang.org/x/sys v0.37.0 // indirect
+ golang.org/x/text v0.30.0 // indirect
)
diff --git a/go.sum b/go.sum
index b1faca9..470a3bc 100644
--- a/go.sum
+++ b/go.sum
@@ -11,6 +11,8 @@ github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7Ulw
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs=
github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
+github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
+github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -24,14 +26,23 @@ github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
+golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
+golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
+golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
+golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
+golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
+golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
+golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=