diff --git a/kernel/api/block.go b/kernel/api/block.go index 8c01f06f9..ccfcc5644 100644 --- a/kernel/api/block.go +++ b/kernel/api/block.go @@ -27,7 +27,6 @@ import ( "github.com/siyuan-note/filelock" "github.com/siyuan-note/logging" "github.com/siyuan-note/siyuan/kernel/model" - "github.com/siyuan-note/siyuan/kernel/sql" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -155,7 +154,19 @@ func checkBlockFold(c *gin.Context) { } id := arg["id"].(string) - ret.Data = sql.IsBlockFolded(id) + b, err := model.GetBlock(id, nil) + if errors.Is(err, filelock.ErrUnableAccessFile) { + ret.Code = 2 + ret.Data = id + return + } + if errors.Is(err, model.ErrIndexing) { + ret.Code = 0 + ret.Data = false + return + } + + ret.Data = nil != b && "1" == b.IAL["fold"] } func checkBlockExist(c *gin.Context) { @@ -168,7 +179,7 @@ func checkBlockExist(c *gin.Context) { } id := arg["id"].(string) - b, err := model.GetBlock(id) + b, err := model.GetBlock(id, nil) if errors.Is(err, filelock.ErrUnableAccessFile) { ret.Code = 2 ret.Data = id @@ -376,7 +387,8 @@ func getBlockInfo(c *gin.Context) { } id := arg["id"].(string) - block, err := model.GetBlock(id) + + tree, err := model.LoadTreeByID(id) if errors.Is(err, filelock.ErrUnableAccessFile) { ret.Code = 2 ret.Data = id @@ -387,6 +399,8 @@ func getBlockInfo(c *gin.Context) { ret.Msg = model.Conf.Language(56) return } + + block, _ := model.GetBlock(id, tree) if nil == block { ret.Code = -1 ret.Msg = fmt.Sprintf(model.Conf.Language(15), id) @@ -401,13 +415,13 @@ func getBlockInfo(c *gin.Context) { rootChildID = b.ID break } - if b, _ = model.GetBlock(parentID); nil == b { + if b, _ = model.GetBlock(parentID, tree); nil == b { logging.LogErrorf("not found parent") break } } - root, err := model.GetBlock(block.RootID) + root, err := model.GetBlock(block.RootID, tree) if errors.Is(err, filelock.ErrUnableAccessFile) { ret.Code = 2 ret.Data = id diff --git a/kernel/api/block_op.go b/kernel/api/block_op.go index 7a5b4fd69..dac26ec3b 100644 --- a/kernel/api/block_op.go +++ b/kernel/api/block_op.go @@ -190,7 +190,7 @@ func updateBlock(c *gin.Context) { return } - block, err := model.GetBlock(id) + block, err := model.GetBlock(id, nil) if nil != err { ret.Code = -1 ret.Msg = "get block failed: " + err.Error() diff --git a/kernel/api/filetree.go b/kernel/api/filetree.go index c3b9b19c6..506730262 100644 --- a/kernel/api/filetree.go +++ b/kernel/api/filetree.go @@ -327,7 +327,7 @@ func duplicateDoc(c *gin.Context) { } id := arg["id"].(string) - newTree, err := model.DuplicateDoc(id) + tree, err := model.LoadTreeByID(id) if nil != err { ret.Code = -1 ret.Msg = err.Error() @@ -335,24 +335,17 @@ func duplicateDoc(c *gin.Context) { return } - block, _ := model.GetBlock(id) - p := block.Path - notebook := block.Box + p := tree.Path + notebook := tree.Box box := model.Conf.Box(notebook) - tree, err := model.LoadTree(box.ID, p) - if nil != err { - ret.Code = -1 - ret.Msg = err.Error() - return - } - + model.DuplicateDoc(tree) pushCreate(box, p, tree.Root.ID, arg) ret.Data = map[string]interface{}{ - "id": newTree.Root.ID, + "id": tree.Root.ID, "notebook": notebook, - "path": newTree.Path, - "hPath": newTree.HPath, + "path": tree.Path, + "hPath": tree.HPath, } } @@ -478,7 +471,7 @@ func createDocWithMd(c *gin.Context) { ret.Data = id box := model.Conf.Box(notebook) - b, _ := model.GetBlock(id) + b, _ := model.GetBlock(id, nil) p := b.Path pushCreate(box, p, id, arg) } diff --git a/kernel/filesys/tree.go b/kernel/filesys/tree.go index 845075d09..dd8d5ce19 100644 --- a/kernel/filesys/tree.go +++ b/kernel/filesys/tree.go @@ -91,6 +91,9 @@ func LoadTree(boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err erro } ial := ReadDocIAL(parentData) + if 1 > len(ial) { + logging.LogWarnf("tree [%s] is corrupted", filePath) + } title := ial["title"] if "" == title { title = "Untitled" @@ -266,6 +269,10 @@ func parseJSON2Tree(boxID, p string, jsonData []byte, luteEngine *lute.Lute) (re func ReadDocIAL(data []byte) (ret map[string]string) { ret = map[string]string{} - jsoniter.Get(data, "Properties").ToVal(&ret) + val := jsoniter.Get(data, "Properties") + if nil == val || val.ValueType() == jsoniter.InvalidValue { + return + } + val.ToVal(&ret) return } diff --git a/kernel/model/block.go b/kernel/model/block.go index 1cc22caba..40d85a4de 100644 --- a/kernel/model/block.go +++ b/kernel/model/block.go @@ -25,7 +25,6 @@ import ( "github.com/88250/lute/ast" "github.com/88250/lute/parse" "github.com/siyuan-note/siyuan/kernel/sql" - "github.com/siyuan-note/siyuan/kernel/task" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -383,31 +382,33 @@ func GetBlockKramdown(id string) (ret string) { return } -func GetBlock(id string) (ret *Block, err error) { - ret, err = getBlock(id) +func GetBlock(id string, tree *parse.Tree) (ret *Block, err error) { + ret, err = getBlock(id, tree) return } -func getBlock(id string) (ret *Block, err error) { +func getBlock(id string, tree *parse.Tree) (ret *Block, err error) { if "" == id { return } - tree, err := loadTreeByBlockID(id) - if nil != err { - if task.ContainIndexTask() { - err = ErrIndexing - return - } - - time.Sleep(1 * time.Second) + if nil == tree { tree, err = loadTreeByBlockID(id) if nil != err { - return + time.Sleep(1 * time.Second) + tree, err = loadTreeByBlockID(id) + if nil != err { + return + } } } node := treenode.GetNodeInTree(tree, id) + if nil == node { + err = ErrBlockNotFound + return + } + sqlBlock := sql.BuildBlockFromNode(node, tree) if nil == sqlBlock { return diff --git a/kernel/model/export.go b/kernel/model/export.go index b082ab3e5..f29212648 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -20,8 +20,6 @@ import ( "bytes" "errors" "fmt" - "github.com/imroc/req/v3" - "github.com/siyuan-note/httpclient" "net/http" "net/url" "os" @@ -44,7 +42,9 @@ import ( "github.com/88250/pdfcpu/pkg/pdfcpu" "github.com/emirpasic/gods/sets/hashset" "github.com/emirpasic/gods/stacks/linkedliststack" + "github.com/imroc/req/v3" "github.com/siyuan-note/filelock" + "github.com/siyuan-note/httpclient" "github.com/siyuan-note/logging" "github.com/siyuan-note/siyuan/kernel/sql" "github.com/siyuan-note/siyuan/kernel/treenode" @@ -1443,7 +1443,7 @@ func exportTree(tree *parse.Tree, wysiwyg, expandKaTexMacros, keepFold bool, } if addTitle { - if root, _ := getBlock(id); nil != root { + if root, _ := getBlock(id, tree); nil != root { title := &ast.Node{Type: ast.NodeHeading, HeadingLevel: 1, KramdownIAL: parse.Map2IAL(root.IAL)} content := html.UnescapeString(root.Content) title.AppendChild(&ast.Node{Type: ast.NodeText, Tokens: []byte(content)}) diff --git a/kernel/model/file.go b/kernel/model/file.go index 613600cc0..d3db4fd53 100644 --- a/kernel/model/file.go +++ b/kernel/model/file.go @@ -892,18 +892,12 @@ func renameWriteJSONQueue(tree *parse.Tree, oldHPath string) (err error) { return } -func DuplicateDoc(rootID string) (ret *parse.Tree, err error) { +func DuplicateDoc(tree *parse.Tree) { msgId := util.PushMsg(Conf.Language(116), 30000) defer util.PushClearMsg(msgId) - WaitForWritingFiles() - ret, err = loadTreeByBlockID(rootID) - if nil != err { - return - } - - resetTree(ret, "Duplicated") - createTreeTx(ret) + resetTree(tree, "Duplicated") + createTreeTx(tree) WaitForWritingFiles() return } diff --git a/kernel/model/heading.go b/kernel/model/heading.go index 79f507578..c60e604de 100644 --- a/kernel/model/heading.go +++ b/kernel/model/heading.go @@ -245,7 +245,7 @@ func Heading2Doc(srcHeadingID, targetBoxID, targetPath string) (srcRootBlockID, } srcRootBlockID = srcTree.Root.ID - headingBlock, err := getBlock(srcHeadingID) + headingBlock, err := getBlock(srcHeadingID, srcTree) if nil != err { return } diff --git a/kernel/model/path.go b/kernel/model/path.go index b40396814..d775e706a 100644 --- a/kernel/model/path.go +++ b/kernel/model/path.go @@ -87,7 +87,7 @@ func toFlatTree(blocks []*Block, baseDepth int, typ string) (ret []*Path) { for _, block := range blocks { root := getBlockIn(blockRoots, block.RootID) if nil == root { - root, _ = getBlock(block.RootID) + root, _ = getBlock(block.RootID, nil) blockRoots = append(blockRoots, root) } if nil == root { @@ -134,7 +134,7 @@ func toSubTree(blocks []*Block, keyword string) (ret []*Path) { for _, block := range blocks { root := getBlockIn(blockRoots, block.RootID) if nil == root { - root, _ = getBlock(block.RootID) + root, _ = getBlock(block.RootID, nil) blockRoots = append(blockRoots, root) } block.Depth = 1 @@ -195,11 +195,11 @@ func toSubTree(blocks []*Block, keyword string) (ret []*Path) { } } for next := li.FirstChild.Next; nil != next; next = next.Next { - subBlock, _ := getBlock(next.ID) + subBlock, _ := getBlock(next.ID, tree) if unfold { if ast.NodeList == next.Type { for subLi := next.FirstChild; nil != subLi; subLi = subLi.Next { - subLiBlock, _ := getBlock(subLi.ID) + subLiBlock, _ := getBlock(subLi.ID, tree) var subFirst *sql.Block if 3 != subLi.ListData.Typ { subFirst = sql.GetBlock(subLi.FirstChild.ID) @@ -224,7 +224,7 @@ func toSubTree(blocks []*Block, keyword string) (ret []*Path) { headingChildren := treenode.HeadingChildren(next) var breakSub bool for _, n := range headingChildren { - block, _ := getBlock(n.ID) + block, _ := getBlock(n.ID, tree) subPos := 0 content := block.Content if "" != keyword { @@ -295,7 +295,7 @@ func toSubTree(blocks []*Block, keyword string) (ret []*Path) { for _, headingChild := range headingChildren { if ast.NodeList == headingChild.Type { for subLi := headingChild.FirstChild; nil != subLi; subLi = subLi.Next { - subLiBlock, _ := getBlock(subLi.ID) + subLiBlock, _ := getBlock(subLi.ID, tree) var subFirst *sql.Block if 3 != subLi.ListData.Typ { subFirst = sql.GetBlock(subLi.FirstChild.ID) @@ -315,7 +315,7 @@ func toSubTree(blocks []*Block, keyword string) (ret []*Path) { subRoot.Blocks = append(subRoot.Blocks, subLiBlock) } } else { - subBlock, _ := getBlock(headingChild.ID) + subBlock, _ := getBlock(headingChild.ID, tree) subBlock.Depth = 2 subRoot.Blocks = append(subRoot.Blocks, subBlock) } diff --git a/kernel/model/tree.go b/kernel/model/tree.go index 18fbe81bc..1bcd94727 100644 --- a/kernel/model/tree.go +++ b/kernel/model/tree.go @@ -30,6 +30,7 @@ import ( "github.com/siyuan-note/filelock" "github.com/siyuan-note/logging" "github.com/siyuan-note/siyuan/kernel/filesys" + "github.com/siyuan-note/siyuan/kernel/task" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -145,6 +146,10 @@ var ( ErrIndexing = errors.New("indexing") ) +func LoadTreeByID(id string) (ret *parse.Tree, err error) { + return loadTreeByBlockID(id) +} + func loadTreeByBlockID(id string) (ret *parse.Tree, err error) { if "" == id { return nil, ErrTreeNotFound @@ -152,6 +157,11 @@ func loadTreeByBlockID(id string) (ret *parse.Tree, err error) { bt := treenode.GetBlockTree(id) if nil == bt { + if task.ContainIndexTask() { + err = ErrIndexing + return + } + return nil, ErrBlockNotFound } ret, err = LoadTree(bt.BoxID, bt.Path) diff --git a/kernel/sql/block_query.go b/kernel/sql/block_query.go index c8dd627f2..0b450083c 100644 --- a/kernel/sql/block_query.go +++ b/kernel/sql/block_query.go @@ -95,25 +95,6 @@ func (block *Block) IsContainerBlock() bool { return false } -func IsBlockFolded(id string) (ret bool) { - sqlStmt := "SELECT parent_id, ial FROM blocks WHERE id = ? AND type != 'd'" - for i := 0; i < 64; i++ { - row := queryRow(sqlStmt, id) - var pid, ial string - if err := row.Scan(&pid, &ial); nil != err { - if sql.ErrNoRows != err { - logging.LogErrorf("query scan field failed: %s", err) - } - return - } - id = pid - if strings.Contains(ial, "fold=\"1\"") { - return true - } - } - return -} - func queryBlockChildrenIDs(id string) (ret []string) { ret = append(ret, id) childIDs := queryBlockIDByParentID(id)