From 24385a2c686d3ca53fc0ff318045e50f7dee1517 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Wed, 30 Jul 2014 13:41:54 -0500 Subject: [PATCH 01/17] don't write to remote directly, use file manager --- resources/lib/backup.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index 29a2d9d..0053d05 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -135,36 +135,36 @@ class XbmcBackup: #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.addFile("-addons") fileManager.walkTree(xbmc.translatePath('special://home/addons')) - self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata") + fileManager.addFile("-userdata") if(utils.getSetting('backup_addon_data') == 'true'): - self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/addon_data") + fileManager.addFile("-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.addFile("-userdata/Database") fileManager.walkTree(xbmc.translatePath('special://home/userdata/Database')) if(utils.getSetting("backup_playlists") == 'true'): - self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/playlists") + fileManager.addFile("-userdata/playlists") fileManager.walkTree(xbmc.translatePath('special://home/userdata/playlists')) if(utils.getSetting('backup_profiles') == 'true'): - self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/profiles") + fileManager.addFile("-userdata/profiles") fileManager.walkTree(xbmc.translatePath('special://home/userdata/profiles')) if(utils.getSetting("backup_thumbnails") == "true"): - self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/Thumbnails") + fileManager.addFile("-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.addFile("-userdata/keymaps") fileManager.walkTree(xbmc.translatePath('special://home/userdata/keymaps')) - self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/peripheral_data") + fileManager.addFile("-userdata/peripheral_data") fileManager.walkTree(xbmc.translatePath('special://home/userdata/peripheral_data')) #this part is an oddity @@ -182,7 +182,7 @@ class XbmcBackup: #create a special remote path with hash self.xbmc_vfs.set_root(utils.getSetting('backup_custom_dir_1')) - self.remote_vfs.mkdir(self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path)) + fileManager.addFile("-custom_" + self._createCRC(self.xbmc_vfs.root_path)) #walk the directory fileManager.walkTree(self.xbmc_vfs.root_path) @@ -193,7 +193,7 @@ class XbmcBackup: #create a special remote path with hash self.xbmc_vfs.set_root(utils.getSetting('backup_custom_dir_2')) - self.remote_vfs.mkdir(self.remote_vfs.root_path + "custom_" + self._createCRC(self.xbmc_vfs.root_path)) + fileManager.addFile("-custom_" + self._createCRC(self.xbmc_vfs.root_path)) #walk the directory fileManager.walkTree(self.xbmc_vfs.root_path) From 19fcb8bd4694423c8bb04358d929dfcaa5f69189 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Wed, 30 Jul 2014 15:16:58 -0500 Subject: [PATCH 02/17] created zip vfs, will create and copy directories to remote share --- resources/lib/backup.py | 51 ++++++++++++++++++++++++++++++----------- resources/lib/vfs.py | 40 +++++++++++++++++++++++++++++++- resources/settings.xml | 1 + 3 files changed, 78 insertions(+), 14 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index 0053d05..326471f 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -2,10 +2,9 @@ import xbmc import xbmcgui import xbmcvfs import utils as utils -import os.path import time import json -from vfs import XBMCFileSystem,DropboxFileSystem +from vfs import XBMCFileSystem,DropboxFileSystem,ZipFileSystem def folderSort(aKey): result = aKey[0] @@ -21,9 +20,11 @@ class XbmcBackup: Backup = 0 Restore = 1 - #remote file system + #file systems xbmc_vfs = None remote_vfs = None + saved_remote_vfs = None + restoreFile = None remote_base_path = None @@ -98,15 +99,20 @@ class XbmcBackup: #append backup folder name progressBarTitle = utils.getString(30010) + " - " if(mode == self.Backup and self.remote_vfs.root_path != ''): + if(utils.getSetting("compress_backups") == 'true'): + #save the remote file system and use the zip vfs + self.saved_remote_vfs = self.remote_vfs + self.remote_vfs = ZipFileSystem("","w") + self.remote_vfs.set_root(self.remote_vfs.root_path + time.strftime("%Y%m%d%H%M") + "/") progressBarTitle = progressBarTitle + utils.getString(30016) - elif(mode == self.Restore and self.restore_point != None and self.remote_vfs.root_path != ''): - self.remote_vfs.set_root(self.remote_vfs.root_path + self.restore_point + "/") - progressBarTitle = progressBarTitle + utils.getString(30017) - else: + elif(mode == self.Restore and self.restore_point != None and self.remote_vfs.root_path != ''): + self.remote_vfs.set_root(self.remote_vfs.root_path + self.restore_point + "/") + progressBarTitle = progressBarTitle + utils.getString(30017) + else: #kill the program here - self.remote_vfs = None - return + self.remote_vfs = None + return utils.log(utils.getString(30047) + ": " + self.xbmc_vfs.root_path) utils.log(utils.getString(30048) + ": " + self.remote_vfs.root_path) @@ -208,6 +214,19 @@ class XbmcBackup: self.remote_vfs.set_root(fileGroup['dest']) self.backupFiles(fileGroup['files'],self.xbmc_vfs,self.remote_vfs) + if(utils.getSetting("compress_backups") == 'true'): + #send the zip file to the real remote vfs + self.remote_vfs.cleanup() + self.xbmc_vfs.rename(xbmc.translatePath(utils.data_dir() + "xbmc_backup_temp.zip"), xbmc.translatePath(utils.data_dir() + self.remote_vfs.root_path[:-1] + ".zip")) + fileManager.addFile(xbmc.translatePath(utils.data_dir() + self.remote_vfs.root_path[:-1] + ".zip")) + + #set root to data dir home + self.xbmc_vfs.set_root(xbmc.translatePath(utils.data_dir())) + + self.remote_vfs = self.saved_remote_vfs + self.progressBar.updateProgress(0, "Copying Zip Archive") + self.backupFiles(fileManager.getFiles(),self.xbmc_vfs, self.remote_vfs) + #remove old backups self._rotateBackups() @@ -324,6 +343,8 @@ class XbmcBackup: #call update addons to refresh everything xbmc.executebuiltin('UpdateLocalAddons') + self.xbmc_vfs.cleanup() + self.remote_vfs.cleanup() self.progressBar.close() #reset the window setting @@ -439,7 +460,10 @@ class FileManager: for aDir in dirs: dirPath = xbmc.translatePath(directory + "/" + aDir) file_ext = aDir.split('.')[-1] - self.addFile("-" + dirPath) + + #don't backup your own zip file + if(aDir != "xbmc_backup_temp.zip"): + self.addFile("-" + dirPath) #catch for "non directory" type files shouldWalk = True @@ -453,9 +477,10 @@ class FileManager: #copy all the files for aFile in files: - utils.log(aFile) - filePath = xbmc.translatePath(directory + "/" + aFile) - self.addFile(filePath) + if(aFile != 'xbmc_backup_temp.zip'): + utils.log(aFile) + filePath = xbmc.translatePath(directory + "/" + aFile) + self.addFile(filePath) def addFile(self,filename): try: diff --git a/resources/lib/vfs.py b/resources/lib/vfs.py index 2c3eced..216301d 100644 --- a/resources/lib/vfs.py +++ b/resources/lib/vfs.py @@ -2,7 +2,8 @@ import utils as utils import xbmc import xbmcvfs import xbmcgui -import sys +import zipfile +import zlib from dropbox import client, rest, session APP_KEY = utils.getSetting('dropbox_key') @@ -45,6 +46,12 @@ class Vfs: def exists(self,aFile): return True + + def rename(self,aFile,newName): + return True + + def cleanup(self): + return True class XBMCFileSystem(Vfs): @@ -60,9 +67,40 @@ class XBMCFileSystem(Vfs): def rmdir(self,directory): return xbmcvfs.rmdir(directory,True) + def rename(self,aFile,newName): + return xbmcvfs.rename(aFile, newName) + def exists(self,aFile): return xbmcvfs.exists(aFile) +class ZipFileSystem(Vfs): + zip = None + + def __init__(self,rootString,mode): + self.root_path = "" + self.zip = zipfile.ZipFile(xbmc.translatePath(utils.data_dir() + "xbmc_backup_temp.zip"),mode=mode) + + + def listdir(self,directory): + return True + + def mkdir(self,directory): + #self.zip.write(directory[len(self.root_path):]) + return True + + def put(self,source,dest): + self.zip.write(source,dest,compress_type=zipfile.ZIP_DEFLATED) + return True + + def rmdir(self,directory): + return True + + def exists(self,aFile): + return True + + def cleanup(self): + self.zip.close() + class DropboxFileSystem(Vfs): client = None diff --git a/resources/settings.xml b/resources/settings.xml index 21d98d1..a1d1c74 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -6,6 +6,7 @@ + From 525dd8ff869d6499a5c9fe0919cbf242407236ee Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Thu, 31 Jul 2014 15:20:22 -0500 Subject: [PATCH 03/17] delete temp zip file when done --- resources/lib/backup.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index 326471f..e66701e 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -216,9 +216,10 @@ class XbmcBackup: if(utils.getSetting("compress_backups") == 'true'): #send the zip file to the real remote vfs + zip_name = self.remote_vfs.root_path[:-1] + ".zip" self.remote_vfs.cleanup() - self.xbmc_vfs.rename(xbmc.translatePath(utils.data_dir() + "xbmc_backup_temp.zip"), xbmc.translatePath(utils.data_dir() + self.remote_vfs.root_path[:-1] + ".zip")) - fileManager.addFile(xbmc.translatePath(utils.data_dir() + self.remote_vfs.root_path[:-1] + ".zip")) + self.xbmc_vfs.rename(xbmc.translatePath(utils.data_dir() + "xbmc_backup_temp.zip"), xbmc.translatePath(utils.data_dir() + zip_name)) + fileManager.addFile(xbmc.translatePath(utils.data_dir() + zip_name)) #set root to data dir home self.xbmc_vfs.set_root(xbmc.translatePath(utils.data_dir())) @@ -226,6 +227,9 @@ class XbmcBackup: self.remote_vfs = self.saved_remote_vfs self.progressBar.updateProgress(0, "Copying Zip Archive") self.backupFiles(fileManager.getFiles(),self.xbmc_vfs, self.remote_vfs) + + #delete the temp zip file + self.xbmc_vfs.rmdir(xbmc.translatePath(utils.data_dir() + zip_name)) #remove old backups self._rotateBackups() From c49aebeba172d9648b10d46669637aee032df107 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Thu, 31 Jul 2014 16:02:53 -0500 Subject: [PATCH 04/17] list zip files for restore --- resources/lib/backup.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index e66701e..dad08ac 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -81,6 +81,21 @@ class XbmcBackup: result.append((aDir,folderName)) + for aFile in files: + file_ext = aFile.split('.')[-1] + + if(file_ext == 'zip'): + + #folder may or may not contain time, older versions didn't include this + folderName = '' + if(len(aFile ) > 8): + folderName = aFile [6:8] + '-' + aFile [4:6] + '-' + aFile [0:4] + " " + aFile [8:10] + ":" + aFile [10:12] + else: + folderName = aFile [6:8] + '-' + aFile [4:6] + '-' + aFile [0:4] + + result.append((aFile ,folderName)) + + result.sort(key=folderSort) return result @@ -107,7 +122,8 @@ class XbmcBackup: self.remote_vfs.set_root(self.remote_vfs.root_path + time.strftime("%Y%m%d%H%M") + "/") progressBarTitle = progressBarTitle + utils.getString(30016) elif(mode == self.Restore and self.restore_point != None and self.remote_vfs.root_path != ''): - self.remote_vfs.set_root(self.remote_vfs.root_path + self.restore_point + "/") + if(self.restore_point.split('.')[-1] != 'zip'): + self.remote_vfs.set_root(self.remote_vfs.root_path + self.restore_point + "/") progressBarTitle = progressBarTitle + utils.getString(30017) else: #kill the program here @@ -237,6 +253,11 @@ class XbmcBackup: elif (mode == self.Restore): utils.log(utils.getString(30023) + " - " + utils.getString(30017)) + #catch for if the restore point is actually a zip file + if(self.restore_point.split('.')[-1] == 'zip'): + #copy just this file from the remote vfs + pass + #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) @@ -464,7 +485,7 @@ class FileManager: for aDir in dirs: dirPath = xbmc.translatePath(directory + "/" + aDir) file_ext = aDir.split('.')[-1] - + #don't backup your own zip file if(aDir != "xbmc_backup_temp.zip"): self.addFile("-" + dirPath) From 933fdbdf09113afac18ebe7a3e72a5bfb10704a0 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Thu, 31 Jul 2014 17:29:59 -0500 Subject: [PATCH 05/17] copy zip file and open in write mode --- resources/lib/backup.py | 22 ++++++++++++++++------ resources/lib/vfs.py | 4 ++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index dad08ac..99af862 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -117,7 +117,7 @@ class XbmcBackup: if(utils.getSetting("compress_backups") == 'true'): #save the remote file system and use the zip vfs self.saved_remote_vfs = self.remote_vfs - self.remote_vfs = ZipFileSystem("","w") + self.remote_vfs = ZipFileSystem(xbmc.translatePath(utils.data_dir() + "xbmc_backup_temp.zip"),"w") self.remote_vfs.set_root(self.remote_vfs.root_path + time.strftime("%Y%m%d%H%M") + "/") progressBarTitle = progressBarTitle + utils.getString(30016) @@ -256,12 +256,22 @@ class XbmcBackup: #catch for if the restore point is actually a zip file if(self.restore_point.split('.')[-1] == 'zip'): #copy just this file from the remote vfs - pass + zipFile = [] + zipFile.append(self.restore_point) + + #set root to data dir home + self.xbmc_vfs.set_root(xbmc.translatePath(utils.data_dir())) + + self.progressBar.updateProgress(0, "Copying Zip Archive") + self.backupFiles(zipFile,self.remote_vfs, self.xbmc_vfs) - #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 + #set the new remote vfs + self.remote_vfs = ZipFileSystem(xbmc.translatePath(utils.data_dir() + self.restore_point),'r') + else: + #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 if(not self._checkValidationFile(self.remote_vfs.root_path)): #don't continue diff --git a/resources/lib/vfs.py b/resources/lib/vfs.py index 216301d..99be5bc 100644 --- a/resources/lib/vfs.py +++ b/resources/lib/vfs.py @@ -18,7 +18,7 @@ class Vfs: def set_root(self,rootString): old_root = self.root_path self.root_path = rootString - + #fix slashes self.root_path = self.root_path.replace("\\","/") @@ -78,7 +78,7 @@ class ZipFileSystem(Vfs): def __init__(self,rootString,mode): self.root_path = "" - self.zip = zipfile.ZipFile(xbmc.translatePath(utils.data_dir() + "xbmc_backup_temp.zip"),mode=mode) + self.zip = zipfile.ZipFile(rootString,mode=mode) def listdir(self,directory): From c28f9fd26b3018aa57d6742d28b05b7026ed7a96 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 12:37:57 -0500 Subject: [PATCH 06/17] will copy zip file from remote to dest --- resources/lib/backup.py | 21 ++++++++++++++------- resources/lib/vfs.py | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index 99af862..cee7ebb 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -255,18 +255,25 @@ class XbmcBackup: #catch for if the restore point is actually a zip file if(self.restore_point.split('.')[-1] == 'zip'): - #copy just this file from the remote vfs - zipFile = [] - zipFile.append(self.restore_point) - + self.progressBar.updateProgress(0, "Copying Zip Archive") + utils.log("copying zip file: " + self.restore_point) + #set root to data dir home self.xbmc_vfs.set_root(xbmc.translatePath(utils.data_dir())) + + if(not self.xbmc_vfs.exists(xbmc.translatePath(utils.data_dir() + self.restore_point))): + #copy just this file from the remote vfs + zipFile = [] + zipFile.append(self.remote_base_path + self.restore_point) - self.progressBar.updateProgress(0, "Copying Zip Archive") - self.backupFiles(zipFile,self.remote_vfs, self.xbmc_vfs) - + self.backupFiles(zipFile,self.remote_vfs, self.xbmc_vfs) + else: + utils.log("zip file exists already") + #set the new remote vfs self.remote_vfs = ZipFileSystem(xbmc.translatePath(utils.data_dir() + self.restore_point),'r') + self.remote_vfs.set_root(self.restore_point.split(".")[0] + "/") + else: #for restores remote path must exist if(not self.remote_vfs.exists(self.remote_vfs.root_path)): diff --git a/resources/lib/vfs.py b/resources/lib/vfs.py index 99be5bc..af49852 100644 --- a/resources/lib/vfs.py +++ b/resources/lib/vfs.py @@ -62,6 +62,7 @@ class XBMCFileSystem(Vfs): return xbmcvfs.mkdir(directory) def put(self,source,dest): + utils.log(source + ":" + dest) return xbmcvfs.copy(source,dest) def rmdir(self,directory): @@ -80,7 +81,6 @@ class ZipFileSystem(Vfs): self.root_path = "" self.zip = zipfile.ZipFile(rootString,mode=mode) - def listdir(self,directory): return True From 9a89066e665b22ded45020fbd8e33e15b97534ae Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 12:57:55 -0500 Subject: [PATCH 07/17] can restore full file tree --- resources/lib/backup.py | 17 ++++++++++------- resources/lib/vfs.py | 12 ++++++++---- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index cee7ebb..a495537 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -270,15 +270,18 @@ class XbmcBackup: else: utils.log("zip file exists already") + #extract the zip file + zip_vfs = ZipFileSystem(xbmc.translatePath(utils.data_dir() + self.restore_point),'r') + zip_vfs.extract(xbmc.translatePath(utils.data_dir())) + #set the new remote vfs - self.remote_vfs = ZipFileSystem(xbmc.translatePath(utils.data_dir() + self.restore_point),'r') - self.remote_vfs.set_root(self.restore_point.split(".")[0] + "/") + self.remote_vfs = XBMCFileSystem(xbmc.translatePath(utils.data_dir() + self.restore_point.split(".")[0] + "/")) - else: - #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 + + #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 if(not self._checkValidationFile(self.remote_vfs.root_path)): #don't continue diff --git a/resources/lib/vfs.py b/resources/lib/vfs.py index af49852..ddb4da4 100644 --- a/resources/lib/vfs.py +++ b/resources/lib/vfs.py @@ -82,24 +82,28 @@ class ZipFileSystem(Vfs): self.zip = zipfile.ZipFile(rootString,mode=mode) def listdir(self,directory): - return True + return [[],[]] def mkdir(self,directory): #self.zip.write(directory[len(self.root_path):]) - return True + return False def put(self,source,dest): self.zip.write(source,dest,compress_type=zipfile.ZIP_DEFLATED) return True def rmdir(self,directory): - return True + return False def exists(self,aFile): - return True + return False def cleanup(self): self.zip.close() + + def extract(self,path): + #extract zip file to path + self.zip.extractall(path) class DropboxFileSystem(Vfs): client = None From e6215dde5190a0553ca3f76a72a51580b0f3444b Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 13:05:58 -0500 Subject: [PATCH 08/17] read/write zip to temp directory --- resources/lib/backup.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index a495537..7318cc7 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -117,7 +117,7 @@ class XbmcBackup: if(utils.getSetting("compress_backups") == 'true'): #save the remote file system and use the zip vfs self.saved_remote_vfs = self.remote_vfs - self.remote_vfs = ZipFileSystem(xbmc.translatePath(utils.data_dir() + "xbmc_backup_temp.zip"),"w") + self.remote_vfs = ZipFileSystem(xbmc.translatePath("special://temp/xbmc_backup_temp.zip"),"w") self.remote_vfs.set_root(self.remote_vfs.root_path + time.strftime("%Y%m%d%H%M") + "/") progressBarTitle = progressBarTitle + utils.getString(30016) @@ -234,11 +234,11 @@ class XbmcBackup: #send the zip file to the real remote vfs zip_name = self.remote_vfs.root_path[:-1] + ".zip" self.remote_vfs.cleanup() - self.xbmc_vfs.rename(xbmc.translatePath(utils.data_dir() + "xbmc_backup_temp.zip"), xbmc.translatePath(utils.data_dir() + zip_name)) - fileManager.addFile(xbmc.translatePath(utils.data_dir() + zip_name)) + self.xbmc_vfs.rename(xbmc.translatePath("special://temp/xbmc_backup_temp.zip"), xbmc.translatePath("special://temp/" + zip_name)) + fileManager.addFile(xbmc.translatePath("special://temp/" + zip_name)) #set root to data dir home - self.xbmc_vfs.set_root(xbmc.translatePath(utils.data_dir())) + self.xbmc_vfs.set_root(xbmc.translatePath("special://temp/")) self.remote_vfs = self.saved_remote_vfs self.progressBar.updateProgress(0, "Copying Zip Archive") @@ -259,9 +259,9 @@ class XbmcBackup: utils.log("copying zip file: " + self.restore_point) #set root to data dir home - self.xbmc_vfs.set_root(xbmc.translatePath(utils.data_dir())) + self.xbmc_vfs.set_root(xbmc.translatePath("special://temp/")) - if(not self.xbmc_vfs.exists(xbmc.translatePath(utils.data_dir() + self.restore_point))): + if(not self.xbmc_vfs.exists(xbmc.translatePath("special://temp/" + self.restore_point))): #copy just this file from the remote vfs zipFile = [] zipFile.append(self.remote_base_path + self.restore_point) @@ -271,11 +271,11 @@ class XbmcBackup: utils.log("zip file exists already") #extract the zip file - zip_vfs = ZipFileSystem(xbmc.translatePath(utils.data_dir() + self.restore_point),'r') - zip_vfs.extract(xbmc.translatePath(utils.data_dir())) - + zip_vfs = ZipFileSystem(xbmc.translatePath("special://temp/"+ self.restore_point),'r') + zip_vfs.extract(xbmc.translatePath("special://temp/")) + #set the new remote vfs - self.remote_vfs = XBMCFileSystem(xbmc.translatePath(utils.data_dir() + self.restore_point.split(".")[0] + "/")) + self.remote_vfs = XBMCFileSystem(xbmc.translatePath("special://temp/" + self.restore_point.split(".")[0] + "/")) #for restores remote path must exist @@ -385,6 +385,11 @@ class XbmcBackup: self.xbmc_vfs.set_root(fileGroup['dest']) self.backupFiles(fileGroup['files'],self.remote_vfs,self.xbmc_vfs) + if(self.restore_point.split('.')[-1] == 'zip'): + #delete the zip file and the extracted directory + self.xbmc_vfs.rmdir(xbmc.translatePath("special://temp/" + self.restore_point)) + self.xbmc_vfs.rmdir(self.remote_vfs.root_path) + #call update addons to refresh everything xbmc.executebuiltin('UpdateLocalAddons') From 647bd8811b71c3a2cf65d2662b7f6152e9aea6ca Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 13:06:35 -0500 Subject: [PATCH 09/17] don't need these checks anymore --- resources/lib/backup.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index 7318cc7..f428165 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -511,9 +511,7 @@ class FileManager: dirPath = xbmc.translatePath(directory + "/" + aDir) file_ext = aDir.split('.')[-1] - #don't backup your own zip file - if(aDir != "xbmc_backup_temp.zip"): - self.addFile("-" + dirPath) + self.addFile("-" + dirPath) #catch for "non directory" type files shouldWalk = True @@ -527,10 +525,9 @@ class FileManager: #copy all the files for aFile in files: - if(aFile != 'xbmc_backup_temp.zip'): - utils.log(aFile) - filePath = xbmc.translatePath(directory + "/" + aFile) - self.addFile(filePath) + utils.log(aFile) + filePath = xbmc.translatePath(directory + "/" + aFile) + self.addFile(filePath) def addFile(self,filename): try: From 545843e9491b9a9723d68901c8017b40b5eb447d Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 13:12:43 -0500 Subject: [PATCH 10/17] need to treat backup zips as files --- resources/lib/backup.py | 12 +++++++++--- resources/lib/vfs.py | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index f428165..57e888c 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -245,7 +245,7 @@ class XbmcBackup: self.backupFiles(fileManager.getFiles(),self.xbmc_vfs, self.remote_vfs) #delete the temp zip file - self.xbmc_vfs.rmdir(xbmc.translatePath(utils.data_dir() + zip_name)) + self.xbmc_vfs.rmfile(xbmc.translatePath(utils.data_dir() + zip_name)) #remove old backups self._rotateBackups() @@ -387,7 +387,7 @@ class XbmcBackup: if(self.restore_point.split('.')[-1] == 'zip'): #delete the zip file and the extracted directory - self.xbmc_vfs.rmdir(xbmc.translatePath("special://temp/" + self.restore_point)) + self.xbmc_vfs.rmfile(xbmc.translatePath("special://temp/" + self.restore_point)) self.xbmc_vfs.rmdir(self.remote_vfs.root_path) #call update addons to refresh everything @@ -453,7 +453,13 @@ class XbmcBackup: while(remove_num < (len(dirs) - total_backups) and not self.progressBar.checkCancel()): self._updateProgress(utils.getString(30054) + " " + dirs[remove_num][1]) utils.log("Removing backup " + dirs[remove_num][0]) - self.remote_vfs.rmdir(self.remote_base_path + dirs[remove_num][0] + "/") + + if(dirs[remove_num][0].split('.')[-1] == 'zip'): + #this is a file, remove it that way + self.remote_vfs.rmfile(self.remote_base_path + dirs[remove_num][0]) + else: + self.remote_vfs.rmdir(self.remote_base_path + dirs[remove_num][0] + "/") + remove_num = remove_num + 1 def _createValidationFile(self): diff --git a/resources/lib/vfs.py b/resources/lib/vfs.py index ddb4da4..fc49d9d 100644 --- a/resources/lib/vfs.py +++ b/resources/lib/vfs.py @@ -44,6 +44,9 @@ class Vfs: def rmdir(self,directory): return True + def rmfile(self,aFile): + return True + def exists(self,aFile): return True @@ -68,6 +71,9 @@ class XBMCFileSystem(Vfs): def rmdir(self,directory): return xbmcvfs.rmdir(directory,True) + def rmfile(self,aFile): + return xbmcvfs.delete(aFile) + def rename(self,aFile,newName): return xbmcvfs.rename(aFile, newName) @@ -181,6 +187,16 @@ class DropboxFileSystem(Vfs): #finally remove the root directory self.client.file_delete(directory) + + return True + else: + return False + + def rmFile(self,aFile): + aFile = self._fix_slashes(aFile) + if(self.client != None and self.exists(aFile)): + self.client.file_delete(aFile) + return True else: return False From 5dfa9d9b7647115538507e815bdc5a1ffa8be55c Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 13:14:47 -0500 Subject: [PATCH 11/17] old logging and misssed name --- resources/lib/backup.py | 3 +-- resources/lib/vfs.py | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index 57e888c..f9cf762 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -245,7 +245,7 @@ class XbmcBackup: self.backupFiles(fileManager.getFiles(),self.xbmc_vfs, self.remote_vfs) #delete the temp zip file - self.xbmc_vfs.rmfile(xbmc.translatePath(utils.data_dir() + zip_name)) + self.xbmc_vfs.rmfile(xbmc.translatePath("special://temp/" + zip_name)) #remove old backups self._rotateBackups() @@ -531,7 +531,6 @@ class FileManager: #copy all the files for aFile in files: - utils.log(aFile) filePath = xbmc.translatePath(directory + "/" + aFile) self.addFile(filePath) diff --git a/resources/lib/vfs.py b/resources/lib/vfs.py index fc49d9d..1234622 100644 --- a/resources/lib/vfs.py +++ b/resources/lib/vfs.py @@ -65,7 +65,6 @@ class XBMCFileSystem(Vfs): return xbmcvfs.mkdir(directory) def put(self,source,dest): - utils.log(source + ":" + dest) return xbmcvfs.copy(source,dest) def rmdir(self,directory): From b3bbdd6911b64b993d9a415b62d258143b88ab90 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 13:54:22 -0500 Subject: [PATCH 12/17] need to reset vfs to default root dirs before copying zip --- resources/lib/backup.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index f9cf762..bb0afe1 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -68,7 +68,7 @@ class XbmcBackup: #get all the folders in the current root path dirs,files = self.remote_vfs.listdir(self.remote_base_path) - + for aDir in dirs: if(self.remote_vfs.exists(self.remote_base_path + aDir + "/xbmcbackup.val")): @@ -199,6 +199,8 @@ class XbmcBackup: self.filesTotal = fileManager.size() allFiles.append({"source":self.xbmc_vfs.root_path,"dest":self.remote_vfs.root_path,"files":fileManager.getFiles()}) + orig_base_path = self.remote_vfs.root_path + #check if there are custom directories if(utils.getSetting('custom_dir_1_enable') == 'true' and utils.getSetting('backup_custom_dir_1') != ''): @@ -229,6 +231,10 @@ class XbmcBackup: self.xbmc_vfs.set_root(fileGroup['source']) self.remote_vfs.set_root(fileGroup['dest']) self.backupFiles(fileGroup['files'],self.xbmc_vfs,self.remote_vfs) + + #reset remote and xbmc vfs + self.xbmc_vfs.set_root(xbmc.translatePath("special://home")) + self.remote_vfs.set_root(orig_base_path) if(utils.getSetting("compress_backups") == 'true'): #send the zip file to the real remote vfs @@ -241,7 +247,7 @@ class XbmcBackup: self.xbmc_vfs.set_root(xbmc.translatePath("special://temp/")) self.remote_vfs = self.saved_remote_vfs - self.progressBar.updateProgress(0, "Copying Zip Archive") + self.progressBar.updateProgress(98, "Copying Zip Archive") self.backupFiles(fileManager.getFiles(),self.xbmc_vfs, self.remote_vfs) #delete the temp zip file @@ -269,13 +275,14 @@ class XbmcBackup: self.backupFiles(zipFile,self.remote_vfs, self.xbmc_vfs) else: utils.log("zip file exists already") - + #extract the zip file zip_vfs = ZipFileSystem(xbmc.translatePath("special://temp/"+ self.restore_point),'r') zip_vfs.extract(xbmc.translatePath("special://temp/")) - #set the new remote vfs + #set the new remote vfs and fix xbmc path self.remote_vfs = XBMCFileSystem(xbmc.translatePath("special://temp/" + self.restore_point.split(".")[0] + "/")) + self.xbmc_vfs.set_root(xbmc.translatePath("special://home")) #for restores remote path must exist From 1255283f4d6751905e83a8d3a0240661a3af83d2 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 14:03:03 -0500 Subject: [PATCH 13/17] should clean up zip resources after extract --- resources/lib/backup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index bb0afe1..2e1ee3f 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -279,7 +279,8 @@ class XbmcBackup: #extract the zip file zip_vfs = ZipFileSystem(xbmc.translatePath("special://temp/"+ self.restore_point),'r') zip_vfs.extract(xbmc.translatePath("special://temp/")) - + zip_vfs.cleanup() + #set the new remote vfs and fix xbmc path self.remote_vfs = XBMCFileSystem(xbmc.translatePath("special://temp/" + self.restore_point.split(".")[0] + "/")) self.xbmc_vfs.set_root(xbmc.translatePath("special://home")) From 49783f712a372e5d9861f1604a54a400d2ffbd0d Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 14:06:55 -0500 Subject: [PATCH 14/17] updated readme --- README.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.txt b/README.txt index 9d57199..11efe87 100644 --- a/README.txt +++ b/README.txt @@ -8,6 +8,8 @@ Remote Destination/File Selection: In the addon settings you can define a remote path for the destination of your xbmc files. Each backup will create a folder named in a YYYYMMDDHHmm format so you can create multiple backups. You can keep a set number of backups by setting the integer value of the Backups to Keep setting greater than 0. +If you choose to compress your backups there are a few things you need to be aware of. Compressing takes place on the server you are trying to backup and then only the archive is copied to the remote backup location. This means you must have sufficient space available to allow for creating the archive. When restoring a zipped archive the process is the same. It is first copied to your local storage, extracted, and the contents put to their correct locations. The archive is then deleted. Zipped and non-zipped backups can be mixed in the same archive folder. + 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. From 24e1311db5d4c17909f11d30e45ef950eb8721af Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 14:09:37 -0500 Subject: [PATCH 15/17] version bump --- addon.xml | 2 +- changelog.txt | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index ac2fae7..3a5037c 100644 --- a/addon.xml +++ b/addon.xml @@ -1,6 +1,6 @@  + name="XBMC Backup" version="0.5.7" provider-name="robweber"> diff --git a/changelog.txt b/changelog.txt index a4943d7..3cd2d67 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +Version 0.5.7 + +added option to compress backups, uses local source for staging the zip before sending to remote + Version 0.5.6 fix dropbox delete recursion error - thanks durd From 9945dc628e168700a22b1787163ac6ba63459b3e Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 14:14:40 -0500 Subject: [PATCH 16/17] don't write to filesystem, use addFile --- resources/lib/backup.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index 2e1ee3f..f411ab9 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -47,7 +47,7 @@ class XbmcBackup: if(utils.getSetting('remote_selection') == '1'): self.remote_base_path = utils.getSetting('remote_path_2'); self.remote_vfs = XBMCFileSystem(utils.getSetting('remote_path_2')) - utils.setSetting("remote_path","") + utils.setSetting("remote_path","") elif(utils.getSetting('remote_selection') == '0'): self.remote_base_path = utils.getSetting('remote_path'); self.remote_vfs = XBMCFileSystem(utils.getSetting("remote_path")) @@ -320,10 +320,10 @@ class XbmcBackup: return - self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata/keymaps')) + fileManager.addFile('-userdata/keymaps') fileManager.walkTree(self.remote_vfs.root_path + "userdata/keymaps") - self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata/peripheral_data')) + fileManager.addFile('-userdata/peripheral_data') fileManager.walkTree(self.remote_vfs.root_path + "userdata/peripheral_data") #this part is an oddity @@ -333,31 +333,31 @@ class XbmcBackup: fileManager.addFile(self.remote_vfs.root_path + "userdata/" + aFile) if(utils.getSetting('backup_addons') == 'true'): - self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/addons')) + fileManager.addFile('-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.addFile('-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.addFile('-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.addFile('-userdata/playlists') fileManager.walkTree(self.remote_vfs.root_path + "userdata/playlists") if(utils.getSetting('backup_profiles') == 'true'): - self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata/profiles')) + fileManager.addFile('-userdata/profiles') fileManager.walkTree(self.remote_vfs.root_path + "userdata/profiles") if(utils.getSetting("backup_thumbnails") == "true"): - self.xbmc_vfs.mkdir(xbmc.translatePath('special://home/userdata/Thumbnails')) + fileManager.addFile('-userdata/Thumbnails') fileManager.walkTree(self.remote_vfs.root_path + "userdata/Thumbnails") - + #add to array self.filesTotal = fileManager.size() allFiles.append({"source":self.remote_vfs.root_path,"dest":self.xbmc_vfs.root_path,"files":fileManager.getFiles()}) From f249ea15835b7c0c59ab258cdb32cbd92da31447 Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Fri, 1 Aug 2014 14:15:27 -0500 Subject: [PATCH 17/17] cosmetics --- resources/lib/backup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lib/backup.py b/resources/lib/backup.py index f411ab9..404ade9 100644 --- a/resources/lib/backup.py +++ b/resources/lib/backup.py @@ -181,7 +181,7 @@ class XbmcBackup: if(utils.getSetting("backup_thumbnails") == "true"): fileManager.addFile("-userdata/Thumbnails") fileManager.walkTree(xbmc.translatePath('special://home/userdata/Thumbnails')) - + if(utils.getSetting("backup_config") == "true"): fileManager.addFile("-userdata/keymaps") fileManager.walkTree(xbmc.translatePath('special://home/userdata/keymaps')) @@ -597,7 +597,7 @@ class BackupProgressBar: else: self.progressBar.update(percent,message=message) else: - self.progressBar.update(percent) + self.progressBar.update(percent) def checkCancel(self): result = False