diff --git a/flag.go b/flag.go index 70646bf..82a2627 100644 --- a/flag.go +++ b/flag.go @@ -3,19 +3,20 @@ package main import ( "bufio" _ "embed" + "errors" "flag" "fmt" "io" - "log" + "log/slog" "os" "path/filepath" - "golang.org/x/term" - "github.com/bouncepaw/mycorrhiza/internal/cfg" "github.com/bouncepaw/mycorrhiza/internal/files" - user2 "github.com/bouncepaw/mycorrhiza/internal/user" + "github.com/bouncepaw/mycorrhiza/internal/user" "github.com/bouncepaw/mycorrhiza/internal/version" + + "golang.org/x/term" ) // CLI options are read and parsed here. @@ -31,7 +32,7 @@ func printHelp() { } // parseCliArgs parses CLI options and sets several important global variables. Call it early. -func parseCliArgs() { +func parseCliArgs() error { var createAdminName string var versionFlag bool @@ -42,43 +43,53 @@ func parseCliArgs() { flag.Parse() if versionFlag { - fmt.Println("Mycorrhiza Wiki", version.Long) + slog.Info("Running Mycorrhiza Wiki", "version", version.Long) os.Exit(0) } args := flag.Args() if len(args) == 0 { - log.Fatal("error: pass a wiki directory") + slog.Error("Pass a wiki directory") + return errors.New("wiki directory not passed") } wikiDir, err := filepath.Abs(args[0]) if err != nil { - log.Fatal(err) + slog.Error("Failed to take absolute filepath of wiki directory", + "path", args[0], "err", err) + return err } cfg.WikiDir = wikiDir if createAdminName != "" { - createAdminCommand(createAdminName) + if err := createAdminCommand(createAdminName); err != nil { + os.Exit(1) + } os.Exit(0) } + return nil } -func createAdminCommand(name string) { +func createAdminCommand(name string) error { if err := files.PrepareWikiRoot(); err != nil { - log.Fatal(err) + slog.Error("Failed to prepare wiki root", "err", err) + return err } cfg.UseAuth = true cfg.AllowRegistration = true - user2.InitUserDatabase() + user.InitUserDatabase() password, err := askPass("Password") if err != nil { - log.Fatal(err) + slog.Error("Failed to prompt password", "err", err) + return err } - if err := user2.Register(name, password, "admin", "local", true); err != nil { - log.Fatal(err) + if err := user.Register(name, password, "admin", "local", true); err != nil { + slog.Error("Failed to register admin", "err", err) + return err } + return nil } func askPass(prompt string) (string, error) { diff --git a/history/feed.go b/history/feed.go index 4906816..edd0dda 100644 --- a/history/feed.go +++ b/history/feed.go @@ -3,11 +3,12 @@ package history import ( "errors" "fmt" - "github.com/bouncepaw/mycorrhiza/internal/cfg" "net/url" "strings" "time" + "github.com/bouncepaw/mycorrhiza/internal/cfg" + "github.com/gorilla/feeds" ) diff --git a/history/history.go b/history/history.go index b889e80..0e77786 100644 --- a/history/history.go +++ b/history/history.go @@ -4,7 +4,7 @@ package history import ( "bytes" "fmt" - "log" + "log/slog" "os/exec" "path/filepath" "regexp" @@ -21,12 +21,14 @@ var renameMsgPattern = regexp.MustCompile(`^Rename ‘(.*)’ to ‘.*’`) var gitEnv = []string{"GIT_COMMITTER_NAME=wikimind", "GIT_COMMITTER_EMAIL=wikimind@mycorrhiza"} // Start finds git and initializes git credentials. -func Start() { +func Start() error { path, err := exec.LookPath("git") if err != nil { - log.Fatal("Could not find the git executable. Check your $PATH.") + slog.Error("Could not find the Git executable. Check your $PATH.") + return err } gitpath = path + return nil } // InitGitRepo checks a Git repository and initializes it if necessary. @@ -44,7 +46,7 @@ func InitGitRepo() { } } if !isGitRepo { - log.Println("Initializing Git repo at", files.HyphaeDir()) + slog.Info("Initializing Git repo", "path", files.HyphaeDir()) gitsh("init") gitsh("config", "core.quotePath", "false") } @@ -60,7 +62,7 @@ func gitsh(args ...string) (out bytes.Buffer, err error) { b, err := cmd.CombinedOutput() if err != nil { - log.Println("gitsh:", err) + slog.Info("Git command failed", "err", err, "output", string(b)) } return *bytes.NewBuffer(b), err } @@ -77,7 +79,9 @@ func silentGitsh(args ...string) (out bytes.Buffer, err error) { // Rename renames from `from` to `to` using `git mv`. func Rename(from, to string) error { - log.Println(util.ShorterPath(from), util.ShorterPath(to)) + slog.Info("Renaming file with git mv", + "from", util.ShorterPath(from), + "to", util.ShorterPath(to)) _, err := gitsh("mv", "--force", from, to) return err } diff --git a/history/histweb/histview.go b/history/histweb/histview.go index 196b998..7c7b3a4 100644 --- a/history/histweb/histview.go +++ b/history/histweb/histview.go @@ -4,19 +4,21 @@ package histweb import ( "embed" "fmt" - "github.com/bouncepaw/mycorrhiza/history" - "github.com/bouncepaw/mycorrhiza/internal/cfg" - "github.com/bouncepaw/mycorrhiza/internal/files" - hyphae2 "github.com/bouncepaw/mycorrhiza/internal/hyphae" - "github.com/bouncepaw/mycorrhiza/util" - viewutil2 "github.com/bouncepaw/mycorrhiza/web/viewutil" - "github.com/gorilla/mux" "html/template" - "log" + "log/slog" "net/http" "path/filepath" "strconv" "strings" + + "github.com/bouncepaw/mycorrhiza/history" + "github.com/bouncepaw/mycorrhiza/internal/cfg" + "github.com/bouncepaw/mycorrhiza/internal/files" + "github.com/bouncepaw/mycorrhiza/internal/hyphae" + "github.com/bouncepaw/mycorrhiza/util" + "github.com/bouncepaw/mycorrhiza/web/viewutil" + + "github.com/gorilla/mux" ) func InitHandlers(rtr *mux.Router) { @@ -30,9 +32,9 @@ func InitHandlers(rtr *mux.Router) { rtr.HandleFunc("/recent-changes-atom", handlerRecentChangesAtom) rtr.HandleFunc("/recent-changes-json", handlerRecentChangesJSON) - chainPrimitiveDiff = viewutil2.CopyEnRuWith(fs, "view_primitive_diff.html", ruTranslation) - chainRecentChanges = viewutil2.CopyEnRuWith(fs, "view_recent_changes.html", ruTranslation) - chainHistory = viewutil2.CopyEnRuWith(fs, "view_history.html", ruTranslation) + chainPrimitiveDiff = viewutil.CopyEnRuWith(fs, "view_primitive_diff.html", ruTranslation) + chainRecentChanges = viewutil.CopyEnRuWith(fs, "view_recent_changes.html", ruTranslation) + chainHistory = viewutil.CopyEnRuWith(fs, "view_history.html", ruTranslation) } func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) { @@ -45,12 +47,12 @@ func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) { } var ( mycoFilePath string - h = hyphae2.ByName(util.CanonicalName(slug)) + h = hyphae.ByName(util.CanonicalName(slug)) ) switch h := h.(type) { - case hyphae2.ExistingHypha: + case hyphae.ExistingHypha: mycoFilePath = h.TextFilePath() - case *hyphae2.EmptyHypha: + case *hyphae.EmptyHypha: mycoFilePath = filepath.Join(files.HyphaeDir(), h.CanonicalName()+".myco") } text, err := history.PrimitiveDiffAtRevision(mycoFilePath, revHash) @@ -58,7 +60,7 @@ func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - primitiveDiff(viewutil2.MetaFrom(w, rq), h, revHash, text) + primitiveDiff(viewutil.MetaFrom(w, rq), h, revHash, text) } // handlerRecentChanges displays the /recent-changes/ page. @@ -68,7 +70,7 @@ func handlerRecentChanges(w http.ResponseWriter, rq *http.Request) { if editCount > 100 { return } - recentChanges(viewutil2.MetaFrom(w, rq), editCount, history.RecentChanges(editCount)) + recentChanges(viewutil.MetaFrom(w, rq), editCount, history.RecentChanges(editCount)) } // handlerHistory lists all revisions of a hypha. @@ -81,9 +83,11 @@ func handlerHistory(w http.ResponseWriter, rq *http.Request) { if err == nil { list = history.WithRevisions(hyphaName, revs) } - log.Println("Found", len(revs), "revisions for", hyphaName) - historyView(viewutil2.MetaFrom(w, rq), hyphaName, list) + // TODO: extra log, not needed? + slog.Info("Found revisions", "hyphaName", hyphaName, "n", len(revs), "err", err) + + historyView(viewutil.MetaFrom(w, rq), hyphaName, list) } // genericHandlerOfFeeds is a helper function for the web feed handlers. @@ -135,20 +139,20 @@ var ( {{define "n recent changes"}}{{.}} свеж{{if eq . 1}}ая правка{{else if le . 4}}их правок{{else}}их правок{{end}}{{end}} {{define "recent empty"}}Правки не найдены.{{end}} ` - chainPrimitiveDiff, chainRecentChanges, chainHistory viewutil2.Chain + chainPrimitiveDiff, chainRecentChanges, chainHistory viewutil.Chain ) type recentChangesData struct { - *viewutil2.BaseData + *viewutil.BaseData EditCount int Changes []history.Revision UserHypha string Stops []int } -func recentChanges(meta viewutil2.Meta, editCount int, changes []history.Revision) { - viewutil2.ExecutePage(meta, chainRecentChanges, recentChangesData{ - BaseData: &viewutil2.BaseData{}, +func recentChanges(meta viewutil.Meta, editCount int, changes []history.Revision) { + viewutil.ExecutePage(meta, chainRecentChanges, recentChangesData{ + BaseData: &viewutil.BaseData{}, EditCount: editCount, Changes: changes, UserHypha: cfg.UserHypha, @@ -157,13 +161,13 @@ func recentChanges(meta viewutil2.Meta, editCount int, changes []history.Revisio } type primitiveDiffData struct { - *viewutil2.BaseData + *viewutil.BaseData HyphaName string Hash string Text template.HTML } -func primitiveDiff(meta viewutil2.Meta, h hyphae2.Hypha, hash, text string) { +func primitiveDiff(meta viewutil.Meta, h hyphae.Hypha, hash, text string) { hunks := history.SplitPrimitiveDiff(text) if len(hunks) > 0 { var buf strings.Builder @@ -198,8 +202,8 @@ func primitiveDiff(meta viewutil2.Meta, h hyphae2.Hypha, hash, text string) { text = fmt.Sprintf( `
%s`, text)
}
- viewutil2.ExecutePage(meta, chainPrimitiveDiff, primitiveDiffData{
- BaseData: &viewutil2.BaseData{},
+ viewutil.ExecutePage(meta, chainPrimitiveDiff, primitiveDiffData{
+ BaseData: &viewutil.BaseData{},
HyphaName: h.CanonicalName(),
Hash: hash,
Text: template.HTML(text),
@@ -207,14 +211,14 @@ func primitiveDiff(meta viewutil2.Meta, h hyphae2.Hypha, hash, text string) {
}
type historyData struct {
- *viewutil2.BaseData
+ *viewutil.BaseData
HyphaName string
Contents string
}
-func historyView(meta viewutil2.Meta, hyphaName, contents string) {
- viewutil2.ExecutePage(meta, chainHistory, historyData{
- BaseData: &viewutil2.BaseData{
+func historyView(meta viewutil.Meta, hyphaName, contents string) {
+ viewutil.ExecutePage(meta, chainHistory, historyData{
+ BaseData: &viewutil.BaseData{
Addr: "/history/" + util.CanonicalName(hyphaName),
},
HyphaName: hyphaName,
diff --git a/history/operations.go b/history/operations.go
index 0f9eb80..71cfbd5 100644
--- a/history/operations.go
+++ b/history/operations.go
@@ -4,11 +4,11 @@ package history
// Things related to writing history.
import (
"fmt"
- "github.com/bouncepaw/mycorrhiza/internal/user"
"os"
"path/filepath"
"sync"
+ "github.com/bouncepaw/mycorrhiza/internal/user"
"github.com/bouncepaw/mycorrhiza/util"
)
diff --git a/history/revision.go b/history/revision.go
index 7f04309..9f5becb 100644
--- a/history/revision.go
+++ b/history/revision.go
@@ -2,7 +2,8 @@ package history
import (
"fmt"
- "log"
+ "log/slog"
+ "os"
"regexp"
"strconv"
"strings"
@@ -11,9 +12,11 @@ import (
"github.com/bouncepaw/mycorrhiza/internal/files"
)
-// Revision represents a revision, duh. Hash is usually short. Username is extracted from email.
+// Revision represents a revision of a hypha.
type Revision struct {
- Hash string
+ // Hash is usually short.
+ Hash string
+ // Username is extracted from email.
Username string
Time time.Time
Message string
@@ -71,7 +74,9 @@ func (stream *recentChangesStream) next(n int) []Revision {
res, err := gitLog(args...)
if err != nil {
- log.Fatal(err)
+ // TODO: return error
+ slog.Error("Failed to git log", "err", err)
+ os.Exit(1)
}
if len(res) != 0 {
stream.currHash = res[len(res)-1].Hash
@@ -103,14 +108,14 @@ func (stream recentChangesStream) iterator() func() (Revision, bool) {
func RecentChanges(n int) []Revision {
stream := newRecentChangesStream()
revs := stream.next(n)
- log.Printf("Found %d recent changes", len(revs))
+ slog.Info("Found recent changes", "n", len(revs))
return revs
}
// Revisions returns slice of revisions for the given hypha name, ordered most recent first.
func Revisions(hyphaName string) ([]Revision, error) {
revs, err := gitLog("--", hyphaName+".*")
- log.Printf("Found %d revisions for ‘%s’\n", len(revs), hyphaName)
+ slog.Info("Found revisions", "hyphaName", hyphaName, "n", len(revs), "err", err)
return revs, err
}
diff --git a/httpd.go b/httpd.go
index ee2af1e..71bf815 100644
--- a/httpd.go
+++ b/httpd.go
@@ -1,16 +1,18 @@
package main
import (
- "github.com/bouncepaw/mycorrhiza/internal/cfg"
- "log"
+ "errors"
+ "log/slog"
"net"
"net/http"
"os"
"strings"
"time"
+
+ "github.com/bouncepaw/mycorrhiza/internal/cfg"
)
-func serveHTTP(handler http.Handler) {
+func serveHTTP(handler http.Handler) (err error) {
server := &http.Server{
ReadTimeout: 300 * time.Second,
WriteTimeout: 300 * time.Second,
@@ -19,35 +21,51 @@ func serveHTTP(handler http.Handler) {
}
if strings.HasPrefix(cfg.ListenAddr, "/") {
- startUnixSocketServer(server, cfg.ListenAddr)
+ err = startUnixSocketServer(server, cfg.ListenAddr)
} else {
server.Addr = cfg.ListenAddr
- startHTTPServer(server)
+ err = startHTTPServer(server)
}
+ return err
}
-func startUnixSocketServer(server *http.Server, socketFile string) {
- os.Remove(socketFile)
-
- listener, err := net.Listen("unix", socketFile)
+func startUnixSocketServer(server *http.Server, socketPath string) error {
+ err := os.Remove(socketPath)
if err != nil {
- log.Fatalf("Failed to start a server: %v", err)
- }
- defer listener.Close()
-
- if err := os.Chmod(socketFile, 0666); err != nil {
- log.Fatalf("Failed to set socket permissions: %v", err)
+ return err
}
- log.Printf("Listening on Unix socket %s", cfg.ListenAddr)
- if err := server.Serve(listener); err != http.ErrServerClosed {
- log.Fatalf("Failed to start a server: %v", err)
+ listener, err := net.Listen("unix", socketPath)
+ if err != nil {
+ slog.Error("Failed to start the server", "err", err)
+ return err
}
+ defer func(listener net.Listener) {
+ _ = listener.Close()
+ }(listener)
+
+ if err := os.Chmod(socketPath, 0666); err != nil {
+ slog.Error("Failed to set socket permissions", "err", err)
+ return err
+ }
+
+ slog.Info("Listening Unix socket", "addr", socketPath)
+
+ if err := server.Serve(listener); !errors.Is(err, http.ErrServerClosed) {
+ slog.Error("Failed to start the server", "err", err)
+ return err
+ }
+
+ return nil
}
-func startHTTPServer(server *http.Server) {
- log.Printf("Listening on %s", server.Addr)
- if err := server.ListenAndServe(); err != http.ErrServerClosed {
- log.Fatalf("Failed to start a server: %v", err)
+func startHTTPServer(server *http.Server) error {
+ slog.Info("Listening over HTTP", "addr", server.Addr)
+
+ if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
+ slog.Error("Failed to start the server", "err", err)
+ return err
}
+
+ return nil
}
diff --git a/hypview/hypview.go b/hypview/hypview.go
index 6881768..0843534 100644
--- a/hypview/hypview.go
+++ b/hypview/hypview.go
@@ -3,7 +3,7 @@ package hypview
import (
"embed"
"html/template"
- "log"
+ "log/slog"
"strings"
"github.com/bouncepaw/mycorrhiza/internal/backlinks"
@@ -66,7 +66,7 @@ func NaviTitle(meta viewutil.Meta, hyphaName string) template.HTML {
HomeHypha: cfg.HomeHypha,
})
if err != nil {
- log.Println(err)
+ slog.Error("Failed to render NaviTitle properly; using nevertheless", "err", err)
}
return template.HTML(buf.String())
}
diff --git a/internal/backlinks/backlinks.go b/internal/backlinks/backlinks.go
index f2e235a..ec9fe9d 100644
--- a/internal/backlinks/backlinks.go
+++ b/internal/backlinks/backlinks.go
@@ -2,8 +2,8 @@
package backlinks
import (
- hyphae2 "github.com/bouncepaw/mycorrhiza/internal/hyphae"
- "log"
+ "github.com/bouncepaw/mycorrhiza/internal/hyphae"
+ "log/slog"
"os"
"sort"
@@ -14,7 +14,7 @@ import (
func yieldHyphaBacklinks(hyphaName string) <-chan string {
hyphaName = util.CanonicalName(hyphaName)
out := make(chan string)
- sorted := hyphae2.PathographicSort(out)
+ sorted := hyphae.PathographicSort(out)
go func() {
backlinks, exists := backlinkIndex[hyphaName]
if exists {
@@ -43,7 +43,7 @@ var backlinkIndex = make(map[string]linkSet)
// IndexBacklinks traverses all text hyphae, extracts links from them and forms an initial index. Call it when indexing and reindexing hyphae.
func IndexBacklinks() {
// It is safe to ignore the mutex, because there is only one worker.
- for h := range hyphae2.FilterHyphaeWithText(hyphae2.YieldExistingHyphae()) {
+ for h := range hyphae.FilterHyphaeWithText(hyphae.YieldExistingHyphae()) {
foundLinks := extractHyphaLinksFromContent(h.CanonicalName(), fetchText(h))
for _, link := range foundLinks {
if _, exists := backlinkIndex[link]; !exists {
@@ -72,7 +72,7 @@ func BacklinksFor(hyphaName string) []string {
func Orphans() []string {
var orphans []string
- for h := range hyphae2.YieldExistingHyphae() {
+ for h := range hyphae.YieldExistingHyphae() {
if BacklinksCount(h.CanonicalName()) == 0 {
orphans = append(orphans, h.CanonicalName())
}
@@ -92,14 +92,14 @@ func toLinkSet(xs []string) linkSet {
return result
}
-func fetchText(h hyphae2.Hypha) string {
+func fetchText(h hyphae.Hypha) string {
var path string
switch h := h.(type) {
- case *hyphae2.EmptyHypha:
+ case *hyphae.EmptyHypha:
return ""
- case *hyphae2.TextualHypha:
+ case *hyphae.TextualHypha:
path = h.TextFilePath()
- case *hyphae2.MediaHypha:
+ case *hyphae.MediaHypha:
if !h.HasTextFile() {
return ""
}
@@ -108,7 +108,7 @@ func fetchText(h hyphae2.Hypha) string {
text, err := os.ReadFile(path)
if err != nil {
- log.Println(err)
+ slog.Error("Failed to read file", "path", path, "err", err, "hyphaName", h.CanonicalName())
return ""
}
return string(text)
diff --git a/internal/backlinks/hooks.go b/internal/backlinks/hooks.go
index ef65952..60a3c50 100644
--- a/internal/backlinks/hooks.go
+++ b/internal/backlinks/hooks.go
@@ -1,12 +1,13 @@
package backlinks
import (
+ "github.com/bouncepaw/mycorrhiza/internal/hyphae"
+ "github.com/bouncepaw/mycorrhiza/mycoopts"
+
"git.sr.ht/~bouncepaw/mycomarkup/v5"
"git.sr.ht/~bouncepaw/mycomarkup/v5/links"
"git.sr.ht/~bouncepaw/mycomarkup/v5/mycocontext"
"git.sr.ht/~bouncepaw/mycomarkup/v5/tools"
- "github.com/bouncepaw/mycorrhiza/internal/hyphae"
- "github.com/bouncepaw/mycorrhiza/mycoopts"
)
// UpdateBacklinksAfterEdit is a creation/editing hook for backlinks index
diff --git a/internal/categories/files.go b/internal/categories/files.go
index f4e4fb3..7c80546 100644
--- a/internal/categories/files.go
+++ b/internal/categories/files.go
@@ -2,7 +2,7 @@ package categories
import (
"encoding/json"
- "log"
+ "log/slog"
"os"
"slices"
"sort"
@@ -16,12 +16,11 @@ var categoryToHyphae = map[string]*categoryNode{}
var hyphaToCategories = map[string]*hyphaNode{}
// Init initializes the category system. Call it after the Structure is initialized. This function might terminate the program in case of a bad mood or filesystem faults.
-func Init() {
- var (
- record, err = readCategoriesFromDisk()
- )
+func Init() error {
+ record, err := readCategoriesFromDisk()
if err != nil {
- log.Fatalln(err)
+ slog.Error("Failed to read categories from disk", "err", err)
+ return err
}
for _, cat := range record.Categories {
@@ -46,7 +45,8 @@ func Init() {
}
}
- log.Println("Found", len(categoryToHyphae), "categories")
+ slog.Info("Indexed categories", "n", len(categoryToHyphae))
+ return nil
}
type categoryNode struct {
@@ -123,9 +123,7 @@ func readCategoriesFromDisk() (catFileRecord, error) {
var fileMutex sync.Mutex
func saveToDisk() {
- var (
- record catFileRecord
- )
+ var record catFileRecord
for name, node := range categoryToHyphae {
record.Categories = append(record.Categories, catRecord{
Name: name,
@@ -134,13 +132,16 @@ func saveToDisk() {
}
data, err := json.MarshalIndent(record, "", "\t")
if err != nil {
- log.Fatalln(err) // Better fail now, than later
+ slog.Error("Failed to marshal categories record", "err", err)
+ os.Exit(1) // Better fail now, than later
}
+
// TODO: make the data safer somehow?? Back it up before overwriting?
fileMutex.Lock()
err = os.WriteFile(files.CategoriesJSON(), data, 0666)
if err != nil {
- log.Fatalln(err)
+ slog.Error("Failed to write categories.json", "err", err)
+ os.Exit(1)
}
fileMutex.Unlock()
}
diff --git a/internal/files/files.go b/internal/files/files.go
index bb82cff..e6fa383 100644
--- a/internal/files/files.go
+++ b/internal/files/files.go
@@ -2,11 +2,12 @@
package files
import (
- "github.com/bouncepaw/mycorrhiza/internal/cfg"
- "github.com/bouncepaw/mycorrhiza/web/static"
"io"
"os"
"path/filepath"
+
+ "github.com/bouncepaw/mycorrhiza/internal/cfg"
+ "github.com/bouncepaw/mycorrhiza/web/static"
)
var paths struct {
diff --git a/internal/hyphae/existing_hypha.go b/internal/hyphae/existing_hypha.go
index 8b6cf7f..0301137 100644
--- a/internal/hyphae/existing_hypha.go
+++ b/internal/hyphae/existing_hypha.go
@@ -1,9 +1,10 @@
package hyphae
import (
- "github.com/bouncepaw/mycorrhiza/util"
"os"
"path/filepath"
+
+ "github.com/bouncepaw/mycorrhiza/util"
)
// ExistingHypha is not EmptyHypha. *MediaHypha and *TextualHypha implement this interface.
diff --git a/internal/hyphae/files.go b/internal/hyphae/files.go
index 9be35a2..3c499bf 100644
--- a/internal/hyphae/files.go
+++ b/internal/hyphae/files.go
@@ -1,11 +1,11 @@
package hyphae
import (
- "github.com/bouncepaw/mycorrhiza/internal/mimetype"
- "log"
"log/slog"
"os"
"path/filepath"
+
+ "github.com/bouncepaw/mycorrhiza/internal/mimetype"
)
// Index finds all hypha files in the full `path` and saves them to the hypha storage.
@@ -51,7 +51,7 @@ func Index(path string) {
}
}
}
- log.Println("Indexed", Count(), "hyphae")
+ slog.Info("Indexed hyphae", "n", Count())
}
// indexHelper finds all hypha files in the full `path` and sends them to the
@@ -60,7 +60,8 @@ func Index(path string) {
func indexHelper(path string, nestLevel uint, ch chan ExistingHypha) {
nodes, err := os.ReadDir(path)
if err != nil {
- log.Fatal(err)
+ slog.Error("Failed to read directory", "path", path, "err", err)
+ os.Exit(1)
}
for _, node := range nodes {
diff --git a/internal/migration/headings.go b/internal/migration/headings.go
index fb8f3cd..1de4a35 100644
--- a/internal/migration/headings.go
+++ b/internal/migration/headings.go
@@ -1,11 +1,13 @@
package migration
import (
- "git.sr.ht/~bouncepaw/mycomarkup/v5/tools"
- "github.com/bouncepaw/mycorrhiza/internal/files"
"io/ioutil"
- "log"
+ "log/slog"
"os"
+
+ "github.com/bouncepaw/mycorrhiza/internal/files"
+
+ "git.sr.ht/~bouncepaw/mycomarkup/v5/tools"
)
var headingMarkerPath string
@@ -29,7 +31,8 @@ func shouldMigrateHeadings() bool {
return true
}
if err != nil {
- log.Fatalln("When checking if heading migration is needed:", err.Error())
+ slog.Error("Failed to check if heading migration is needed", "err", err)
+ os.Exit(1)
}
_ = file.Close()
return false
@@ -42,6 +45,7 @@ func createHeadingMarker() {
0766,
)
if err != nil {
- log.Fatalln(err)
+ slog.Error("Failed to create heading migration marker", "err", err)
+ os.Exit(1)
}
}
diff --git a/internal/migration/migration.go b/internal/migration/migration.go
index d3f945f..0bcad88 100644
--- a/internal/migration/migration.go
+++ b/internal/migration/migration.go
@@ -8,14 +8,14 @@
package migration
import (
- "github.com/bouncepaw/mycorrhiza/internal/user"
"io"
- "log"
+ "log/slog"
"os"
"strings"
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/internal/hyphae"
+ "github.com/bouncepaw/mycorrhiza/internal/user"
)
func genericLineMigrator(
@@ -37,7 +37,8 @@ func genericLineMigrator(
file, err := os.OpenFile(hypha.TextFilePath(), os.O_RDWR, 0766)
if err != nil {
hop.WithErrAbort(err)
- log.Fatal("Something went wrong when opening ", hypha.TextFilePath(), ": ", err.Error())
+ slog.Error("Failed to open text part file", "path", hypha.TextFilePath(), "err", err)
+ os.Exit(1)
}
var buf strings.Builder
@@ -45,7 +46,7 @@ func genericLineMigrator(
if err != nil {
hop.WithErrAbort(err)
_ = file.Close()
- log.Fatal("Something went wrong when reading ", hypha.TextFilePath(), ": ", err.Error())
+ slog.Error("Failed to read text part file", "path", hypha.TextFilePath(), "err", err)
}
var (
@@ -59,21 +60,24 @@ func genericLineMigrator(
if err != nil {
hop.WithErrAbort(err)
_ = file.Close()
- log.Fatal("Something went wrong when truncating ", hypha.TextFilePath(), ": ", err.Error())
+ slog.Error("Failed to truncate text part file", "path", hypha.TextFilePath(), "err", err)
+ os.Exit(1)
}
_, err = file.Seek(0, 0)
if err != nil {
hop.WithErrAbort(err)
_ = file.Close()
- log.Fatal("Something went wrong when seeking in ", hypha.TextFilePath(), ": ", err.Error())
+ slog.Error("Failed to seek in text part file", "path", hypha.TextFilePath(), "err", err)
+ os.Exit(1)
}
_, err = file.WriteString(newText)
if err != nil {
hop.WithErrAbort(err)
_ = file.Close()
- log.Fatal("Something went wrong when writing to ", hypha.TextFilePath(), ": ", err.Error())
+ slog.Error("Failed to write to text part file", "path", hypha.TextFilePath(), "err", err)
+ os.Exit(1)
}
}
_ = file.Close()
@@ -85,8 +89,8 @@ func genericLineMigrator(
}
if hop.WithFiles(mycoFiles...).Apply().HasErrors() {
- log.Fatal(commitErrorMessage, hop.FirstErrorText())
+ slog.Error(commitErrorMessage + hop.FirstErrorText())
}
- log.Println("Migrated", len(mycoFiles), "Mycomarkup documents")
+ slog.Info("Migrated Mycomarkup documents", "n", len(mycoFiles))
}
diff --git a/internal/migration/rockets.go b/internal/migration/rockets.go
index 5dc050b..dc99fce 100644
--- a/internal/migration/rockets.go
+++ b/internal/migration/rockets.go
@@ -1,11 +1,13 @@
package migration
import (
- "git.sr.ht/~bouncepaw/mycomarkup/v5/tools"
- "github.com/bouncepaw/mycorrhiza/internal/files"
"io/ioutil"
- "log"
+ "log/slog"
"os"
+
+ "github.com/bouncepaw/mycorrhiza/internal/files"
+
+ "git.sr.ht/~bouncepaw/mycomarkup/v5/tools"
)
var rocketMarkerPath string
@@ -33,7 +35,8 @@ func shouldMigrateRockets() bool {
return true
}
if err != nil {
- log.Fatalln("When checking if rocket migration is needed:", err.Error())
+ slog.Error("Failed to check if rocket migration is needed", "err", err)
+ os.Exit(1)
}
_ = file.Close()
return false
@@ -46,6 +49,7 @@ func createRocketLinkMarker() {
0766,
)
if err != nil {
- log.Fatalln(err)
+ slog.Error("Failed to create rocket link migration marker")
+ os.Exit(1)
}
}
diff --git a/internal/shroom/can.go b/internal/shroom/can.go
index c9d1f3d..8a4ccc3 100644
--- a/internal/shroom/can.go
+++ b/internal/shroom/can.go
@@ -2,23 +2,23 @@ package shroom
import (
"errors"
- hyphae2 "github.com/bouncepaw/mycorrhiza/internal/hyphae"
- "github.com/bouncepaw/mycorrhiza/internal/user"
+ "github.com/bouncepaw/mycorrhiza/internal/hyphae"
+ "github.com/bouncepaw/mycorrhiza/internal/user"
"github.com/bouncepaw/mycorrhiza/l18n"
)
// TODO: get rid of this abomination
func canFactory(
- rejectLogger func(hyphae2.Hypha, *user.User, string),
+ rejectLogger func(hyphae.Hypha, *user.User, string),
action string,
- dispatcher func(hyphae2.Hypha, *user.User, *l18n.Localizer) (string, string),
+ dispatcher func(hyphae.Hypha, *user.User, *l18n.Localizer) (string, string),
noRightsMsg string,
notExistsMsg string,
mustExist bool,
-) func(*user.User, hyphae2.Hypha, *l18n.Localizer) error {
- return func(u *user.User, h hyphae2.Hypha, lc *l18n.Localizer) error {
+) func(*user.User, hyphae.Hypha, *l18n.Localizer) error {
+ return func(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) error {
if !u.CanProceed(action) {
rejectLogger(h, u, "no rights")
return errors.New(noRightsMsg)
@@ -26,7 +26,7 @@ func canFactory(
if mustExist {
switch h.(type) {
- case *hyphae2.EmptyHypha:
+ case *hyphae.EmptyHypha:
rejectLogger(h, u, "does not exist")
return errors.New(notExistsMsg)
}
diff --git a/internal/shroom/delete.go b/internal/shroom/delete.go
index 701fd0c..f07df9d 100644
--- a/internal/shroom/delete.go
+++ b/internal/shroom/delete.go
@@ -2,29 +2,30 @@ package shroom
import (
"fmt"
+
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/internal/backlinks"
"github.com/bouncepaw/mycorrhiza/internal/categories"
- hyphae2 "github.com/bouncepaw/mycorrhiza/internal/hyphae"
+ "github.com/bouncepaw/mycorrhiza/internal/hyphae"
"github.com/bouncepaw/mycorrhiza/internal/user"
)
// Delete deletes the hypha and makes a history record about that.
-func Delete(u *user.User, h hyphae2.ExistingHypha) error {
+func Delete(u *user.User, h hyphae.ExistingHypha) error {
hop := history.
Operation(history.TypeDeleteHypha).
WithMsg(fmt.Sprintf("Delete ‘%s’", h.CanonicalName())).
WithUser(u)
- originalText, _ := hyphae2.FetchMycomarkupFile(h)
+ originalText, _ := hyphae.FetchMycomarkupFile(h)
switch h := h.(type) {
- case *hyphae2.MediaHypha:
+ case *hyphae.MediaHypha:
if h.HasTextFile() {
hop.WithFilesRemoved(h.MediaFilePath(), h.TextFilePath())
} else {
hop.WithFilesRemoved(h.MediaFilePath())
}
- case *hyphae2.TextualHypha:
+ case *hyphae.TextualHypha:
hop.WithFilesRemoved(h.TextFilePath())
}
if hop.Apply().HasErrors() {
@@ -32,6 +33,6 @@ func Delete(u *user.User, h hyphae2.ExistingHypha) error {
}
backlinks.UpdateBacklinksAfterDelete(h, originalText)
categories.RemoveHyphaFromAllCategories(h.CanonicalName())
- hyphae2.DeleteHypha(h)
+ hyphae.DeleteHypha(h)
return nil
}
diff --git a/internal/shroom/header_links.go b/internal/shroom/header_links.go
index dd3ff1b..af28f75 100644
--- a/internal/shroom/header_links.go
+++ b/internal/shroom/header_links.go
@@ -1,22 +1,24 @@
package shroom
import (
+ "os"
+
+ "github.com/bouncepaw/mycorrhiza/internal/cfg"
+ "github.com/bouncepaw/mycorrhiza/internal/hyphae"
+ "github.com/bouncepaw/mycorrhiza/mycoopts"
+ "github.com/bouncepaw/mycorrhiza/web/viewutil"
+
"git.sr.ht/~bouncepaw/mycomarkup/v5"
"git.sr.ht/~bouncepaw/mycomarkup/v5/blocks"
"git.sr.ht/~bouncepaw/mycomarkup/v5/mycocontext"
- "github.com/bouncepaw/mycorrhiza/internal/cfg"
- hyphae2 "github.com/bouncepaw/mycorrhiza/internal/hyphae"
- "github.com/bouncepaw/mycorrhiza/mycoopts"
- "github.com/bouncepaw/mycorrhiza/web/viewutil"
- "os"
)
// SetHeaderLinks initializes header links by reading the configured hypha, if there is any, or resorting to default values.
func SetHeaderLinks() {
- switch userLinksHypha := hyphae2.ByName(cfg.HeaderLinksHypha).(type) {
- case *hyphae2.EmptyHypha:
+ switch userLinksHypha := hyphae.ByName(cfg.HeaderLinksHypha).(type) {
+ case *hyphae.EmptyHypha:
setDefaultHeaderLinks()
- case hyphae2.ExistingHypha:
+ case hyphae.ExistingHypha:
contents, err := os.ReadFile(userLinksHypha.TextFilePath())
if err != nil || len(contents) == 0 {
setDefaultHeaderLinks()
diff --git a/internal/shroom/log.go b/internal/shroom/log.go
index 2aef825..535dcaf 100644
--- a/internal/shroom/log.go
+++ b/internal/shroom/log.go
@@ -1,20 +1,36 @@
package shroom
import (
+ "log/slog"
+
"github.com/bouncepaw/mycorrhiza/internal/hyphae"
"github.com/bouncepaw/mycorrhiza/internal/user"
- "log"
)
func rejectRenameLog(h hyphae.Hypha, u *user.User, errmsg string) {
- log.Printf("Reject rename ‘%s’ by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
+ slog.Info("Reject rename",
+ "hyphaName", h.CanonicalName(),
+ "username", u.Name,
+ "errmsg", errmsg)
}
+
func rejectRemoveMediaLog(h hyphae.Hypha, u *user.User, errmsg string) {
- log.Printf("Reject remove media ‘%s’ by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
+ slog.Info("Reject remove media",
+ "hyphaName", h.CanonicalName(),
+ "username", u.Name,
+ "errmsg", errmsg)
}
+
func rejectEditLog(h hyphae.Hypha, u *user.User, errmsg string) {
- log.Printf("Reject edit ‘%s’ by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
+ slog.Info("Reject edit",
+ "hyphaName", h.CanonicalName(),
+ "username", u.Name,
+ "errmsg", errmsg)
}
+
func rejectUploadMediaLog(h hyphae.Hypha, u *user.User, errmsg string) {
- log.Printf("Reject upload media ‘%s’ by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
+ slog.Info("Reject upload media",
+ "hyphaName", h.CanonicalName(),
+ "username", u.Name,
+ "errmsg", errmsg)
}
diff --git a/internal/shroom/rename.go b/internal/shroom/rename.go
index 3aeeeb7..6150c92 100644
--- a/internal/shroom/rename.go
+++ b/internal/shroom/rename.go
@@ -3,36 +3,36 @@ package shroom
import (
"errors"
"fmt"
- "github.com/bouncepaw/mycorrhiza/internal/backlinks"
- "github.com/bouncepaw/mycorrhiza/internal/categories"
- "github.com/bouncepaw/mycorrhiza/internal/cfg"
- "github.com/bouncepaw/mycorrhiza/internal/files"
- hyphae2 "github.com/bouncepaw/mycorrhiza/internal/hyphae"
- "github.com/bouncepaw/mycorrhiza/internal/user"
"path"
"path/filepath"
"regexp"
"strings"
"github.com/bouncepaw/mycorrhiza/history"
+ "github.com/bouncepaw/mycorrhiza/internal/backlinks"
+ "github.com/bouncepaw/mycorrhiza/internal/categories"
+ "github.com/bouncepaw/mycorrhiza/internal/cfg"
+ "github.com/bouncepaw/mycorrhiza/internal/files"
+ "github.com/bouncepaw/mycorrhiza/internal/hyphae"
+ "github.com/bouncepaw/mycorrhiza/internal/user"
"github.com/bouncepaw/mycorrhiza/util"
)
// Rename renames the old hypha to the new name and makes a history record about that. Call if and only if the user has the permission to rename.
-func Rename(oldHypha hyphae2.ExistingHypha, newName string, recursive bool, leaveRedirections bool, u *user.User) error {
+func Rename(oldHypha hyphae.ExistingHypha, newName string, recursive bool, leaveRedirections bool, u *user.User) error {
// * bouncepaw hates this function and related renaming functions
if newName == "" {
rejectRenameLog(oldHypha, u, "no new name given")
return errors.New("ui.rename_noname_tip")
}
- if !hyphae2.IsValidName(newName) {
+ if !hyphae.IsValidName(newName) {
rejectRenameLog(oldHypha, u, fmt.Sprintf("new name ‘%s’ invalid", newName))
return errors.New("ui.rename_badname_tip") // FIXME: There is a bug related to this.
}
- switch targetHypha := hyphae2.ByName(newName); targetHypha.(type) {
- case hyphae2.ExistingHypha:
+ switch targetHypha := hyphae.ByName(newName); targetHypha.(type) {
+ case hyphae.ExistingHypha:
if targetHypha.CanonicalName() == oldHypha.CanonicalName() {
return nil
}
@@ -81,7 +81,7 @@ func Rename(oldHypha hyphae2.ExistingHypha, newName string, recursive bool, leav
oldName = h.CanonicalName()
newName = re.ReplaceAllString(oldName, newName)
)
- hyphae2.RenameHyphaTo(h, newName, replaceName)
+ hyphae.RenameHyphaTo(h, newName, replaceName)
backlinks.UpdateBacklinksAfterRename(h, oldName)
categories.RenameHyphaInAllCategories(oldName, newName)
if leaveRedirections {
@@ -104,12 +104,12 @@ const redirectionTemplate = `=> %[1]s | 👁️➡️ %[2]s
func leaveRedirection(oldName, newName string, hop *history.Op) error {
var (
text = fmt.Sprintf(redirectionTemplate, newName, util.BeautifulName(newName))
- emptyHypha = hyphae2.ByName(oldName)
+ emptyHypha = hyphae.ByName(oldName)
)
switch emptyHypha := emptyHypha.(type) {
- case *hyphae2.EmptyHypha:
- h := hyphae2.ExtendEmptyToTextual(emptyHypha, filepath.Join(files.HyphaeDir(), oldName+".myco"))
- hyphae2.Insert(h)
+ case *hyphae.EmptyHypha:
+ h := hyphae.ExtendEmptyToTextual(emptyHypha, filepath.Join(files.HyphaeDir(), oldName+".myco"))
+ hyphae.Insert(h)
categories.AddHyphaToCategory(oldName, cfg.RedirectionCategory)
defer backlinks.UpdateBacklinksAfterEdit(h, "")
return writeTextToDisk(h, []byte(text), hop)
@@ -118,15 +118,15 @@ func leaveRedirection(oldName, newName string, hop *history.Op) error {
}
}
-func findHyphaeToRename(superhypha hyphae2.ExistingHypha, recursive bool) []hyphae2.ExistingHypha {
- hyphaList := []hyphae2.ExistingHypha{superhypha}
+func findHyphaeToRename(superhypha hyphae.ExistingHypha, recursive bool) []hyphae.ExistingHypha {
+ hyphaList := []hyphae.ExistingHypha{superhypha}
if recursive {
- hyphaList = append(hyphaList, hyphae2.Subhyphae(superhypha)...)
+ hyphaList = append(hyphaList, hyphae.Subhyphae(superhypha)...)
}
return hyphaList
}
-func renamingPairs(hyphaeToRename []hyphae2.ExistingHypha, replaceName func(string) string) (map[string]string, error) {
+func renamingPairs(hyphaeToRename []hyphae.ExistingHypha, replaceName func(string) string) (map[string]string, error) {
var (
renameMap = make(map[string]string)
newNames = make([]string, len(hyphaeToRename))
@@ -138,12 +138,12 @@ func renamingPairs(hyphaeToRename []hyphae2.ExistingHypha, replaceName func(stri
renameMap[h.TextFilePath()] = replaceName(h.TextFilePath())
}
switch h := h.(type) {
- case *hyphae2.MediaHypha:
+ case *hyphae.MediaHypha:
renameMap[h.MediaFilePath()] = replaceName(h.MediaFilePath())
}
h.Unlock()
}
- if firstFailure, ok := hyphae2.AreFreeNames(newNames...); !ok {
+ if firstFailure, ok := hyphae.AreFreeNames(newNames...); !ok {
return nil, errors.New("Hypha " + firstFailure + " already exists")
}
return renameMap, nil
diff --git a/internal/shroom/search.go b/internal/shroom/search.go
index 57efad0..666752d 100644
--- a/internal/shroom/search.go
+++ b/internal/shroom/search.go
@@ -1,9 +1,9 @@
package shroom
import (
- "github.com/bouncepaw/mycorrhiza/internal/hyphae"
"strings"
+ "github.com/bouncepaw/mycorrhiza/internal/hyphae"
"github.com/bouncepaw/mycorrhiza/util"
)
diff --git a/internal/shroom/unattach.go b/internal/shroom/unattach.go
index 74b76b4..613cae3 100644
--- a/internal/shroom/unattach.go
+++ b/internal/shroom/unattach.go
@@ -2,14 +2,14 @@ package shroom
import (
"fmt"
- hyphae2 "github.com/bouncepaw/mycorrhiza/internal/hyphae"
- "github.com/bouncepaw/mycorrhiza/internal/user"
"github.com/bouncepaw/mycorrhiza/history"
+ "github.com/bouncepaw/mycorrhiza/internal/hyphae"
+ "github.com/bouncepaw/mycorrhiza/internal/user"
)
// RemoveMedia removes media from the media hypha and makes a history record about that. If it only had media, the hypha will be deleted. If it also had text, the hypha will become textual.
-func RemoveMedia(u *user.User, h *hyphae2.MediaHypha) error {
+func RemoveMedia(u *user.User, h *hyphae.MediaHypha) error {
hop := history.
Operation(history.TypeRemoveMedia).
WithFilesRemoved(h.MediaFilePath()).
@@ -24,9 +24,9 @@ func RemoveMedia(u *user.User, h *hyphae2.MediaHypha) error {
}
if h.HasTextFile() {
- hyphae2.Insert(hyphae2.ShrinkMediaToTextual(h))
+ hyphae.Insert(hyphae.ShrinkMediaToTextual(h))
} else {
- hyphae2.DeleteHypha(h)
+ hyphae.DeleteHypha(h)
}
return nil
}
diff --git a/internal/shroom/upload.go b/internal/shroom/upload.go
index a63c1ec..ff438a6 100644
--- a/internal/shroom/upload.go
+++ b/internal/shroom/upload.go
@@ -5,7 +5,7 @@ import (
"errors"
"fmt"
"io"
- "log"
+ "log/slog"
"mime/multipart"
"os"
"path/filepath"
@@ -201,7 +201,7 @@ func UploadBinary(h hyphae.Hypha, mime string, file multipart.File, u *user.User
if err := history.Rename(prevFilePath, uploadedFilePath); err != nil {
return err
}
- log.Printf("Move ‘%s’ to ‘%s’\n", prevFilePath, uploadedFilePath)
+ slog.Info("Move file", "from", prevFilePath, "to", uploadedFilePath)
h.SetMediaFilePath(uploadedFilePath)
}
}
diff --git a/internal/tree/tree.go b/internal/tree/tree.go
index 6dc171e..44f4dac 100644
--- a/internal/tree/tree.go
+++ b/internal/tree/tree.go
@@ -2,13 +2,14 @@ package tree
import (
"fmt"
- "github.com/bouncepaw/mycorrhiza/internal/hyphae"
- "github.com/bouncepaw/mycorrhiza/util"
"html/template"
"io"
"path"
"sort"
"strings"
+
+ "github.com/bouncepaw/mycorrhiza/internal/hyphae"
+ "github.com/bouncepaw/mycorrhiza/util"
)
// Tree returns the subhypha matrix as HTML and names of the next and previous hyphae (or empty strings).
diff --git a/internal/user/files.go b/internal/user/files.go
index d48d8a9..7d836a6 100644
--- a/internal/user/files.go
+++ b/internal/user/files.go
@@ -3,10 +3,10 @@ package user
import (
"encoding/json"
"errors"
- "github.com/bouncepaw/mycorrhiza/internal/cfg"
- "log"
+ "log/slog"
"os"
+ "github.com/bouncepaw/mycorrhiza/internal/cfg"
"github.com/bouncepaw/mycorrhiza/internal/files"
"github.com/bouncepaw/mycorrhiza/util"
)
@@ -32,19 +32,23 @@ func usersFromFile() []*User {
return users
}
if err != nil {
- log.Fatal(err)
+ slog.Error("Failed to read users.json", "err", err)
+ os.Exit(1)
}
+
err = json.Unmarshal(contents, &users)
if err != nil {
- log.Fatal(err)
+ slog.Error("Failed to unmarshal users.json contents", "err", err)
+ os.Exit(1)
}
+
for _, u := range users {
u.Name = util.CanonicalName(u.Name)
if u.Source == "" {
u.Source = "local"
}
}
- log.Println("Found", len(users), "users")
+ slog.Info("Indexed users", "n", len(users))
return users
}
@@ -63,20 +67,22 @@ func readTokensToUsers() {
return
}
if err != nil {
- log.Fatal(err)
+ slog.Error("Failed to read tokens.json", "err", err)
+ os.Exit(1)
}
var tmp map[string]string
err = json.Unmarshal(contents, &tmp)
if err != nil {
- log.Fatal(err)
+ slog.Error("Failed to unmarshal tokens.json contents", "err", err)
+ os.Exit(1)
}
for token, username := range tmp {
tokens.Store(token, username)
// commenceSession(username, token)
}
- log.Println("Found", len(tmp), "active sessions")
+ slog.Info("Indexed active sessions", "n", len(tmp))
}
// SaveUserDatabase stores current user credentials into JSON file by configured path.
@@ -94,13 +100,13 @@ func dumpUserCredentials() error {
blob, err := json.MarshalIndent(userList, "", "\t")
if err != nil {
- log.Println(err)
+ slog.Error("Failed to marshal users.json", "err", err)
return err
}
err = os.WriteFile(files.UserCredentialsJSON(), blob, 0666)
if err != nil {
- log.Println(err)
+ slog.Error("Failed to write users.json", "err", err)
return err
}
@@ -119,11 +125,11 @@ func dumpTokens() {
blob, err := json.MarshalIndent(tmp, "", "\t")
if err != nil {
- log.Println(err)
+ slog.Error("Failed to marshal tokens.json", "err", err)
return
}
err = os.WriteFile(files.TokensJSON(), blob, 0666)
if err != nil {
- log.Println("an error occurred in dumpTokens function:", err)
+ slog.Error("Failed to write tokens.json", "err", err)
}
}
diff --git a/internal/user/net.go b/internal/user/net.go
index 00f60c2..7066d28 100644
--- a/internal/user/net.go
+++ b/internal/user/net.go
@@ -6,16 +6,16 @@ import (
"encoding/hex"
"errors"
"fmt"
- "github.com/bouncepaw/mycorrhiza/internal/cfg"
- "log"
+ "log/slog"
"net/http"
"sort"
"strings"
"time"
- "golang.org/x/crypto/bcrypt"
-
+ "github.com/bouncepaw/mycorrhiza/internal/cfg"
"github.com/bouncepaw/mycorrhiza/util"
+
+ "golang.org/x/crypto/bcrypt"
)
// CanProceed returns `true` if the user in `rq` has enough rights to access `route`.
@@ -91,17 +91,17 @@ func LoginDataHTTP(w http.ResponseWriter, username, password string) error {
w.Header().Set("Content-Type", "text/html;charset=utf-8")
if !HasUsername(username) {
w.WriteHeader(http.StatusBadRequest)
- log.Println("Unknown username", username, "was entered")
+ slog.Info("Unknown username entered", "username", username)
return ErrUnknownUsername
}
if !CredentialsOK(username, password) {
w.WriteHeader(http.StatusBadRequest)
- log.Println("A wrong password was entered for username", username)
+ slog.Info("Wrong password entered", "username", username)
return ErrWrongPassword
}
token, err := AddSession(username)
if err != nil {
- log.Println(err)
+ slog.Error("Failed to add session", "username", username, "err", err)
w.WriteHeader(http.StatusBadRequest)
return err
}
@@ -114,7 +114,7 @@ func AddSession(username string) (string, error) {
token, err := util.RandomString(16)
if err == nil {
commenceSession(username, token)
- log.Println("New token for", username, "is", token)
+ slog.Info("Added session", "username", username)
}
return token, err
}
diff --git a/internal/user/user.go b/internal/user/user.go
index 6aa500a..eec2ff7 100644
--- a/internal/user/user.go
+++ b/internal/user/user.go
@@ -2,12 +2,13 @@ package user
import (
"fmt"
- "github.com/bouncepaw/mycorrhiza/internal/cfg"
"net/http"
"strings"
"sync"
"time"
+ "github.com/bouncepaw/mycorrhiza/internal/cfg"
+
"golang.org/x/crypto/bcrypt"
)
diff --git a/interwiki/interwiki.go b/interwiki/interwiki.go
index de4a532..5020afc 100644
--- a/interwiki/interwiki.go
+++ b/interwiki/interwiki.go
@@ -4,29 +4,36 @@ package interwiki
import (
"encoding/json"
"errors"
- "git.sr.ht/~bouncepaw/mycomarkup/v5/options"
- "github.com/bouncepaw/mycorrhiza/internal/files"
- "github.com/bouncepaw/mycorrhiza/util"
- "log"
+ "log/slog"
"os"
"sync"
+
+ "github.com/bouncepaw/mycorrhiza/internal/files"
+ "github.com/bouncepaw/mycorrhiza/util"
+
+ "git.sr.ht/~bouncepaw/mycomarkup/v5/options"
)
-func Init() {
- var (
- record, err = readInterwiki()
- )
+func Init() error {
+ record, err := readInterwiki()
if err != nil {
- log.Fatalln(err)
+ slog.Error("Failed to read interwiki", "err", err)
+ return err
}
+
for _, wiki := range record {
wiki := wiki // This line is required
- wiki.canonize()
+ if err := wiki.canonize(); err != nil {
+ return err
+ }
if err := addEntry(&wiki); err != nil {
- log.Fatalln(err.Error())
+ slog.Error("Failed to add interwiki entry", "err", err)
+ return err
}
}
- log.Printf("Loaded %d interwiki entries\n", len(listOfEntries))
+
+ slog.Info("Indexed interwiki map", "n", len(listOfEntries))
+ return nil
}
func dropEmptyStrings(ss []string) (clean []string) {
@@ -100,7 +107,6 @@ func deleteEntry(wiki *Wiki) {
for i, w := range listOfEntries {
i, w := i, w
if w.Name == wiki.Name {
- log.Println("It came to delete")
// Drop ith element.
listOfEntries[i] = listOfEntries[len(listOfEntries)-1]
listOfEntries = listOfEntries[:len(listOfEntries)-1]
@@ -113,21 +119,22 @@ func deleteEntry(wiki *Wiki) {
wg.Wait()
}
+// TODO: There is something clearly wrong with error-returning in this function.
func addEntry(wiki *Wiki) error {
mutex.Lock()
defer mutex.Unlock()
wiki.Aliases = dropEmptyStrings(wiki.Aliases)
+
var (
names = append(wiki.Aliases, wiki.Name)
ok, name = areNamesFree(names)
)
- if !ok {
- log.Printf("There are multiple uses of the same name ‘%s’\n", name)
+ switch {
+ case !ok:
+ slog.Error("There are multiple uses of the same name", "name", name)
return errors.New(name)
- }
- if len(names) == 0 {
- log.Println("No names passed for a new interwiki entry")
- // There is something clearly wrong with error-returning in this function.
+ case len(names) == 0:
+ slog.Error("No names passed for a new interwiki entry")
return errors.New("")
}
@@ -176,10 +183,13 @@ func readInterwiki() ([]Wiki, error) {
func saveInterwikiJson() {
// Trust me, wiki crashing when an admin takes an administrative action totally makes sense.
if data, err := json.MarshalIndent(listOfEntries, "", "\t"); err != nil {
- log.Fatalln(err)
+ slog.Error("Failed to marshal interwiki entries", "err", err)
+ os.Exit(1)
} else if err = os.WriteFile(files.InterwikiJSON(), data, 0666); err != nil {
- log.Fatalln(err)
- } else {
- log.Println("Saved interwiki.json")
+ slog.Error("Failed to write interwiki.json", "err", err)
+ os.Exit(1)
}
+
+ slog.Info("Saved interwiki.json")
+
}
diff --git a/interwiki/web.go b/interwiki/web.go
index 58ba51d..b8c62f8 100644
--- a/interwiki/web.go
+++ b/interwiki/web.go
@@ -2,11 +2,13 @@ package interwiki
import (
"embed"
- "github.com/bouncepaw/mycorrhiza/web/viewutil"
- "github.com/gorilla/mux"
- "log"
+ "log/slog"
"net/http"
"strings"
+
+ "github.com/bouncepaw/mycorrhiza/web/viewutil"
+
+ "github.com/gorilla/mux"
)
var (
@@ -63,19 +65,24 @@ func handlerModifyEntry(w http.ResponseWriter, rq *http.Request) {
)
if oldData, ok = entriesByName[name]; !ok {
- log.Printf("Could not modify interwiki entry ‘%s’ because it does not exist", name)
+ slog.Info("Could not modify entry",
+ "name", name,
+ "reason", "does not exist")
viewutil.HandlerNotFound(w, rq)
return
}
if err := replaceEntry(oldData, &newData); err != nil {
- log.Printf("Could not modify interwiki entry ‘%s’ because one of the proposed aliases/name is taken\n", name)
+ slog.Info("Could not modify entry",
+ "name", name,
+ "reason", "one of the proposed aliases or the name is taken",
+ "err", err)
viewNameTaken(viewutil.MetaFrom(w, rq), oldData, err.Error(), "modify-entry/"+name)
return
}
saveInterwikiJson()
- log.Printf("Modified interwiki entry ‘%s’\n", name)
+ slog.Info("Modified entry", "name", name)
http.Redirect(w, rq, "/interwiki", http.StatusSeeOther)
}
diff --git a/interwiki/wiki.go b/interwiki/wiki.go
index 4d0ef51..05df378 100644
--- a/interwiki/wiki.go
+++ b/interwiki/wiki.go
@@ -1,9 +1,11 @@
package interwiki
import (
+ "errors"
"fmt"
+ "log/slog"
+
"github.com/bouncepaw/mycorrhiza/util"
- "log"
)
// WikiEngine is an enumeration of supported interwiki targets.
@@ -47,14 +49,20 @@ type Wiki struct {
Engine WikiEngine `json:"engine"`
}
-func (w *Wiki) canonize() {
+func (w *Wiki) canonize() error {
switch {
case w.Name == "":
- log.Fatalln("Cannot have a wiki in the interwiki map with no name")
+ slog.Error("A site in the interwiki map has no name")
+ return errors.New("site with no name")
case w.URL == "":
- log.Fatalf("Wiki ‘%s’ has no URL\n", w.Name)
+ slog.Error("Site in the interwiki map has no URL", "name", w.Name)
+ return errors.New("site with no URL")
case !w.Engine.Valid():
- log.Fatalf("Unknown engine ‘%s’ for wiki ‘%s’\n", w.Engine, w.Name)
+ slog.Error("Site in the interwiki map has an unknown engine",
+ "siteName", w.Name,
+ "engine", w.Engine,
+ )
+ return errors.New("unknown engine")
}
w.Name = util.CanonicalName(w.Name)
@@ -83,4 +91,6 @@ func (w *Wiki) canonize() {
w.ImgSrcFormat = fmt.Sprintf("%s/{NAME}", w.URL)
}
}
+
+ return nil
}
diff --git a/l18n/l18n.go b/l18n/l18n.go
index d352d61..ea5ae44 100644
--- a/l18n/l18n.go
+++ b/l18n/l18n.go
@@ -21,7 +21,7 @@ import (
"encoding/json"
"fmt"
"io/fs"
- "log"
+ "log/slog"
"net/http"
"path/filepath"
"strings"
@@ -78,7 +78,7 @@ func init() {
var strings map[string]string
if err := json.Unmarshal(contents, &strings); err != nil {
- log.Fatalf("error while parsing %s: %v", path, err)
+ slog.Error("Failed to unmarshal localization file", "path", path, "err", err)
}
for key, value := range strings {
diff --git a/main.go b/main.go
index 4028464..21dd33f 100644
--- a/main.go
+++ b/main.go
@@ -5,12 +5,9 @@
package main
import (
- "github.com/bouncepaw/mycorrhiza/internal/categories"
- "log"
- "os"
-
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/internal/backlinks"
+ "github.com/bouncepaw/mycorrhiza/internal/categories"
"github.com/bouncepaw/mycorrhiza/internal/cfg"
"github.com/bouncepaw/mycorrhiza/internal/files"
"github.com/bouncepaw/mycorrhiza/internal/hyphae"
@@ -22,45 +19,63 @@ import (
"github.com/bouncepaw/mycorrhiza/web"
"github.com/bouncepaw/mycorrhiza/web/static"
"github.com/bouncepaw/mycorrhiza/web/viewutil"
+ "log/slog"
+ "os"
)
func main() {
- parseCliArgs()
+ if err := parseCliArgs(); err != nil {
+ os.Exit(1)
+ }
if err := files.PrepareWikiRoot(); err != nil {
- log.Fatal(err)
+ slog.Error("Failed to prepare wiki root", "err", err)
+ os.Exit(1)
}
if err := cfg.ReadConfigFile(files.ConfigPath()); err != nil {
- log.Fatal(err)
+ slog.Error("Failed to read config", "err", err)
+ os.Exit(1)
}
- log.Println("Running Mycorrhiza Wiki", version.Short)
if err := os.Chdir(files.HyphaeDir()); err != nil {
- log.Fatal(err)
+ slog.Error("Failed to chdir to hyphae dir",
+ "err", err, "hyphaeDir", files.HyphaeDir())
+ os.Exit(1)
}
- log.Println("Wiki directory is", cfg.WikiDir)
+ slog.Info("Running Mycorrhiza Wiki",
+ "version", version.Short, "wikiDir", cfg.WikiDir)
// Init the subsystems:
+ // TODO: keep all crashes in main rather than somewhere there
viewutil.Init()
hyphae.Index(files.HyphaeDir())
backlinks.IndexBacklinks()
go backlinks.RunBacklinksConveyor()
user.InitUserDatabase()
- history.Start()
+ if err := history.Start(); err != nil {
+ os.Exit(1)
+ }
history.InitGitRepo()
migration.MigrateRocketsMaybe()
migration.MigrateHeadingsMaybe()
shroom.SetHeaderLinks()
- categories.Init()
- interwiki.Init()
+ if err := categories.Init(); err != nil {
+ os.Exit(1)
+ }
+ if err := interwiki.Init(); err != nil {
+ os.Exit(1)
+ }
// Static files:
static.InitFS(files.StaticFiles())
if !user.HasAnyAdmins() {
- log.Println("Your wiki has no admin yet. Run Mycorrhiza with -create-admin