commit 2675437

delthas  ·  2026-03-11 12:53:36 +0000 UTC
parent 2440d28
Use per-config-path cache files to prevent multi-instance conflicts

Cache files (lastbuffer, laststamp) now include a hash of the config
file path in their filename, so multiple senpai instances with different
configs no longer overwrite each other's state. Falls back to reading
the old unsuffixed files for migration.

See https://codeberg.org/obsoleszenz/senpai/commit/fe77778bcc11de6e5e2018f408599000b9999962

Co-authored-by: obsoleszenz <obsoleszenz@riseup.net>
1 files changed,  +55, -22
+55, -22
  1@@ -1,9 +1,11 @@
  2 package main
  3 
  4 import (
  5+	"encoding/hex"
  6 	"errors"
  7 	"flag"
  8 	"fmt"
  9+	"hash/fnv"
 10 	"io"
 11 	"math/rand"
 12 	"net"
 13@@ -209,10 +211,11 @@ func main() {
 14 		return
 15 	}
 16 
 17+	cfgHash := configPathHash(configPath)
 18 	if !cfg.Transient {
 19-		lastNetID, lastBuffer := getLastBuffer()
 20+		lastNetID, lastBuffer := getLastBuffer(cfgHash)
 21 		app.SwitchToBuffer(lastNetID, lastBuffer)
 22-		app.SetLastClose(getLastStamp())
 23+		app.SetLastClose(getLastStamp(cfgHash))
 24 	}
 25 
 26 	sigCh := make(chan os.Signal, 1)
 27@@ -234,8 +237,8 @@ func main() {
 28 	app.Run()
 29 	app.Close()
 30 	if !cfg.Transient {
 31-		writeLastBuffer(app)
 32-		writeLastStamp(app)
 33+		writeLastBuffer(app, cfgHash)
 34+		writeLastStamp(app, cfgHash)
 35 	}
 36 }
 37 
 38@@ -287,13 +290,33 @@ func cachePath() string {
 39 	return cache
 40 }
 41 
 42-func lastBufferPath() string {
 43-	return path.Join(cachePath(), "lastbuffer.txt")
 44+func configPathHash(configPath string) string {
 45+	abs, err := filepath.Abs(configPath)
 46+	if err != nil {
 47+		abs = configPath
 48+	}
 49+	h := fnv.New32a()
 50+	h.Write([]byte(abs))
 51+	return hex.EncodeToString(h.Sum(nil))
 52 }
 53 
 54-func getLastBuffer() (netID, buffer string) {
 55-	buf, err := os.ReadFile(lastBufferPath())
 56-	if err != nil {
 57+func lastBufferPath(hash string) string {
 58+	name := "lastbuffer.txt"
 59+	if hash != "" {
 60+		name = "lastbuffer-" + hash + ".txt"
 61+	}
 62+	return path.Join(cachePath(), name)
 63+}
 64+
 65+func getLastBuffer(hash string) (netID, buffer string) {
 66+	p := lastBufferPath(hash)
 67+	buf, err := os.ReadFile(p)
 68+	if err != nil && hash != "" {
 69+		buf, err = os.ReadFile(lastBufferPath(""))
 70+		if err != nil {
 71+			return "", ""
 72+		}
 73+	} else if err != nil {
 74 		return "", ""
 75 	}
 76 
 77@@ -305,22 +328,32 @@ func getLastBuffer() (netID, buffer string) {
 78 	return fields[0], fields[1]
 79 }
 80 
 81-func writeLastBuffer(app *senpai.App) {
 82-	lastBufferPath := lastBufferPath()
 83+func writeLastBuffer(app *senpai.App, hash string) {
 84+	p := lastBufferPath(hash)
 85 	lastNetID, lastBuffer := app.CurrentBuffer()
 86-	err := os.WriteFile(lastBufferPath, []byte(fmt.Sprintf("%s %s", lastNetID, lastBuffer)), 0666)
 87+	err := os.WriteFile(p, []byte(fmt.Sprintf("%s %s", lastNetID, lastBuffer)), 0666)
 88 	if err != nil {
 89-		fmt.Fprintf(os.Stderr, "failed to write last buffer at %q: %s\n", lastBufferPath, err)
 90+		fmt.Fprintf(os.Stderr, "failed to write last buffer at %q: %s\n", p, err)
 91 	}
 92 }
 93 
 94-func lastStampPath() string {
 95-	return path.Join(cachePath(), "laststamp.txt")
 96+func lastStampPath(hash string) string {
 97+	name := "laststamp.txt"
 98+	if hash != "" {
 99+		name = "laststamp-" + hash + ".txt"
100+	}
101+	return path.Join(cachePath(), name)
102 }
103 
104-func getLastStamp() time.Time {
105-	buf, err := os.ReadFile(lastStampPath())
106-	if err != nil {
107+func getLastStamp(hash string) time.Time {
108+	p := lastStampPath(hash)
109+	buf, err := os.ReadFile(p)
110+	if err != nil && hash != "" {
111+		buf, err = os.ReadFile(lastStampPath(""))
112+		if err != nil {
113+			return time.Time{}
114+		}
115+	} else if err != nil {
116 		return time.Time{}
117 	}
118 
119@@ -332,15 +365,15 @@ func getLastStamp() time.Time {
120 	return t
121 }
122 
123-func writeLastStamp(app *senpai.App) {
124-	lastStampPath := lastStampPath()
125+func writeLastStamp(app *senpai.App, hash string) {
126+	p := lastStampPath(hash)
127 	last := app.LastMessageTime()
128 	if last.IsZero() {
129 		return
130 	}
131-	err := os.WriteFile(lastStampPath, []byte(last.UTC().Format(time.RFC3339Nano)), 0666)
132+	err := os.WriteFile(p, []byte(last.UTC().Format(time.RFC3339Nano)), 0666)
133 	if err != nil {
134-		fmt.Fprintf(os.Stderr, "failed to write last stamp at %q: %s\n", lastStampPath, err)
135+		fmt.Fprintf(os.Stderr, "failed to write last stamp at %q: %s\n", p, err)
136 	}
137 }
138