diff --git a/go.mod b/go.mod index f724fa0..75e083a 100644 --- a/go.mod +++ b/go.mod @@ -3,5 +3,3 @@ module denotesrv go 1.23.0 require 9fans.net/go v0.0.5 - -require github.com/simonfxr/pubsub v0.0.5 // indirect diff --git a/go.sum b/go.sum index e8c7e00..5089ea2 100644 --- a/go.sum +++ b/go.sum @@ -2,13 +2,7 @@ 9fans.net/go v0.0.5/go.mod h1:Rxvbbc1e+1TyGMjAvLthGTyO97t+6JMQ6ly+Lcs9Uf0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/simonfxr/pubsub v0.0.5 h1:DJfvFoglqGvwJriIOC5NI5um34n2YX8KAU5+7jv768w= -github.com/simonfxr/pubsub v0.0.5/go.mod h1:bQ+B2NEEHZ08VY/0xVFGaGL1KMJ7cl3yLaXe8xvyC24= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -38,5 +32,3 @@ golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -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= diff --git a/internal/p9/server/server.go b/internal/p9/server/server.go index 53124b5..1cbefd5 100644 --- a/internal/p9/server/server.go +++ b/internal/p9/server/server.go @@ -51,7 +51,6 @@ import ( "9fans.net/go/plan9" "9fans.net/go/plan9/client" - ps "github.com/simonfxr/pubsub" ) // File types in our filesystem @@ -69,7 +68,6 @@ const ( qidNoteBase = 1 qidFileBase = 1000001 qidIndex = 999999 - qidEvent = 999998 qidNew = 999997 qidNDir = 999996 qidCtl = 999995 @@ -93,7 +91,6 @@ type server struct { callbacks Callbacks filterQuery string filteredNotes []*metadata.Metadata - events *ps.Bus } type connState struct { @@ -106,9 +103,7 @@ type fid struct { path string offset int64 mode uint8 - writeBuf []byte // accumulates Twrite chunks, dispatched on Tclunk - eventCh chan string // for event subscribers - eventCancel func() // unsubscribe callback + writeBuf []byte // accumulates Twrite chunks, dispatched on Tclunk } var srv *server @@ -185,7 +180,6 @@ func NewServer(denoteDir string, callbacks Callbacks) (*Server, error) { notes: notes, denoteDir: denoteDir, callbacks: callbacks, - events: ps.NewBus(), } return &Server{s}, nil } @@ -204,7 +198,6 @@ func StartServer(initialData metadata.Results, denoteDir string, callbacks Callb notes: initialData, denoteDir: denoteDir, callbacks: callbacks, - events: ps.NewBus(), } // Get namespace and create Unix socket path @@ -409,14 +402,6 @@ func (s *server) walk(cs *connState, fc *plan9.Fcall) *plan9.Fcall { qids = append(qids, qid) path = "/dir" found = true - } else if name == "event" { - qid := plan9.Qid{ - Type: QTFile, - Path: uint64(qidEvent), - } - qids = append(qids, qid) - path = "/event" - found = true } else if name == "n" { qid := plan9.Qid{ Type: QTDir, @@ -509,24 +494,6 @@ func (s *server) read(cs *connState, fc *plan9.Fcall) *plan9.Fcall { return errorFcall(fc, "fid not found") } - // Handle event stream (blocking read with pubsub) - if f.path == "/event" { - if f.eventCh == nil { - ch := make(chan string, 64) - sub := s.events.SubscribeChan("events", ch, ps.CloseOnUnsubscribe) - f.eventCh = ch - f.eventCancel = func() { s.events.Unsubscribe(sub) } - } - cs.mu.Unlock() - select { - case msg := <-f.eventCh: - data := []byte(msg + "\n") - return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: uint32(len(data)), Data: data} - case <-time.After(30 * time.Second): - return &plan9.Fcall{Type: plan9.Rread, Tag: fc.Tag, Count: 0, Data: []byte{}} - } - } - defer cs.mu.Unlock() var data []byte @@ -654,7 +621,6 @@ func (s *server) dispatchWrite(f *fid, tag uint16) *plan9.Fcall { if s.callbacks.OnNew != nil { go s.callbacks.OnNew(identifier) } - s.events.Publish("events", "n "+identifier) return &plan9.Fcall{Type: plan9.Rwrite, Tag: fc.Tag, Count: uint32(len(f.writeBuf))} } @@ -684,8 +650,9 @@ func (s *server) dispatchWrite(f *fid, tag uint16) *plan9.Fcall { if s.callbacks.OnRename != nil { s.callbacks.OnRename(noteID) } - s.events.Publish("events", "u "+noteID) - s.events.Publish("events", "r "+noteID) + if err := s.renameNote(note); err != nil { + return errorFcall(fc, err.Error()) + } case "keywords": if input == "" { note.Tags = []string{} @@ -702,8 +669,9 @@ func (s *server) dispatchWrite(f *fid, tag uint16) *plan9.Fcall { if s.callbacks.OnRename != nil { s.callbacks.OnRename(noteID) } - s.events.Publish("events", "u "+noteID) - s.events.Publish("events", "r "+noteID) + if err := s.renameNote(note); err != nil { + return errorFcall(fc, err.Error()) + } case "signature": note.Signature = input if s.callbacks.OnUpdate != nil { @@ -712,15 +680,15 @@ func (s *server) dispatchWrite(f *fid, tag uint16) *plan9.Fcall { if s.callbacks.OnRename != nil { s.callbacks.OnRename(noteID) } - s.events.Publish("events", "u "+noteID) - s.events.Publish("events", "r "+noteID) + if err := s.renameNote(note); err != nil { + return errorFcall(fc, err.Error()) + } case "ctl": switch input { case "d": if s.callbacks.OnDelete != nil { s.callbacks.OnDelete(noteID) } - s.events.Publish("events", "d "+noteID) s.mu.Lock() for i, n := range s.notes { if n.Identifier == noteID { @@ -739,7 +707,6 @@ func (s *server) dispatchWrite(f *fid, tag uint16) *plan9.Fcall { if s.callbacks.OnRename != nil { s.callbacks.OnRename(noteID) } - s.events.Publish("events", "r "+noteID) } case "body": if err := s.writeBody(note.Path, input, note); err != nil { @@ -785,10 +752,6 @@ func (s *server) clunk(cs *connState, fc *plan9.Fcall) *plan9.Fcall { } cs.mu.Lock() } - // Clean up event subscription if any - if ok && f.eventCancel != nil { - f.eventCancel() - } delete(cs.fids, fc.Fid) cs.mu.Unlock() @@ -854,19 +817,6 @@ func (s *server) readDir(path string, offset int64, count uint32) []byte { Muid: "denote", Length: uint64(len(s.denoteDir)), }) - // add event node - dirs = append(dirs, plan9.Dir{ - Qid: plan9.Qid{ - Type: QTFile, - Path: uint64(qidEvent), - }, - Mode: 0444, - Name: "event", - Uid: "denote", - Gid: "denote", - Muid: "denote", - Length: 0, - }) // add n directory dirs = append(dirs, plan9.Dir{ Qid: plan9.Qid{ @@ -1075,6 +1025,26 @@ func (s *server) readBody(path string) string { return string(data) } +// renameNote renames the physical file to match current note metadata and updates note.Path. +// It is a no-op when the filename is already correct. +func (s *server) renameNote(note *metadata.Metadata) error { + if note.Path == "" { + return nil + } + ext := filepath.Ext(note.Path) + fm := metadata.NewFrontMatter(note.Title, note.Signature, note.Tags, note.Identifier) + newName := metadata.BuildFilename(fm, ext) + newPath := filepath.Join(filepath.Dir(note.Path), newName) + if newPath == note.Path { + return nil + } + if err := os.Rename(note.Path, newPath); err != nil { + return err + } + note.Path = newPath + return nil +} + // writeBody writes content to file and syncs frontmatter to metadata func (s *server) writeBody(path, body string, note *metadata.Metadata) error { if path == "" { @@ -1091,7 +1061,7 @@ func (s *server) writeBody(path, body string, note *metadata.Metadata) error { note.Tags = fm.Tags note.Signature = fm.Signature } - return nil + return s.renameNote(note) } func errorFcall(fc *plan9.Fcall, msg string) *plan9.Fcall {