diff options
Diffstat (limited to 'vrsite/log.go')
| -rw-r--r-- | vrsite/log.go | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/vrsite/log.go b/vrsite/log.go new file mode 100644 index 0000000..a0a4f3e --- /dev/null +++ b/vrsite/log.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + "os" + "sync" +) + +// logStore is implemented by the production jj sidecar and by the file-backed +// adapter used in tests. Append's callback makes session note numbering atomic +// with the content update. +type logStore interface { + Read() ([]byte, error) + Generation() (string, error) + Append(func(current []byte) ([]byte, error)) error + String() string +} + +type fileLog struct { + path string + mu sync.Mutex +} + +func newFileLog(path string) *fileLog { return &fileLog{path: path} } + +func (l *fileLog) String() string { return l.path } + +func (l *fileLog) Read() ([]byte, error) { return os.ReadFile(l.path) } + +func (l *fileLog) Generation() (string, error) { + info, err := os.Stat(l.path) + if err != nil { + return "", err + } + return fmt.Sprintf("%d:%d", info.Size(), info.ModTime().UnixNano()), nil +} + +func (l *fileLog) Append(makePayload func(current []byte) ([]byte, error)) error { + l.mu.Lock() + defer l.mu.Unlock() + current, err := os.ReadFile(l.path) + if err != nil && !os.IsNotExist(err) { + return err + } + payload, err := makePayload(current) + if err != nil { + return err + } + f, err := os.OpenFile(l.path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644) + if err != nil { + return err + } + defer f.Close() + _, err = f.Write(payload) + return err +} |
