| 1666 | } |
| 1667 | |
| 1668 | func (v *Vault) MoveNote(rel string, target NoteFolder, targetSubpath string) (NoteMeta, error) { |
| 1669 | v.mu.Lock() |
| 1670 | defer v.mu.Unlock() |
| 1671 | abs, err := SafeJoin(v.root, rel) |
| 1672 | if err != nil { |
| 1673 | return NoteMeta{}, err |
| 1674 | } |
| 1675 | if !IsValidFolder(target) { |
| 1676 | return NoteMeta{}, fmt.Errorf("invalid folder: %s", target) |
| 1677 | } |
| 1678 | destDir, err := v.folderRoot(target) |
| 1679 | if err != nil { |
| 1680 | return NoteMeta{}, err |
| 1681 | } |
| 1682 | if targetSubpath != "" { |
| 1683 | sub, err := SafeJoin(destDir, targetSubpath) |
| 1684 | if err != nil { |
| 1685 | return NoteMeta{}, err |
| 1686 | } |
| 1687 | destDir = sub |
| 1688 | } |
| 1689 | if err := os.MkdirAll(destDir, v.dirMode); err != nil { |
| 1690 | return NoteMeta{}, err |
| 1691 | } |
| 1692 | title := strings.TrimSuffix(filepath.Base(abs), filepath.Ext(abs)) |
| 1693 | newAbs := uniquePath(destDir, title, noteExt(abs)) |
| 1694 | if err := os.Rename(abs, newAbs); err != nil { |
| 1695 | return NoteMeta{}, err |
| 1696 | } |
| 1697 | v.invalidateTextSearchCache() |
| 1698 | meta, err := v.readMeta(target, newAbs) |
| 1699 | if err != nil { |
| 1700 | return NoteMeta{}, err |
| 1701 | } |
| 1702 | if err := v.moveNoteCommentsLocked(rel, meta.Path); err != nil { |
| 1703 | return NoteMeta{}, err |
| 1704 | } |
| 1705 | return meta, nil |
| 1706 | } |
| 1707 | |
| 1708 | // --- Folders --- |
| 1709 | |