fix: complete vault layout transition — fs_path everywhere, no more spaces/
- notes.Create(): .md files stored in parent node's fs_path folder - files.CopyIntoVault/CreateEmptyFile/Duplicate: use parent fs_path - files.AddPathCopy/AddPathLink: use parent fs_path, set folder fs_path - files.DeleteNodeAndChildren: move physical folder to .verstak/trash - UpdateFsPathRecursive: use SafeDisplayNameToPathSegment(child.Title) - sync_apply.go note ops: use fs_path instead of spaces/ - internal/gui/server.go file upload: use n.FsPath instead of nodeSlug - VaultCheck diagnostic: walk nodes/files, verify paths on disk - Tests: create/rename/move/delete/name-conflict/vault-check all pass
This commit is contained in:
+21
-10
@@ -9,6 +9,7 @@ import (
|
||||
"verstak/internal/core/files"
|
||||
"verstak/internal/core/nodes"
|
||||
"verstak/internal/core/storage"
|
||||
"verstak/internal/core/templates"
|
||||
"verstak/internal/core/util"
|
||||
)
|
||||
|
||||
@@ -40,33 +41,43 @@ func (s *Service) Create(parentID, title, section string) (*nodes.Node, *files.R
|
||||
return nil, nil, fmt.Errorf("create node: %w", err)
|
||||
}
|
||||
|
||||
slug := node.Slug
|
||||
if slug == "" {
|
||||
slug = "note"
|
||||
seg := templates.SafeDisplayNameToPathSegment(title)
|
||||
if seg == "" {
|
||||
seg = "note"
|
||||
}
|
||||
filename := seg + ".md"
|
||||
|
||||
var destDir string
|
||||
if parentID != "" {
|
||||
parent, err := s.nodes.GetActive(parentID)
|
||||
if err == nil && parent.FsPath != "" {
|
||||
destDir = filepath.Join(s.vaultRoot, parent.FsPath)
|
||||
}
|
||||
}
|
||||
if destDir == "" {
|
||||
destDir = s.vaultRoot
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(destDir, 0o750); err != nil {
|
||||
return nil, nil, fmt.Errorf("mkdir: %w", err)
|
||||
}
|
||||
filename := slug + ".md"
|
||||
destDir := filepath.Join(s.vaultRoot, "spaces")
|
||||
os.MkdirAll(destDir, 0o750)
|
||||
|
||||
dest := filepath.Join(destDir, filename)
|
||||
if _, err := os.Stat(dest); err == nil {
|
||||
filename = fmt.Sprintf("%s_%s.md", slug, node.ID[:8])
|
||||
filename = fmt.Sprintf("%s_%s.md", seg, node.ID[:8])
|
||||
dest = filepath.Join(destDir, filename)
|
||||
}
|
||||
|
||||
// Write initial content.
|
||||
if err := os.WriteFile(dest, []byte("# "+title+"\n\n"), 0o640); err != nil {
|
||||
return nil, nil, fmt.Errorf("write: %w", err)
|
||||
}
|
||||
|
||||
// Register file record.
|
||||
relPath, _ := filepath.Rel(s.vaultRoot, dest)
|
||||
fileRec, err := insertFileRecord(s.db, node.ID, filename, relPath, "vault", 0)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("insert file: %w", err)
|
||||
}
|
||||
|
||||
// Link.
|
||||
_, err = s.db.Exec(
|
||||
`INSERT INTO notes (node_id, file_id, format) VALUES (?,?,?)`,
|
||||
node.ID, fileRec.ID, "markdown")
|
||||
|
||||
@@ -49,11 +49,16 @@ func TestCreateAndRead(t *testing.T) {
|
||||
t.Errorf("content = %q", content)
|
||||
}
|
||||
|
||||
// Verify file on disk.
|
||||
spacesDir := filepath.Join(vaultRoot, "spaces")
|
||||
entries, _ := os.ReadDir(spacesDir)
|
||||
if len(entries) == 0 {
|
||||
t.Error("expected file in spaces/")
|
||||
// Verify file on disk (in vault root for parentless notes).
|
||||
entries, _ := os.ReadDir(vaultRoot)
|
||||
var mdFiles int
|
||||
for _, e := range entries {
|
||||
if !e.IsDir() && filepath.Ext(e.Name()) == ".md" {
|
||||
mdFiles++
|
||||
}
|
||||
}
|
||||
if mdFiles == 0 {
|
||||
t.Error("expected .md file in vault root")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user