Add storage code to handle projecty structure and old projects

This commit is contained in:
Veronica Berglyd Olsen
2022-11-05 16:15:26 +01:00
parent 2e590b742f
commit 407e7fa69e
4 changed files with 154 additions and 62 deletions
+140 -7
View File
@@ -57,6 +57,32 @@ class NWStorage:
self._openMode = self.MODE_INACTIVE
return
##
# Properties
##
@property
def runtimePath(self):
return self._runtimePath
@property
def contentPath(self):
if self._runtimePath is not None:
return self._runtimePath / "content"
return None
@property
def metaPath(self):
if self._runtimePath is not None:
return self._runtimePath / "meta"
return None
@property
def cachePath(self):
if self._runtimePath is not None:
return self._runtimePath / "cache"
return None
##
# Core Methods
##
@@ -70,19 +96,20 @@ class NWStorage:
"""Open a novelWriter project in-place. That is, it is opened
directly from a project folder.
"""
inPath = Path(path)
inPath = Path(path).resolve()
if inPath.is_file():
# The path should not point to an exisitng file,
# but it can point to a folder containing files
inPath = inPath.parent
if not inPath.is_dir():
logger.error("No such folder: %s", inPath)
self.clear()
return False
self._storagePath = inPath
self._runtimePath = inPath
self._openMode = self.MODE_INPLACE
if self._prepareStorage(checkLegacy=True) is False:
self.clear()
return False
return True
def openProjectArchive(self, path):
@@ -142,10 +169,116 @@ class NWStorage:
def _zipIt(self, target):
pass
def _reeadLockFile(self):
def _readLockFile(self):
pass
def _writeLockFile(self):
pass
def _prepareStorage(self, checkLegacy=True):
"""Prepare the storage area for the project.
"""
path = self._runtimePath
if path is None:
logger.error("No path set")
self.clear()
return False
if path == Path.home().absolute():
logger.error("Cannot use the user's home path as the root of a project")
self.clear()
return False
# The folder is not required to exist, as it could be a new
# project, so we make sure it does. Then we add subfolders.
try:
path.mkdir(exist_ok=True)
(path / "content").mkdir(exist_ok=True)
(path / "cache").mkdir(exist_ok=True)
(path / "meta").mkdir(exist_ok=True)
except Exception as exc:
logger.error("Failed to create required project folders", exc_info=exc)
return False
if not checkLegacy:
# The legacy content check is only needed for project folder
# storage, so if it is not expected to be that, there's no
# need for the remaning checks.
return True
# Check for legacy data folders
for child in path.iterdir():
if child.is_dir() and child.name.startswith("data_"):
self._legacyDataFolder(path, child)
# Check for no longer used files, and delete them
self._deleteDeprecatedFiles(path)
return True
##
# Legacy Project Data Handlers
##
def _legacyDataFolder(self, path: Path, child: Path):
"""Handle the content of a legacy data folder from a version 1.0
project.
"""
logger.info("Processing legacy data folder: %s", path)
# Move Documents to Content
first = child.name[-1]
if first not in "0123456789abcdef":
return
for item in child.iterdir():
if not item.is_file():
continue
name = item.name
if len(name) == 21 and name.endswith("_main.nwd"):
newPath = path / "content" / f"{first}{name[:12]}.nwd"
try:
item.rename(newPath)
logger.info("Moved file: %s", newPath)
except Exception as exc:
logger.warning("Failed to move: %s", item, exc_info=exc)
elif len(name) == 21 and name.endswith("_main.bak"):
try:
item.unlink()
logger.info("Deleted file: %s", item)
except Exception as exc:
logger.warning("Failed to delete: %s", item, exc_info=exc)
# Remove Data Folder
try:
child.rmdir()
logger.info("Deleted folder: %s", child)
except Exception as exc:
logger.warning("Failed to delete: %s", child, exc_info=exc)
return
def _deleteDeprecatedFiles(self, path: Path):
"""Delete files that are no longer used by novelWriter.
"""
remove = [
path / "meta" / "mainOptions.json",
path / "meta" / "exportOptions.json",
path / "meta" / "outlineOptions.json",
path / "meta" / "timelineOptions.json",
path / "meta" / "docMergeOptions.json",
path / "meta" / "sessionLogOptions.json",
path / "ToC.json",
]
for item in remove:
if item.is_file():
try:
item.unlink()
logger.info("Deleted: %s", item)
except Exception as exc:
logger.warning("Failed to delete: %s", item, exc_info=exc)
return
# END Class NWStorage