From 9fe364ef8605d9e7e3c8598d25947b1cfe38b499 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Tue, 11 Dec 2012 14:18:35 -0600 Subject: [PATCH 1/8] testing branch --- resources/settings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/settings.xml b/resources/settings.xml index 4774662..8f167e2 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -14,6 +14,7 @@ + From 052cd1a062bd064e16b9846c758491b591494d40 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Mon, 28 Jan 2013 15:44:22 -0600 Subject: [PATCH 2/8] can now backup custom directories - other functions stripped out for now --- resources/lib/backup.py | 224 +++++++++++++++++----------------------- resources/lib/vfs.py | 15 ++- resources/settings.xml | 2 +- 3 files changed, 108 insertions(+), 133 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index a798ad3..4c87091 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -7,54 +7,13 @@ import time from vfs import XBMCFileSystem,DropboxFileSystem class FileManager: - fileArray = None - verbose_log = False + fileArray = [] not_dir = ['.zip','.xsp','.rar'] vfs = None - + def __init__(self,vfs): self.vfs = vfs - - def createFileList(self): - self.fileArray = [] - self.verbose_log = utils.getSetting("verbose_log") == 'true' - - #figure out which syncing options to run - if(utils.getSetting('backup_addons') == 'true'): - self.addFile("-addons") - self.walkTree(self.vfs.root_path + "addons/") - self.addFile("-userdata") - - if(utils.getSetting('backup_addon_data') == 'true'): - self.addFile("-userdata/addon_data") - self.walkTree(self.vfs.root_path + "userdata/addon_data/") - - if(utils.getSetting('backup_database') == 'true'): - self.addFile("-userdata/Database") - self.walkTree(self.vfs.root_path + "userdata/Database") - - if(utils.getSetting("backup_playlists") == 'true'): - self.addFile("-userdata/playlists") - self.walkTree(self.vfs.root_path + "userdata/playlists") - - if(utils.getSetting("backup_thumbnails") == "true"): - self.addFile("-userdata/Thumbnails") - self.walkTree(self.vfs.root_path + "userdata/Thumbnails") - - if(utils.getSetting("backup_config") == "true"): - self.addFile("-userdata/keymaps") - self.walkTree(self.vfs.root_path + "userdata/keymaps") - - self.addFile("-userdata/peripheral_data") - self.walkTree(self.vfs.root_path + "userdata/peripheral_data") - - #this part is an oddity - dirs,configFiles = self.vfs.listdir(self.vfs.root_path + "userdata/") - for aFile in configFiles: - if(aFile.endswith(".xml")): - self.addFile("userdata/" + aFile) - def walkTree(self,directory): dirs,files = self.vfs.listdir(directory) @@ -62,7 +21,7 @@ class FileManager: for aDir in dirs: dirPath = xbmc.translatePath(directory + "/" + aDir) file_ext = aDir.split('.')[-1] - self.addFile("-" + dirPath[len(self.vfs.root_path):]) + self.addFile("-" + dirPath) #catch for "non directory" type files if (not any(file_ext in s for s in self.not_dir)): self.walkTree(dirPath) @@ -70,7 +29,7 @@ class FileManager: #copy all the files for aFile in files: filePath = xbmc.translatePath(directory + "/" + aFile) - self.addFile(filePath[len(self.vfs.root_path):]) + self.addFile(filePath) def addFile(self,filename): try: @@ -82,8 +41,10 @@ class FileManager: utils.log("Add File: " + filename,xbmc.LOGDEBUG) self.fileArray.append(filename) - def getFileList(self): - return self.fileArray + def getFiles(self): + result = self.fileArray + self.fileArray = [] + return result class XbmcBackup: #constants for initiating a back or restore @@ -91,7 +52,7 @@ class XbmcBackup: Restore = 1 #remote file system - local_vfs = None + xbmc_vfs = None remote_vfs = None restoreFile = None @@ -102,26 +63,21 @@ class XbmcBackup: fileManager = None restore_point = None - - def __init__(self): - self.local_vfs = XBMCFileSystem() - self.local_vfs.set_root(xbmc.translatePath("special://home")) - self.configureVFS() - + def __init__(self): + self.xbmc_vfs = XBMCFileSystem(xbmc.translatePath('special://home')) + + self.configureRemote() utils.log(utils.getString(30046)) - def configureVFS(self): + def configureRemote(self): if(utils.getSetting('remote_selection') == '1'): - self.remote_vfs = XBMCFileSystem() - self.remote_vfs.set_root(utils.getSetting('remote_path_2')) + self.remote_vfs = XBMCFileSystem(utils.getSetting('remote_path_2')) utils.setSetting("remote_path","") elif(utils.getSetting('remote_selection') == '0'): - self.remote_vfs = XBMCFileSystem() - self.remote_vfs.set_root(utils.getSetting("remote_path")) + self.remote_vfs = XBMCFileSystem(utils.getSetting("remote_path")) elif(utils.getSetting('remote_selection') == '2'): - self.remote_vfs = DropboxFileSystem() - self.remote_vfs.set_root('/') + self.remote_vfs = DropboxFileSystem("/") def listBackups(self): result = list() @@ -138,7 +94,6 @@ class XbmcBackup: self.restore_point = restore_point def run(self,mode=-1,runSilent=False): - #append backup folder name remote_base_path = "" progressBarTitle = utils.getString(30010) + " - " @@ -154,7 +109,7 @@ class XbmcBackup: self.remote_vfs = None return - utils.log(utils.getString(30047) + ": " + self.local_vfs.root_path) + utils.log(utils.getString(30047) + ": " + self.xbmc_vfs.root_path) utils.log(utils.getString(30048) + ": " + self.remote_vfs.root_path) #check if we should use the progress bar @@ -162,103 +117,114 @@ class XbmcBackup: self.progressBar = xbmcgui.DialogProgress() self.progressBar.create(progressBarTitle,utils.getString(30049) + "......") - #run the correct mode if(mode == self.Backup): utils.log(utils.getString(30023) + " - " + utils.getString(30016)) - self.fileManager = FileManager(self.local_vfs) - #for backups check if remote path exists if(self.remote_vfs.exists(self.remote_vfs.root_path)): #this will fail - need a disclaimer here utils.log(utils.getString(30050)) - - self.syncFiles() - - #remove old backups - total_backups = int(utils.getSetting('backup_rotation')) - if(total_backups > 0): - - dirs,files = self.remote_vfs.listdir(remote_base_path) - if(len(dirs) > total_backups): - #remove backups to equal total wanted - dirs.sort() - remove_num = len(dirs) - total_backups - 1 - self.filesTotal = self.filesTotal + remove_num + 1 - - #update the progress bar if it is available - while(remove_num >= 0 and not self.checkCancel()): - self.updateProgress(utils.getString(30054) + " " + dirs[remove_num]) - utils.log("Removing backup " + dirs[remove_num]) - self.remote_vfs.rmdir(remote_base_path + dirs[remove_num] + "/") - remove_num = remove_num - 1 - - - else: - utils.log(utils.getString(30023) + " - " + utils.getString(30017)) - self.fileManager = FileManager(self.remote_vfs) - - #for restores remote path must exist - if(self.remote_vfs.exists(self.remote_vfs.root_path)): - self.restoreFiles() else: - xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30045),self.remote_vfs.root_path) + #make the remote directory + self.remote_vfs.mkdir(self.remote_vfs.root_path) - if(utils.getSetting('run_silent') == 'false' and not runSilent): - self.progressBar.close() + utils.log(utils.getString(30051)) + fileManager = FileManager(self.xbmc_vfs) + + #go through each of the user selected items and write them to the backup store + if(utils.getSetting('backup_addons') == 'true'): + self.remote_vfs.mkdir(self.remote_vfs.root_path + "addons") + fileManager.walkTree(xbmc.translatePath('special://home/addons')) + + self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata") + + if(utils.getSetting('backup_addon_data') == 'true'): + self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/addon_data") + fileManager.walkTree(xbmc.translatePath('special://home/userdata/addon_data')) + + if(utils.getSetting('backup_database') == 'true'): + self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/Database") + fileManager.walkTree(xbmc.translatePath('special://home/userdata/Database')) - def syncFiles(self): - - #make the remote directory - self.remote_vfs.mkdir(self.remote_vfs.root_path) + if(utils.getSetting("backup_playlists") == 'true'): + self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/playlists") + fileManager.walkTree(xbmc.translatePath('special://home/userdata/playlists')) + + if(utils.getSetting("backup_thumbnails") == "true"): + self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/Thumbnails") + fileManager.walkTree(xbmc.translatePath('special://home/userdata/Thumbnails')) + + if(utils.getSetting("backup_config") == "true"): + self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/keymaps") + fileManager.walkTree(xbmc.translatePath('special://home/userdata/keymaps')) + + self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/peripheral_data") + fileManager.walkTree(xbmc.translatePath('special://home/userdata/peripheral_data')) + + #this part is an oddity + dirs,configFiles = self.xbmc_vfs.listdir(xbmc.translatePath('special://home/userdata/')) + for aFile in configFiles: + if(aFile.endswith(".xml")): + fileManager.addFile(xbmc.translatePath('special://home/userdata/') + aFile) - utils.log(utils.getString(30051)) - self.fileManager.createFileList() + #backup all the files + self.backupFiles(fileManager.getFiles(),self.xbmc_vfs,self.remote_vfs) - allFiles = self.fileManager.getFileList() + #check if there are custom directories + if(utils.getSetting('backup_custom_dir') != ''): + self._updateProgress(utils.getString(30049) + "......") - #write list from local to remote - self.writeFiles(allFiles,self.local_vfs,self.remote_vfs) - - def restoreFiles(self): - self.fileManager.createFileList() + #create a special remote path with hash + self.xbmc_vfs.set_root(utils.getSetting('backup_custom_dir')) + self.remote_vfs.mkdir(self.remote_vfs.root_path + "custom_1_" + self._createCRC(self.xbmc_vfs.root_path)) + self.remote_vfs.set_root(self.remote_vfs.root_path + "custom_1_" + self._createCRC(self.xbmc_vfs.root_path)) - utils.log(utils.getString(30051)) - allFiles = self.fileManager.getFileList() + fileManager.walkTree(self.xbmc_vfs.root_path) + self.backupFiles(fileManager.getFiles(),self.xbmc_vfs,self.remote_vfs) + - #write list from remote to local - self.writeFiles(allFiles,self.remote_vfs,self.local_vfs) - - #call update addons to refresh everything - xbmc.executebuiltin('UpdateLocalAddons') - - def writeFiles(self,fileList,source,dest): + def backupFiles(self,fileList,source,dest): utils.log("Writing files to: " + dest.root_path) self.filesTotal = len(fileList) self.filesLeft = self.filesTotal - #write each file from source to destination for aFile in fileList: - if(not self.checkCancel()): - utils.log('Writing file: ' + source.root_path + aFile,xbmc.LOGDEBUG) - self.updateProgress(aFile) - if (aFile.startswith("-")): - dest.mkdir(dest.root_path + aFile[1:]) + if(not self._checkCancel()): + utils.log('Writing file: ' + aFile,xbmc.LOGDEBUG) + self._updateProgress(aFile) + if(aFile.startswith("-")): + dest.mkdir(dest.root_path + aFile[len(source.root_path) + 1:]) else: if(isinstance(source,DropboxFileSystem)): #if copying from dropbox we need the file handle, use get_file - source.get_file(source.root_path + aFile,dest.root_path + aFile) + source.get_file(aFile,dest.root_path + aFile[len(source.root_path):]) else: #copy using normal method - dest.put(source.root_path + aFile,dest.root_path + aFile) + dest.put(aFile,dest.root_path + aFile[len(source.root_path):]) - def updateProgress(self,message=''): + def _createCRC(self,string): + #create hash from string + string = string.lower() + bytes = bytearray(string.encode()) + crc = 0xffffffff; + for b in bytes: + crc = crc ^ (b << 24) + for i in range(8): + if (crc & 0x80000000 ): + crc = (crc << 1) ^ 0x04C11DB7 + else: + crc = crc << 1; + crc = crc & 0xFFFFFFFF + + return '%08x' % crc + + def _updateProgress(self,message=''): self.filesLeft = self.filesLeft - 1 #update the progress bar if(self.progressBar != None): self.progressBar.update(int((float(self.filesTotal - self.filesLeft)/float(self.filesTotal)) * 100),message) - def checkCancel(self): + def _checkCancel(self): result = False if(self.progressBar != None): diff --git a/resources/lib/vfs.py b/resources/lib/vfs.py index 2d7a1d0..566374a 100644 --- a/resources/lib/vfs.py +++ b/resources/lib/vfs.py @@ -11,6 +11,12 @@ APP_SECRET = utils.getSetting('dropbox_secret') class Vfs: root_path = None + def __init(self): + pass + + def __init__(self,rootString): + self.set_root(rootString) + def set_root(self,rootString): old_root = self.root_path self.root_path = rootString @@ -44,7 +50,7 @@ class Vfs: return True class XBMCFileSystem(Vfs): - + def listdir(self,directory): return xbmcvfs.listdir(directory) @@ -63,7 +69,11 @@ class XBMCFileSystem(Vfs): class DropboxFileSystem(Vfs): client = None - def __init__(self): + def __init__(self,rootString): + self.setup() + Vfs.__init__(rootString) + + def setup(self): if(APP_KEY == '' or APP_SECRET == ''): xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30058),utils.getString(30059)) return @@ -94,7 +104,6 @@ class DropboxFileSystem(Vfs): except: #this didn't work, delete the token file self.deleteToken() - def listdir(self,directory): if(self.client != None and self.exists(directory)): diff --git a/resources/settings.xml b/resources/settings.xml index c2162fd..0622cf7 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -16,7 +16,7 @@ - + From 2d123318d90e117d926330f114c70e73c9f09354 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Tue, 29 Jan 2013 10:34:48 -0600 Subject: [PATCH 3/8] got progress bar to work correctly again --- resources/lib/backup.py | 110 ++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 49 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index 4c87091..6cbe990 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -6,46 +6,6 @@ import os.path import time from vfs import XBMCFileSystem,DropboxFileSystem -class FileManager: - fileArray = [] - not_dir = ['.zip','.xsp','.rar'] - vfs = None - - def __init__(self,vfs): - self.vfs = vfs - - def walkTree(self,directory): - dirs,files = self.vfs.listdir(directory) - - #create all the subdirs first - for aDir in dirs: - dirPath = xbmc.translatePath(directory + "/" + aDir) - file_ext = aDir.split('.')[-1] - self.addFile("-" + dirPath) - #catch for "non directory" type files - if (not any(file_ext in s for s in self.not_dir)): - self.walkTree(dirPath) - - #copy all the files - for aFile in files: - filePath = xbmc.translatePath(directory + "/" + aFile) - self.addFile(filePath) - - def addFile(self,filename): - try: - filename = filename.decode('UTF-8') - except UnicodeDecodeError: - filename = filename.decode('ISO-8859-2') - - #write the full remote path name of this file - utils.log("Add File: " + filename,xbmc.LOGDEBUG) - self.fileArray.append(filename) - - def getFiles(self): - result = self.fileArray - self.fileArray = [] - return result - class XbmcBackup: #constants for initiating a back or restore Backup = 0 @@ -119,15 +79,16 @@ class XbmcBackup: if(mode == self.Backup): utils.log(utils.getString(30023) + " - " + utils.getString(30016)) - #for backups check if remote path exists + #check if remote path exists if(self.remote_vfs.exists(self.remote_vfs.root_path)): - #this will fail - need a disclaimer here + #may be data in here already utils.log(utils.getString(30050)) else: #make the remote directory self.remote_vfs.mkdir(self.remote_vfs.root_path) utils.log(utils.getString(30051)) + allFiles = [] fileManager = FileManager(self.xbmc_vfs) #go through each of the user selected items and write them to the backup store @@ -166,12 +127,12 @@ class XbmcBackup: if(aFile.endswith(".xml")): fileManager.addFile(xbmc.translatePath('special://home/userdata/') + aFile) - #backup all the files - self.backupFiles(fileManager.getFiles(),self.xbmc_vfs,self.remote_vfs) + #add to array + self.filesTotal = fileManager.size() + allFiles.append({"source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()}) #check if there are custom directories if(utils.getSetting('backup_custom_dir') != ''): - self._updateProgress(utils.getString(30049) + "......") #create a special remote path with hash self.xbmc_vfs.set_root(utils.getSetting('backup_custom_dir')) @@ -179,14 +140,22 @@ class XbmcBackup: self.remote_vfs.set_root(self.remote_vfs.root_path + "custom_1_" + self._createCRC(self.xbmc_vfs.root_path)) fileManager.walkTree(self.xbmc_vfs.root_path) - self.backupFiles(fileManager.getFiles(),self.xbmc_vfs,self.remote_vfs) + self.filesTotal = self.filesTotal + fileManager.size() + allFiles.append({"source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()}) + + #backup all the files + self.filesLeft = self.filesTotal + for fileGroup in allFiles: + self.xbmc_vfs.set_root(fileGroup['source']) + self.remote_vfs.set_root(fileGroup['dest']) + self.backupFiles(fileGroup['files'],self.xbmc_vfs,self.remote_vfs) + + #remove old backups def backupFiles(self,fileList,source,dest): utils.log("Writing files to: " + dest.root_path) - self.filesTotal = len(fileList) - self.filesLeft = self.filesTotal - + utils.log("Source: " + source.root_path) for aFile in fileList: if(not self._checkCancel()): utils.log('Writing file: ' + aFile,xbmc.LOGDEBUG) @@ -231,3 +200,46 @@ class XbmcBackup: result = self.progressBar.iscanceled() return result + +class FileManager: + fileArray = [] + not_dir = ['.zip','.xsp','.rar'] + vfs = None + + def __init__(self,vfs): + self.vfs = vfs + + def walkTree(self,directory): + dirs,files = self.vfs.listdir(directory) + + #create all the subdirs first + for aDir in dirs: + dirPath = xbmc.translatePath(directory + "/" + aDir) + file_ext = aDir.split('.')[-1] + self.addFile("-" + dirPath) + #catch for "non directory" type files + if (not any(file_ext in s for s in self.not_dir)): + self.walkTree(dirPath) + + #copy all the files + for aFile in files: + filePath = xbmc.translatePath(directory + "/" + aFile) + self.addFile(filePath) + + def addFile(self,filename): + try: + filename = filename.decode('UTF-8') + except UnicodeDecodeError: + filename = filename.decode('ISO-8859-2') + + #write the full remote path name of this file + utils.log("Add File: " + filename,xbmc.LOGDEBUG) + self.fileArray.append(filename) + + def getFiles(self): + result = self.fileArray + self.fileArray = [] + return result + + def size(self): + return len(self.fileArray) From 9165f8b2dc31d1d68cc025b90c8b0fb22eed5fc1 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Tue, 29 Jan 2013 10:38:08 -0600 Subject: [PATCH 4/8] added backup rotation --- resources/lib/backup.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index 6cbe990..2f01458 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -151,7 +151,22 @@ class XbmcBackup: self.backupFiles(fileGroup['files'],self.xbmc_vfs,self.remote_vfs) #remove old backups - + total_backups = int(utils.getSetting('backup_rotation')) + if(total_backups > 0): + + dirs,files = self.remote_vfs.listdir(remote_base_path) + if(len(dirs) > total_backups): + #remove backups to equal total wanted + dirs.sort() + remove_num = len(dirs) - total_backups - 1 + self.filesTotal = self.filesTotal + remove_num + 1 + + #update the progress bar if it is available + while(remove_num >= 0 and not self._checkCancel()): + self._updateProgress(utils.getString(30054) + " " + dirs[remove_num]) + utils.log("Removing backup " + dirs[remove_num]) + self.remote_vfs.rmdir(remote_base_path + dirs[remove_num] + "/") + remove_num = remove_num - 1 def backupFiles(self,fileList,source,dest): utils.log("Writing files to: " + dest.root_path) From 1357d45945a8c304bb085ce86f79eea3f100e3b0 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Tue, 29 Jan 2013 11:00:16 -0600 Subject: [PATCH 5/8] preliminary restore support --- resources/lib/backup.py | 76 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index 2f01458..bdbf305 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -168,6 +168,82 @@ class XbmcBackup: self.remote_vfs.rmdir(remote_base_path + dirs[remove_num] + "/") remove_num = remove_num - 1 + elif (mode == self.Restore): + utils.log(utils.getString(30023) + " - " + utils.getString(30017)) + + #for restores remote path must exist + if(not self.remote_vfs.exists(self.remote_vfs.root_path)): + xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30045),self.remote_vfs.root_path) + return + + utils.log(utils.getString(30051)) + allFiles = [] + fileManager = FileManager(self.remote_vfs) + + #go through each of the user selected items and write them to the backup store + if(utils.getSetting('backup_addons') == 'true'): + self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/addons')) + fileManager.walkTree(self.remote_vfs.root_path + "addons") + + self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata')) + + if(utils.getSetting('backup_addon_data') == 'true'): + self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata/addon_data')) + fileManager.walkTree(self.remote_vfs.root_path + "userdata/addon_data") + + if(utils.getSetting('backup_database') == 'true'): + self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata/Database')) + fileManager.walkTree(self.remote_vfs.root_path + "userdata/Database") + + if(utils.getSetting("backup_playlists") == 'true'): + self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata/playlists')) + fileManager.walkTree(self.remote_vfs.root_path + "userdata/playlists") + + if(utils.getSetting("backup_thumbnails") == "true"): + self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata/Thumbnails')) + fileManager.walkTree(self.remote_vfs.root_path + "userdata/Thumbnails") + + if(utils.getSetting("backup_config") == "true"): + self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata/keymaps')) + fileManager.walkTree(self.remote_vfs.root_path + "userdata/keymaps") + + self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata/peripheral_data')) + fileManager.walkTree(self.remote_vfs.root_path + "userdata/peripheral_data") + + #this part is an oddity + dirs,configFiles = self.remote_vfs.listdir(self.remote_vfs.root_path + "userdata/") + for aFile in configFiles: + if(aFile.endswith(".xml")): + fileManager.addFile(self.remote_vfs.root_path + "userdata/" + aFile) + + #add to array + self.filesTotal = fileManager.size() + allFiles.append({"source":self.remote_vfs.root_path,"dest":self.xbmc_vfs.root_path,"files":fileManager.getFiles()}) + + #check if there are custom directories + if(utils.getSetting('backup_custom_dir') != ''): + + self.xbmc_vfs.set_root(utils.getSetting('backup_custom_dir')) + if(self.remote_vfs.exists(self.remote_vfs.root_path + "custom_1_" + self._createCRC(self.xbmc_vfs.root_path))): + #index files to restore + self.remote_vfs.set_root(self.remote_vfs.root_path + "custom_1_" + self._createCRC(self.xbmc_vfs.root_path)) + + fileManager.walkTree(self.remote_vfs.root_path) + self.filesTotal = self.filesTotal + fileManager.size() + allFiles.append({"source":self.remote_vfs.root_path,"dest":self.xbmc_vfs.root_path,"files":fileManager.getFiles()}) + else: + xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30045),self.remote_vfs.root_path + "custom_1_" + self._createCRC(utils.getSetting('backup_custom_dir'))) + + #restore all the files + self.filesLeft = self.filesTotal + for fileGroup in allFiles: + self.remote_vfs.set_root(fileGroup['source']) + self.xbmc_vfs.set_root(fileGroup['dest']) + self.backupFiles(fileGroup['files'],self.remote_vfs,self.xbmc_vfs) + + if(utils.getSetting('run_silent') == 'false' and not runSilent): + self.progressBar.close() + def backupFiles(self,fileList,source,dest): utils.log("Writing files to: " + dest.root_path) utils.log("Source: " + source.root_path) From 625de8fa71f2e1e2994358a6ff843bbec2f03bc5 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Tue, 29 Jan 2013 11:32:47 -0600 Subject: [PATCH 6/8] updated readme and version --- README.txt | 6 ++++++ addon.xml | 2 +- changelog.txt | 4 ++++ resources/lib/backup.py | 3 +++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/README.txt b/README.txt index 370fac2..633b412 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. +You can also define non-XBMC directories on your device. See "Custom Directories" for more information on how these are handled. + Scheduling: You can also schedule backups to be completed on a set interval via the scheduling area. When it is time for the backup to run it will be executed in the background. @@ -19,6 +21,10 @@ Running the Program: Running the program will allow you to select Backup or Restore as a running mode. Selecting Backup will push files to your remote store using the addon settings you defined. Selecting Restore will give you a list of restore points currently in your remote destination. Selecting one will pull the files matching your selection criteria from the restore point to your local XBMC folders. +Custom Directories: + +You can define custom directories that are not a part of your XBMC folder structure for backup. These create a custom_1_hash folder in your backup destination. The hash for these folders is very important. During a restore if the hash of the file path in Custom 1 does not match the hash in the restore folder it will not move the files. This is to prevent files from being restored to the wrong location in the event you change file paths in the addon settings. A dialog box will let you know if file paths do not match up. + Using Dropbox: diff --git a/addon.xml b/addon.xml index 3a0f316..355536c 100644 --- a/addon.xml +++ b/addon.xml @@ -1,6 +1,6 @@  + name="XBMC Backup" version="0.3.5" provider-name="robweber"> diff --git a/changelog.txt b/changelog.txt index d2f9ded..ce1879f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +Version 0.3.5 + +test of custom directories - only 1 at the moment + Version 0.3.4 added ability to take parameters via RunScript() or JSONRPC.Addons.ExecuteAddon() diff --git a/resources/lib/backup.py b/resources/lib/backup.py index bdbf305..8799afc 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -241,6 +241,9 @@ class XbmcBackup: self.xbmc_vfs.set_root(fileGroup['dest']) self.backupFiles(fileGroup['files'],self.remote_vfs,self.xbmc_vfs) + #call update addons to refresh everything + xbmc.executebuiltin('UpdateLocalAddons') + if(utils.getSetting('run_silent') == 'false' and not runSilent): self.progressBar.close() From 7e703ca08cad3c162b16a8ce8b2a5bb31c3265f9 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Mon, 4 Mar 2013 10:22:09 -0600 Subject: [PATCH 7/8] fixed Dropbox VFS --- resources/lib/vfs.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/resources/lib/vfs.py b/resources/lib/vfs.py index 566374a..88e33a3 100644 --- a/resources/lib/vfs.py +++ b/resources/lib/vfs.py @@ -11,9 +11,6 @@ APP_SECRET = utils.getSetting('dropbox_secret') class Vfs: root_path = None - def __init(self): - pass - def __init__(self,rootString): self.set_root(rootString) @@ -70,8 +67,8 @@ class DropboxFileSystem(Vfs): client = None def __init__(self,rootString): + self.set_root(rootString) self.setup() - Vfs.__init__(rootString) def setup(self): if(APP_KEY == '' or APP_SECRET == ''): @@ -123,6 +120,7 @@ class DropboxFileSystem(Vfs): def mkdir(self,directory): + directory = self._fix_slashes(directory) if(self.client != None): if(not self.exists(directory)): self.client.file_create_folder(directory) @@ -131,12 +129,14 @@ class DropboxFileSystem(Vfs): return False def rmdir(self,directory): + directory = self._fix_slashes(directory) if(self.client != None and self.exists(directory)): self.client.file_delete(directory) else: return False def exists(self,aFile): + aFile = self._fix_slashes(aFile) if(self.client != None): try: meta_data = self.client.metadata(aFile) @@ -147,7 +147,9 @@ class DropboxFileSystem(Vfs): else: return False - def put(self,source,dest): + def put(self,source,dest): + dest = self._fix_slashes(dest) + if(self.client != None): f = open(source,'rb') try: @@ -169,7 +171,10 @@ class DropboxFileSystem(Vfs): out.close() else: return False - + + def _fix_slashes(self,filename): + return filename.replace('\\','/') + def setToken(self,key,secret): #write the token files token_file = open(xbmc.translatePath(utils.data_dir() + "tokens.txt"),'w') From db7f7a02f59e9a8275b7ac0cc6ebba19cdcedcc1 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Mon, 4 Mar 2013 10:27:25 -0600 Subject: [PATCH 8/8] return boolean on complete (match super class) --- resources/lib/vfs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lib/vfs.py b/resources/lib/vfs.py index 88e33a3..9044126 100644 --- a/resources/lib/vfs.py +++ b/resources/lib/vfs.py @@ -169,6 +169,7 @@ class DropboxFileSystem(Vfs): f = self.client.get_file(source).read() out.write(f) out.close() + return True else: return False