From 3d910041cd315b1ab8bb79641fc4b068893aa198 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Fri, 8 May 2020 18:19:09 +0200 Subject: [PATCH 1/2] Moved the backup function to the project class since it was only one function anyway --- nw/gui/mainmenu.py | 6 ++- nw/guimain.py | 11 +---- nw/project/__init__.py | 2 - nw/project/backup.py | 99 ------------------------------------------ nw/project/project.py | 68 +++++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 111 deletions(-) delete mode 100644 nw/project/backup.py diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py index f1021fc3..a37ddf0c 100644 --- a/nw/gui/mainmenu.py +++ b/nw/gui/mainmenu.py @@ -177,6 +177,10 @@ class GuiMainMenu(QMenuBar): self.theParent.docEditor.revealLocation() return True + def _doBackup(self): + self.theProject.zipIt(True) + return True + ## # Menu Builders ## @@ -703,7 +707,7 @@ class GuiMainMenu(QMenuBar): # Tools > Backup self.aBackupProject = QAction("Backup Project", self) self.aBackupProject.setStatusTip("Backup Project") - self.aBackupProject.triggered.connect(self.theParent.backupProject) + self.aBackupProject.triggered.connect(self._doBackup) self.toolsMenu.addAction(self.aBackupProject) # Tools > Settings diff --git a/nw/guimain.py b/nw/guimain.py index 14e0816b..935c1fb2 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -45,7 +45,7 @@ from nw.gui import ( GuiConfigEditor, GuiProjectEditor, GuiItemEditor, GuiProjectOutline, GuiSessionLogView, GuiDocMerge, GuiDocSplit, GuiProjectLoad ) -from nw.project import NWProject, NWDoc, NWIndex, NWBackup +from nw.project import NWProject, NWDoc, NWIndex from nw.tools import countWords from nw.constants import nwFiles, nwItemType, nwAlert @@ -333,7 +333,7 @@ class GuiMain(QMainWindow): if msgRes != QMessageBox.Yes: doBackup = False if doBackup: - self.backupProject() + self.theProject.zipIt(False) else: saveOK = True @@ -450,13 +450,6 @@ class GuiMain(QMainWindow): return True - def backupProject(self): - """Trigger the project backup process. - """ - theBackup = NWBackup(self, self.theProject) - theBackup.zipIt() - return True - ## # Document Actions ## diff --git a/nw/project/__init__.py b/nw/project/__init__.py index b36f5a5e..f2a0fe0c 100644 --- a/nw/project/__init__.py +++ b/nw/project/__init__.py @@ -1,12 +1,10 @@ # -*- coding: utf-8 -*- -from nw.project.backup import NWBackup from nw.project.document import NWDoc from nw.project.index import NWIndex from nw.project.project import NWProject __all__ = [ - "NWBackup", "NWDoc", "NWIndex", "NWProject", diff --git a/nw/project/backup.py b/nw/project/backup.py deleted file mode 100644 index 3b6b61f4..00000000 --- a/nw/project/backup.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -"""novelWriter Project Backup - - novelWriter – Project Backup -============================== - Class handling project backups - - File History: - Created: 2019-06-16 [0.1.5] - - This file is a part of novelWriter - Copyright 2020, Veronica Berglyd Olsen - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -""" - -import logging -import nw - -from os import path -from shutil import make_archive -from datetime import datetime - -from nw.constants import nwAlert - -logger = logging.getLogger(__name__) - -class NWBackup(): - - def __init__(self, theParent, theProject): - self.mainConf = nw.CONFIG - self.theParent = theParent - self.theProject = theProject - return - - def zipIt(self): - - if self.mainConf.backupPath is None or self.mainConf.backupPath == "": - self.theParent.makeAlert(( - "Cannot backup project because no backup path is set. " - "Please set a valid backup location in Tools > Preferences." - ), nwAlert.WARN) - return False - - if self.theProject.projName is None or self.theProject.projName == "": - self.theParent.makeAlert(( - "Cannot backup project because no project name is set. " - "Please set a Working Title in Project > Project Settings." - ), nwAlert.WARN) - return False - - if not path.isdir(self.mainConf.backupPath): - self.theParent.makeAlert(( - "Cannot backup project because the backup path does not exist. " - "Please set a valid backup location in Tools > Preferences." - ), nwAlert.WARN) - return False - - logger.info("Backing up project") - self.theParent.statusBar.setStatus("Backing up project ...") - - archName = "" - for c in self.theProject.projName: - if c.isalnum(): - archName += c - else: - archName += "_" - - archName = archName+"_"+datetime.now().strftime("%Y%m%d-%H%M%S") - baseName = path.join(self.mainConf.backupPath, archName) - - try: - self.theProject._clearLockFile() - make_archive(baseName, "zip", self.theProject.projPath, ".") - self.theProject._writeLockFile() - logger.info("Backup written to: %s" % archName) - except Exception as e: - self.theParent.makeAlert( - ["Could not write backup archive.",str(e)], - nwAlert.ERROR - ) - return False - - self.theParent.statusBar.setStatus("Project backup complete") - - return True - -# END Class NWBackup diff --git a/nw/project/project.py b/nw/project/project.py index cd3fdc55..94881fba 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -38,6 +38,7 @@ from lxml import etree from hashlib import sha256 from datetime import datetime from time import time +from shutil import make_archive from nw.tools import projectMaintenance, OptionState from nw.common import checkString, checkBool, checkInt @@ -478,6 +479,73 @@ class NWProject(): self.lockedBy = None return True + ## + # Backup Project + ## + + def zipIt(self, doNotify): + """Create a zip file of the entire project. + """ + + logger.info("Backing up project") + self.theParent.statusBar.setStatus("Backing up project ...") + + if self.mainConf.backupPath is None or self.mainConf.backupPath == "": + self.theParent.makeAlert(( + "Cannot backup project because no backup path is set. " + "Please set a valid backup location in Tools > Preferences." + ), nwAlert.WARN) + return False + + if self.projName is None or self.projName == "": + self.theParent.makeAlert(( + "Cannot backup project because no project name is set. " + "Please set a Working Title in Project > Project Settings." + ), nwAlert.WARN) + return False + + if not path.isdir(self.mainConf.backupPath): + self.theParent.makeAlert(( + "Cannot backup project because the backup path does not exist. " + "Please set a valid backup location in Tools > Preferences." + ), nwAlert.WARN) + return False + + cleanName = "" + for c in self.projName.strip(): + if c.isalpha() or c.isdigit() or c == " ": + cleanName += c + + baseDir = path.join(self.mainConf.backupPath, cleanName) + if not path.isdir(baseDir): + mkdir(baseDir) + logger.debug("Created folder %s" % baseDir) + + archName = "Backup on %s" % datetime.now().strftime("%Y-%m-%d at %H.%M.%S") + baseName = path.join(baseDir, archName) + + try: + self._clearLockFile() + make_archive(baseName, "zip", self.projPath, ".") + self._writeLockFile() + if doNotify: + self.theParent.makeAlert( + "Backup archive file written to: '%s.zip'" % path.join(cleanName, archName), + nwAlert.INFO + ) + else: + logger.info("Backup written to: %s" % archName) + except Exception as e: + self.theParent.makeAlert( + ["Could not write backup archive.",str(e)], + nwAlert.ERROR + ) + return False + + self.theParent.statusBar.setStatus("Project backed up to '%s.zip'" % baseName) + + return True + ## # Setters ## From 8d4fa4b627a8cc031d66c5a4fba8f71e8801b25e Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Fri, 8 May 2020 18:28:13 +0200 Subject: [PATCH 2/2] Added a try/except to the creation of backup folder --- nw/project/project.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/nw/project/project.py b/nw/project/project.py index 94881fba..fb4f340a 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -518,8 +518,15 @@ class NWProject(): baseDir = path.join(self.mainConf.backupPath, cleanName) if not path.isdir(baseDir): - mkdir(baseDir) - logger.debug("Created folder %s" % baseDir) + try: + mkdir(baseDir) + logger.debug("Created folder %s" % baseDir) + except Exception as e: + self.theParent.makeAlert( + ["Could not create backup folder.",str(e)], + nwAlert.ERROR + ) + return False archName = "Backup on %s" % datetime.now().strftime("%Y-%m-%d at %H.%M.%S") baseName = path.join(baseDir, archName)