diff --git a/internal/p9/server/fs.go b/internal/p9/server/fs.go index 25e2c3b..81e66c4 100644 --- a/internal/p9/server/fs.go +++ b/internal/p9/server/fs.go @@ -164,41 +164,7 @@ func loadData(filters []*metadata.Filter) (metadata.Results, error) { return notes, nil } -func AddNote(note *metadata.Metadata) error { - if srv == nil { - return fmt.Errorf("server not running") - } - srv.mu.Lock() - defer srv.mu.Unlock() - - srv.notes = append(srv.notes, note) - return nil -} - -func GetNote(identifier string) (*metadata.Metadata, error) { - if srv == nil { - return nil, fmt.Errorf("server not running") - } - - return findNote(identifier) -} - -func UpdateNotePath(identifier, path string) error { - if srv == nil { - return fmt.Errorf("server not running") - } - - note, err := findNote(identifier) - if err != nil { - return err - } - - srv.mu.Lock() - defer srv.mu.Unlock() - note.Path = path - return nil -} // StartServer starts the 9P fileserver in the background func StartServer() error { @@ -676,6 +642,9 @@ func (s *server) write(cs *connState, fc *plan9.Fcall) *plan9.Fcall { value := strings.TrimSpace(string(fc.Data)) switch fieldName { + case "path": + note.Path = value + emitEvent(noteID, 'r') case "title": note.Title = value emitEvent(noteID, 'u') @@ -858,7 +827,7 @@ func (s *server) readDir(path string, offset int64, count uint32) []byte { for i, fname := range fileNames { content := s.getFileContent(path + "/" + fname) mode := uint32(0444) // read-only by default - if fname == "title" || fname == "keywords" { + if fname == "title" || fname == "keywords" || fname == "path" { mode = 0644 // writable } else if fname == "ctl" { mode = 0200 // write-only diff --git a/main.go b/main.go index a8bccff..369e6bb 100644 --- a/main.go +++ b/main.go @@ -219,13 +219,9 @@ func eventListener() { log.Printf("error handling rename for %s: %v", identifier, err) } case "n": - if err := handleNewEvent(identifier); err != nil { + if err := handleNewEvent(f, identifier); err != nil { log.Printf("error handling new for %s: %v", identifier, err) } - case "d": - if err := handleDeleteEvent(identifier); err != nil { - log.Printf("error handling delete for %s: %v", identifier, err) - } } } }) @@ -280,53 +276,79 @@ func handleUpdateEvent(f *client.Fsys, identifier string) error { } } + // After updating content, check if a rename is needed + dir := filepath.Dir(path) + if dir == "." { + dir = denoteDir + } + filename := buildDenoteFilename(identifier, title, tags, ext) + newPath := filepath.Join(dir, filename) + + if newPath != path { + if err := p9client.WriteFile(f, "n/"+identifier+"/path", newPath); err != nil { + return fmt.Errorf("failed to update path in 9p: %w", err) + } + } + return nil } func handleRenameEvent(f *client.Fsys, identifier string) error { - fields, err := read9PFields(f, identifier, "title", "keywords", "path") + // Get new path from 9P server. + newPath, err := read9PFile(f, "n/"+identifier+"/path") if err != nil { - return err + return fmt.Errorf("failed to read path: %w", err) } - title := fields["title"] - keywords := fields["keywords"] - path := fields["path"] - - var tags []string - if keywords != "" { - for _, tag := range strings.Split(keywords, ",") { - tags = append(tags, strings.TrimSpace(tag)) - } + if newPath == "" { + // Path is not set yet. This can happen during note creation. + return nil } - newPath, err := renameNote(path, title, tags, identifier) + // Find old file on disk. + pattern := filepath.Join(denoteDir, identifier+"--*") + matches, err := filepath.Glob(pattern) if err != nil { - return fmt.Errorf("failed to rename file: %w", err) + return fmt.Errorf("failed to find file: %w", err) } - if newPath != path { - if err := p9server.UpdateNotePath(identifier, newPath); err != nil { - return fmt.Errorf("failed to update path: %w", err) + if len(matches) == 0 { + // File doesn't exist on disk. Nothing to rename. + return nil + } + oldPath := matches[0] + + // Rename if different. + if oldPath != newPath { + if err := os.Rename(oldPath, newPath); err != nil { + return fmt.Errorf("failed to rename file from %s to %s: %w", oldPath, newPath, err) } } return nil } -func handleNewEvent(identifier string) error { - metadata, err := p9server.GetNote(identifier) +func handleNewEvent(f *client.Fsys, identifier string) error { + fields, err := read9PFields(f, identifier, "title", "keywords") if err != nil { return fmt.Errorf("failed to get metadata: %w", err) } + title := fields["title"] + var tags []string + if keywords, ok := fields["keywords"]; ok && keywords != "" { + tags = strings.Split(keywords, ",") + for i := range tags { + tags[i] = strings.TrimSpace(tags[i]) + } + } - path, content := generateNotePath(denoteDir, metadata.Title, metadata.Tags, "md-yaml") + path, content := generateNotePath(denoteDir, title, tags, "md-yaml") if err := os.WriteFile(path, []byte(content), 0644); err != nil { return fmt.Errorf("failed to create note file: %w", err) } - if err := p9server.UpdateNotePath(identifier, path); err != nil { + if err := p9client.WriteFile(f, "n/"+identifier+"/path", path); err != nil { return fmt.Errorf("failed to update path in metadata: %w", err) }