Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add automatic index rebuild #975

Merged
merged 2 commits into from
Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 39 additions & 32 deletions novelwriter/core/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def loadIndex(self):

logger.verbose("Index loaded in %.3f ms", (time() - tStart)*1000)

self.checkIndex()
self._checkIndex()

return True

Expand All @@ -182,10 +182,10 @@ def saveIndex(self):
try:
with open(indexFile, mode="w+", encoding="utf-8") as outFile:
outFile.write("{\n")
outFile.write(f'"tagIndex": {jsonEncode(self._tagIndex, nmax=1)},\n')
outFile.write(f'"refIndex": {jsonEncode(self._refIndex, nmax=2)},\n')
outFile.write(f'"fileIndex": {jsonEncode(self._fileIndex, nmax=2)},\n')
outFile.write(f'"fileMeta": {jsonEncode(self._fileMeta, nmax=1)}\n')
outFile.write(f' "tagIndex": {jsonEncode(self._tagIndex, n=1, nmax=2)},\n')
outFile.write(f' "refIndex": {jsonEncode(self._refIndex, n=1, nmax=3)},\n')
outFile.write(f' "fileIndex": {jsonEncode(self._fileIndex, n=1, nmax=3)},\n')
outFile.write(f' "fileMeta": {jsonEncode(self._fileMeta, n=1, nmax=2)}\n')
outFile.write("}\n")

except Exception:
Expand All @@ -197,33 +197,6 @@ def saveIndex(self):

return True

def checkIndex(self):
"""Check that the entries in the index are valid and contain the
elements it should.
"""
logger.debug("Checking index")
tStart = time()

try:
self._checkTagIndex()
self._checkRefIndex()
self._checkFileIndex()
self._checkFileMeta()
self._indexBroken = False

except Exception:
logger.error("Error while checking index")
logException()
self._indexBroken = True

logger.verbose("Index check took %.3f ms", (time() - tStart)*1000)
logger.debug("Index check complete")

if self._indexBroken:
self.clearIndex()

return

##
# Index Building
##
Expand Down Expand Up @@ -687,6 +660,40 @@ def _listNovelHandles(self, skipExcluded):
# Index Checkers
##

def _checkIndex(self):
"""Check that the entries in the index are valid and contain the
elements it should. Also check that each file present in the
contents folder when the project was loaded are also present in
the fileMeta index.
"""
logger.debug("Checking index")
tStart = time()

try:
self._checkTagIndex()
self._checkRefIndex()
self._checkFileIndex()
self._checkFileMeta()
self._indexBroken = False

except Exception:
logger.error("Error while checking index")
logException()
self._indexBroken = True

# Check that project files are indexed
for fHandle in self.theProject.projFiles:
if fHandle not in self._fileMeta:
self._indexBroken = True
break

logger.verbose("Index check completed in %.3f ms", (time() - tStart)*1000)

if self._indexBroken:
self.clearIndex()

return

def _checkTagIndex(self):
"""Scan the tag index for errors.
Warning: This function raises exceptions.
Expand Down
6 changes: 6 additions & 0 deletions novelwriter/core/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def __init__(self, theParent):
self.projSpell = None # The spell check language, if different than default
self.projLang = None # The project language, used for builds
self.projFile = None # The file name of the project main XML file
self.projFiles = [] # A list of all files in the content folder on load

# Project Meta
self.projName = "" # Project name (working title)
Expand Down Expand Up @@ -203,6 +204,7 @@ def clearProject(self):
self.projSpell = None
self.projLang = None
self.projFile = nwFiles.PROJ_FILE
self.projFiles = []
self.projName = ""
self.bookTitle = ""
self.bookAuthors = []
Expand Down Expand Up @@ -1352,18 +1354,22 @@ def _scanProjectFolder(self):
# Then check the files in the data folder
logger.debug("Checking files in project content folder")
orphanFiles = []
self.projFiles = []
for fileItem in os.listdir(self.projContent):
if not fileItem.endswith(".nwd"):
logger.warning("Skipping file: %s", fileItem)
continue
if len(fileItem) != 17:
logger.warning("Skipping file: %s", fileItem)
continue

fHandle = fileItem[:13]
if not isHandle(fHandle):
logger.warning("Skipping file: %s", fileItem)
continue

if fHandle in self.projTree:
self.projFiles.append(fHandle)
logger.debug("Checking file %s, handle '%s': OK", fileItem, fHandle)
else:
logger.warning("Checking file %s, handle '%s': Orphaned", fileItem, fHandle)
Expand Down
3 changes: 1 addition & 2 deletions novelwriter/guimain.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,8 +550,7 @@ def openProject(self, projFile):
), nwAlert.WARN)
self.rebuildIndex()

# Make sure the changed status is set to false on all that was
# just opened
# Make sure the changed status is set to false on things opened
qApp.processEvents()
self.docEditor.setDocumentChanged(False)
self.theProject.setProjectChanged(False)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_core/test_core_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def testCoreIndex_LoadSave(monkeypatch, nwLipsum, mockGUI, outDir, refDir):
# Break the index and check that we notice
assert theIndex.indexBroken is False
theIndex._tagIndex["Bod"].append("Stuff")
theIndex.checkIndex()
theIndex._checkIndex()
assert theIndex.indexBroken is True

# Finalise
Expand Down
4 changes: 1 addition & 3 deletions tests/test_gui/test_gui_docviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ def testGuiViewer_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
nwGUI.theProject.projTree.setSeed(42)
assert nwGUI.openProject(nwLipsum)

# Rebuild the index as it isn't automatically copied
assert nwGUI.theIndex._tagIndex == {}
assert nwGUI.theIndex._refIndex == {}
# Rebuild the index
nwGUI.mainMenu.aRebuildIndex.activate(QAction.Trigger)
assert nwGUI.theIndex._tagIndex != {}
assert nwGUI.theIndex._refIndex != {}
Expand Down
4 changes: 0 additions & 4 deletions tests/test_gui/test_gui_noveltree.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, nwMinimal):
##

nwGUI.projTabs.setCurrentIndex(nwGUI.idxNovelView)

# The tree should be empty as there is no index
assert nwTree.topLevelItemCount() == 0

nwGUI.rebuildIndex()
nwTree._populateTree()
assert nwTree.topLevelItemCount() == 1
Expand Down