diff --git a/kernel/model/index_fix.go b/kernel/model/index_fix.go index c97647c79..f31fc4327 100644 --- a/kernel/model/index_fix.go +++ b/kernel/model/index_fix.go @@ -44,6 +44,8 @@ func FixIndexJob() { task.AppendTask(task.DatabaseIndexFix, removeDuplicateDatabaseIndex) sql.WaitForWritingDatabase() + task.AppendTask(task.DatabaseIndexFix, resetDuplicateTrees) + task.AppendTask(task.DatabaseIndexFix, fixBlockTreeByFileSys) sql.WaitForWritingDatabase() @@ -100,6 +102,68 @@ func removeDuplicateDatabaseIndex() { } } +// resetDuplicateTrees 重置重复 ID 的文档树。 https://github.com/siyuan-note/siyuan/issues/7340 +func resetDuplicateTrees() { + defer logging.Recover() + + autoFixLock.Lock() + defer autoFixLock.Unlock() + + util.PushStatusBar(Conf.Language(58)) + boxes := Conf.GetBoxes() + luteEngine := lute.New() + for _, box := range boxes { + boxPath := filepath.Join(util.DataDir, box.ID) + paths := map[string]string{} + filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error { + if !info.IsDir() && filepath.Ext(path) == ".sy" && !strings.Contains(filepath.ToSlash(path), "/assets/") { + p := path[len(boxPath):] + p = filepath.ToSlash(p) + paths[p] = path + } + return nil + }) + + names := map[string]bool{} + duplicatedPaths := map[string]string{} + for p, absPath := range paths { + name := path.Base(p) + if !names[name] { + names[name] = true + continue + } + + duplicatedPaths[p] = absPath + } + + for p, absPath := range duplicatedPaths { + logging.LogWarnf("exist more than one file with same id [%s], reset it", p) + + tree, loadErr := filesys.LoadTree(box.ID, p, luteEngine) + if nil != loadErr { + logging.LogWarnf("load tree [%s] failed: %s", p, loadErr) + box.moveCorruptedData(absPath) + continue + } + + resetTree(tree, "Duplicated") + createTreeTx(tree) + if gulu.File.IsDir(strings.TrimSuffix(absPath, ".sy")) { + // 重命名子文档文件夹 + if renameErr := os.Rename(strings.TrimSuffix(absPath, ".sy"), filepath.Join(filepath.Dir(absPath), tree.ID)); nil != renameErr { + logging.LogWarnf("rename [%s] failed: %s", absPath, renameErr) + continue + } + } + os.RemoveAll(absPath) + } + + if util.IsExiting { + break + } + } +} + // fixBlockTreeByFileSys 通过文件系统订正块树。 func fixBlockTreeByFileSys() { defer logging.Recover()