From f520d58c6be096a16a1c9013113d6d4ac421c888 Mon Sep 17 00:00:00 2001 From: robweber Date: Sat, 21 Apr 2012 17:18:41 -0500 Subject: [PATCH] added a "restore.txt" document that can be used to reverse the flow from remote to local. Added restore mode in settings --- README.txt | 2 + addon.xml | 4 +- default.py | 184 ++++++++++++++----------- resources/language/English/strings.xml | 3 +- resources/settings.xml | 1 + 5 files changed, 114 insertions(+), 80 deletions(-) diff --git a/README.txt b/README.txt index 81120f6..11a2c08 100644 --- a/README.txt +++ b/README.txt @@ -9,6 +9,8 @@ In the addon settings you can define a remote path for the destination of your x On the Backup Selection page you can select which items from your user profile folder will be sent to the backup location. By default all are turned on except the Addon Data directory. +To restore your data simply switch the Mode from "backup" to "restore" and the files will be copied from your remote directory to the local path. + What this Addon Will Not Do: This is not meant as an XBMC file sync solution. If you have multiple frontends you want to keep in sync this addon may work in a "poor man's" sort of way but it is not intended for that. diff --git a/addon.xml b/addon.xml index 541e40e..b8f658e 100644 --- a/addon.xml +++ b/addon.xml @@ -1,6 +1,6 @@ + name="XBMC Backup" version="0.0.4" provider-name="robweber"> @@ -8,7 +8,7 @@ executable - Backup your XBMC database and configuration files before an upgrade or in the even of a crash. + Backup abd restore your XBMC database and configuration files in the event of a crash or file corruption. Ever hosed your XBMC configuration and wished you'd had a backup? Now you can with one easy click. You can export your database, playlist, thumbnails, addons and other configuration details to any source writeable by XBMC. all diff --git a/default.py b/default.py index 4511c84..5203c41 100644 --- a/default.py +++ b/default.py @@ -4,31 +4,78 @@ import xbmcgui import xbmcvfs import os -class RestoreFile: +class FileManager: + local_path = '' addonDir = '' fHandle = None - + def __init__(self,addon_dir): + self.local_path = xbmc.translatePath("special://home") self.addonDir = addon_dir - def createRestoreFile(self): #create the addon folder if it doesn't exist if(not os.path.exists(unicode(xbmc.translatePath(self.addonDir),'utf-8'))): os.makedirs(unicode(xbmc.translatePath(self.addonDir),'utf-8')) - xbmc.log(self.addonDir) - self.fHandle = open(unicode(xbmc.translatePath(self.addonDir + "restore.txt"),'utf-8'),"w") + def createFileList(self,Addon): + self.fHandle = open(unicode(xbmc.translatePath(self.addonDir + "restore.txt"),'utf-8'),"w") + + #figure out which syncing options to run + if(Addon.getSetting('backup_addons') == 'true'): + self.addFile("-addons") + self.walkTree(self.local_path + "addons/") + + self.addFile("-userdata") + + if(Addon.getSetting('backup_addon_data') == 'true'): + self.addFile("-userdata/addon_data") + self.walkTree(self.local_path + "userdata/addon_data/") + + if(Addon.getSetting('backup_database') == 'true'): + self.addFile("-userdata/Database") + self.walkTree(self.local_path + "userdata/Database") + + if(Addon.getSetting("backup_playlists") == 'true'): + self.addFile("-userdata/playlists") + self.walkTree(self.local_path + "userdata/playlists") + + if(Addon.getSetting("backup_thumbnails") == "true"): + self.addFile("-userdata/Thumbnails") + self.walkTree(self.local_path + "userdata/Thumbnails") + + if(Addon.getSetting("backup_config") == "true"): + #this one is an oddity + configFiles = os.listdir(self.local_path + "userdata/") + for aFile in configFiles: + if(aFile.endswith(".xml")): + self.addFile("userdata/" + aFile) + + if(self.fHandle != None): + self.fHandle.close() + + def walkTree(self,directory): + for (path, dirs, files) in os.walk(directory): + + #get the relative part of this path + path = path[len(self.local_path):] + + #create all the subdirs first + for aDir in dirs: + self.addFile("-" + path + os.sep + aDir) + #copy all the files + for aFile in files: + filePath = path + os.sep + aFile + self.addFile(filePath) + def addFile(self,filename): #write the full remote path name of this file if(self.fHandle != None): self.fHandle.write(str(filename) + "\n") - def closeRestoreFile(self,sendDir): - #close out the file and write it to the remote store - if(self.fHandle != None): - self.fHandle.close() - #xbmcvfs.copy(self.addonDir + "restore.txt",sendDir + "restore.txt") - + def readFileList(self): + allFiles = open(unicode(xbmc.translatePath(self.addonDir + "restore.txt"),'utf-8'),"r").read().splitlines() + + return allFiles class XbmcBackup: __addon_id__ = 'script.xbmcbackup' @@ -39,8 +86,10 @@ class XbmcBackup: #for the progress bar progressBar = None - dirsLeft = 0 - dirsTotal = 0 + filesLeft = 0 + filesTotal = 0 + + fileManager = None def __init__(self): self.local_path = xbmc.translatePath("special://home") @@ -48,92 +97,73 @@ class XbmcBackup: if(self.Addon.getSetting('remote_path') != '' and self.Addon.getSetting("backup_name") != ''): self.remote_path = self.Addon.getSetting("remote_path") + self.Addon.getSetting('backup_name') + "/" - self.restoreFile = RestoreFile(self.Addon.getAddonInfo('profile')) + self.fileManager = FileManager(self.Addon.getAddonInfo('profile')) self.log("Starting") self.log('Local Dir: ' + self.local_path) self.log('Remote Dir: ' + self.remote_path) + + def run(self): + #check what mode were are in + if(int(self.Addon.getSetting('addon_mode')) == 0): + self.syncFiles() + else: + self.restoreFiles() def syncFiles(self): - self.restoreFile.createRestoreFile() - if(xbmcvfs.exists(self.remote_path)): #this will fail - need a disclaimer here self.log("Remote Path exists - may have old files in it!") + #make the remote directory xbmcvfs.mkdir(self.remote_path) + + self.fileManager.createFileList(self.Addon) + allFiles = self.fileManager.readFileList() + + #write list from local to remote + self.writeFiles(allFiles,self.local_path,self.remote_path) + + #write the restore list + xbmcvfs.copy(self.Addon.getAddonInfo('profile') + "restore.txt",self.remote_path + "restore.txt") + + def restoreFiles(self): + #copy the restore file + xbmcvfs.copy(self.remote_path + "restore.txt",self.Addon.getAddonInfo('profile') + "restore.txt") + + allFiles = self.fileManager.readFileList() + + #write list from remote to local + self.writeFiles(allFiles,self.remote_path,self.local_path) + + def writeFiles(self,fileList,source,dest): + self.filesTotal = len(fileList) + self.filesLeft = self.filesTotal + + #check if we should use the progress bar if(self.Addon.getSetting('run_silent') == 'false'): self.progressBar = xbmcgui.DialogProgress() self.progressBar.create('XBMC Backup','Running......') - self.updateProgress(1) - #figure out which syncing options to run - if(self.Addon.getSetting('backup_addons') == 'true' and not self.checkCancel()): - xbmcvfs.mkdir(self.remote_path + "addons") - self.walkTree(self.local_path + "addons/") + #write each file from source to destination + for aFile in fileList: + if(not self.checkCancel()): + self.updateProgress(aFile) + if (aFile.startswith("-")): + xbmcvfs.mkdir(dest + aFile[1:]) + else: + xbmcvfs.copy(source + aFile,dest + aFile) - xbmcvfs.mkdir(self.remote_path + "userdata") - if(self.Addon.getSetting('backup_addon_data') == 'true' and not self.checkCancel()): - xbmcvfs.mkdir(self.remote_path + "userdata/addon_data") - self.walkTree(self.local_path + "userdata/addon_data/") - - if(self.Addon.getSetting('backup_database') == 'true' and not self.checkCancel()): - xbmcvfs.mkdir(self.remote_path + "userdata/Database") - self.walkTree(self.local_path + "userdata/Database") - - if(self.Addon.getSetting("backup_playlists") == 'true' and not self.checkCancel()): - xbmcvfs.mkdir(self.remote_path + "userdata/playlists") - self.walkTree(self.local_path + "userdata/playlists") - - if(self.Addon.getSetting("backup_thumbnails") == "true" and not self.checkCancel()): - xbmcvfs.mkdir(self.remote_path + "userdata/Thumbnails") - self.walkTree(self.local_path + "userdata/Thumbnails") - - if(self.Addon.getSetting("backup_config") == "true" and not self.checkCancel()): - #this one is an oddity - configFiles = os.listdir(self.local_path + "userdata/") - for aFile in configFiles: - if(aFile.endswith(".xml")): - self.log("Copying: " + self.local_path + "userdata/" + aFile) - xbmcvfs.copy(self.local_path + "userdata/" + aFile,self.remote_path + "userdata/" + aFile) - - #close out everything - self.restoreFile.closeRestoreFile(self.remote_path) if(self.Addon.getSetting('run_silent') == 'false'): self.progressBar.close() - - - def walkTree(self,directory): - for (path, dirs, files) in os.walk(directory): - if(not self.checkCancel()): - #get the relative part of this path - path = path[len(self.local_path):] - - #subtract one from total - self.dirsLeft = self.dirsLeft - 1 - self.updateProgress(len(dirs),"Copying: " + path) - #create all the subdirs first - for aDir in dirs: - xbmcvfs.mkdir(self.remote_path + os.sep + path + os.sep + aDir) - self.restoreFile.addFile(path + os.sep + aDir) - #copy all the files - for aFile in files: - filePath = path + os.sep + aFile - self.log("copying: " + self.local_path + filePath) - self.restoreFile.addFile(filePath) - - xbmcvfs.copy(self.local_path + filePath,self.remote_path + filePath) - - def updateProgress(self,dirCount,message=''): - #add to the total - self.dirsTotal = self.dirsTotal + dirCount - self.dirsLeft = self.dirsLeft + dirCount + def updateProgress(self,message=''): + self.filesLeft = self.filesLeft - 1 #update the progress bar if(self.progressBar != None): - self.progressBar.update((float(self.dirsTotal - self.dirsLeft)/float(self.dirsTotal)) * 100,message) + self.progressBar.update((float(self.filesTotal - self.filesLeft)/float(self.filesTotal)) * 100,message) def checkCancel(self): result = False @@ -153,6 +183,6 @@ class XbmcBackup: backup = XbmcBackup() if(backup.isReady()): - backup.syncFiles() + backup.run() else: xbmcgui.Dialog().ok('XBMC Backup','Error: Remote path cannot be empty') diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml index f3e3ae7..f26e003 100644 --- a/resources/language/English/strings.xml +++ b/resources/language/English/strings.xml @@ -2,11 +2,12 @@ XBMC Backup General - Backup Selection + File Selection Remote Path Backup Folder Name Run Silent + Mode User Addons Addon Data diff --git a/resources/settings.xml b/resources/settings.xml index ad15070..acc9813 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -3,6 +3,7 @@ +