can now backup custom directories - other functions stripped out for now

This commit is contained in:
Rob Weber 2013-01-28 15:44:22 -06:00
parent cfdc3694ef
commit 052cd1a062
3 changed files with 108 additions and 133 deletions

View File

@ -7,54 +7,13 @@ import time
from vfs import XBMCFileSystem,DropboxFileSystem from vfs import XBMCFileSystem,DropboxFileSystem
class FileManager: class FileManager:
fileArray = None fileArray = []
verbose_log = False
not_dir = ['.zip','.xsp','.rar'] not_dir = ['.zip','.xsp','.rar']
vfs = None vfs = None
def __init__(self,vfs): def __init__(self,vfs):
self.vfs = 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): def walkTree(self,directory):
dirs,files = self.vfs.listdir(directory) dirs,files = self.vfs.listdir(directory)
@ -62,7 +21,7 @@ class FileManager:
for aDir in dirs: for aDir in dirs:
dirPath = xbmc.translatePath(directory + "/" + aDir) dirPath = xbmc.translatePath(directory + "/" + aDir)
file_ext = aDir.split('.')[-1] file_ext = aDir.split('.')[-1]
self.addFile("-" + dirPath[len(self.vfs.root_path):]) self.addFile("-" + dirPath)
#catch for "non directory" type files #catch for "non directory" type files
if (not any(file_ext in s for s in self.not_dir)): if (not any(file_ext in s for s in self.not_dir)):
self.walkTree(dirPath) self.walkTree(dirPath)
@ -70,7 +29,7 @@ class FileManager:
#copy all the files #copy all the files
for aFile in files: for aFile in files:
filePath = xbmc.translatePath(directory + "/" + aFile) filePath = xbmc.translatePath(directory + "/" + aFile)
self.addFile(filePath[len(self.vfs.root_path):]) self.addFile(filePath)
def addFile(self,filename): def addFile(self,filename):
try: try:
@ -82,8 +41,10 @@ class FileManager:
utils.log("Add File: " + filename,xbmc.LOGDEBUG) utils.log("Add File: " + filename,xbmc.LOGDEBUG)
self.fileArray.append(filename) self.fileArray.append(filename)
def getFileList(self): def getFiles(self):
return self.fileArray result = self.fileArray
self.fileArray = []
return result
class XbmcBackup: class XbmcBackup:
#constants for initiating a back or restore #constants for initiating a back or restore
@ -91,7 +52,7 @@ class XbmcBackup:
Restore = 1 Restore = 1
#remote file system #remote file system
local_vfs = None xbmc_vfs = None
remote_vfs = None remote_vfs = None
restoreFile = None restoreFile = None
@ -102,26 +63,21 @@ class XbmcBackup:
fileManager = None fileManager = None
restore_point = 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)) utils.log(utils.getString(30046))
def configureVFS(self): def configureRemote(self):
if(utils.getSetting('remote_selection') == '1'): if(utils.getSetting('remote_selection') == '1'):
self.remote_vfs = XBMCFileSystem() self.remote_vfs = XBMCFileSystem(utils.getSetting('remote_path_2'))
self.remote_vfs.set_root(utils.getSetting('remote_path_2'))
utils.setSetting("remote_path","") utils.setSetting("remote_path","")
elif(utils.getSetting('remote_selection') == '0'): elif(utils.getSetting('remote_selection') == '0'):
self.remote_vfs = XBMCFileSystem() self.remote_vfs = XBMCFileSystem(utils.getSetting("remote_path"))
self.remote_vfs.set_root(utils.getSetting("remote_path"))
elif(utils.getSetting('remote_selection') == '2'): elif(utils.getSetting('remote_selection') == '2'):
self.remote_vfs = DropboxFileSystem() self.remote_vfs = DropboxFileSystem("/")
self.remote_vfs.set_root('/')
def listBackups(self): def listBackups(self):
result = list() result = list()
@ -138,7 +94,6 @@ class XbmcBackup:
self.restore_point = restore_point self.restore_point = restore_point
def run(self,mode=-1,runSilent=False): def run(self,mode=-1,runSilent=False):
#append backup folder name #append backup folder name
remote_base_path = "" remote_base_path = ""
progressBarTitle = utils.getString(30010) + " - " progressBarTitle = utils.getString(30010) + " - "
@ -154,7 +109,7 @@ class XbmcBackup:
self.remote_vfs = None self.remote_vfs = None
return 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) utils.log(utils.getString(30048) + ": " + self.remote_vfs.root_path)
#check if we should use the progress bar #check if we should use the progress bar
@ -162,103 +117,114 @@ class XbmcBackup:
self.progressBar = xbmcgui.DialogProgress() self.progressBar = xbmcgui.DialogProgress()
self.progressBar.create(progressBarTitle,utils.getString(30049) + "......") self.progressBar.create(progressBarTitle,utils.getString(30049) + "......")
#run the correct mode
if(mode == self.Backup): if(mode == self.Backup):
utils.log(utils.getString(30023) + " - " + utils.getString(30016)) utils.log(utils.getString(30023) + " - " + utils.getString(30016))
self.fileManager = FileManager(self.local_vfs)
#for backups check if remote path exists #for backups check if remote path exists
if(self.remote_vfs.exists(self.remote_vfs.root_path)): if(self.remote_vfs.exists(self.remote_vfs.root_path)):
#this will fail - need a disclaimer here #this will fail - need a disclaimer here
utils.log(utils.getString(30050)) 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: 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): utils.log(utils.getString(30051))
self.progressBar.close() 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): if(utils.getSetting("backup_playlists") == 'true'):
self.remote_vfs.mkdir(self.remote_vfs.root_path + "userdata/playlists")
#make the remote directory fileManager.walkTree(xbmc.translatePath('special://home/userdata/playlists'))
self.remote_vfs.mkdir(self.remote_vfs.root_path)
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)) #backup all the files
self.fileManager.createFileList() 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 #create a special remote path with hash
self.writeFiles(allFiles,self.local_vfs,self.remote_vfs) 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))
def restoreFiles(self): self.remote_vfs.set_root(self.remote_vfs.root_path + "custom_1_" + self._createCRC(self.xbmc_vfs.root_path))
self.fileManager.createFileList()
utils.log(utils.getString(30051)) fileManager.walkTree(self.xbmc_vfs.root_path)
allFiles = self.fileManager.getFileList() self.backupFiles(fileManager.getFiles(),self.xbmc_vfs,self.remote_vfs)
#write list from remote to local def backupFiles(self,fileList,source,dest):
self.writeFiles(allFiles,self.remote_vfs,self.local_vfs)
#call update addons to refresh everything
xbmc.executebuiltin('UpdateLocalAddons')
def writeFiles(self,fileList,source,dest):
utils.log("Writing files to: " + dest.root_path) utils.log("Writing files to: " + dest.root_path)
self.filesTotal = len(fileList) self.filesTotal = len(fileList)
self.filesLeft = self.filesTotal self.filesLeft = self.filesTotal
#write each file from source to destination
for aFile in fileList: for aFile in fileList:
if(not self.checkCancel()): if(not self._checkCancel()):
utils.log('Writing file: ' + source.root_path + aFile,xbmc.LOGDEBUG) utils.log('Writing file: ' + aFile,xbmc.LOGDEBUG)
self.updateProgress(aFile) self._updateProgress(aFile)
if (aFile.startswith("-")): if(aFile.startswith("-")):
dest.mkdir(dest.root_path + aFile[1:]) dest.mkdir(dest.root_path + aFile[len(source.root_path) + 1:])
else: else:
if(isinstance(source,DropboxFileSystem)): if(isinstance(source,DropboxFileSystem)):
#if copying from dropbox we need the file handle, use get_file #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: else:
#copy using normal method #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 self.filesLeft = self.filesLeft - 1
#update the progress bar #update the progress bar
if(self.progressBar != None): if(self.progressBar != None):
self.progressBar.update(int((float(self.filesTotal - self.filesLeft)/float(self.filesTotal)) * 100),message) self.progressBar.update(int((float(self.filesTotal - self.filesLeft)/float(self.filesTotal)) * 100),message)
def checkCancel(self): def _checkCancel(self):
result = False result = False
if(self.progressBar != None): if(self.progressBar != None):

View File

@ -11,6 +11,12 @@ APP_SECRET = utils.getSetting('dropbox_secret')
class Vfs: class Vfs:
root_path = None root_path = None
def __init(self):
pass
def __init__(self,rootString):
self.set_root(rootString)
def set_root(self,rootString): def set_root(self,rootString):
old_root = self.root_path old_root = self.root_path
self.root_path = rootString self.root_path = rootString
@ -44,7 +50,7 @@ class Vfs:
return True return True
class XBMCFileSystem(Vfs): class XBMCFileSystem(Vfs):
def listdir(self,directory): def listdir(self,directory):
return xbmcvfs.listdir(directory) return xbmcvfs.listdir(directory)
@ -63,7 +69,11 @@ class XBMCFileSystem(Vfs):
class DropboxFileSystem(Vfs): class DropboxFileSystem(Vfs):
client = None client = None
def __init__(self): def __init__(self,rootString):
self.setup()
Vfs.__init__(rootString)
def setup(self):
if(APP_KEY == '' or APP_SECRET == ''): if(APP_KEY == '' or APP_SECRET == ''):
xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30058),utils.getString(30059)) xbmcgui.Dialog().ok(utils.getString(30010),utils.getString(30058),utils.getString(30059))
return return
@ -94,7 +104,6 @@ class DropboxFileSystem(Vfs):
except: except:
#this didn't work, delete the token file #this didn't work, delete the token file
self.deleteToken() self.deleteToken()
def listdir(self,directory): def listdir(self,directory):
if(self.client != None and self.exists(directory)): if(self.client != None and self.exists(directory)):

View File

@ -16,7 +16,7 @@
<setting id="backup_playlists" type="bool" label="30033" default="true" /> <setting id="backup_playlists" type="bool" label="30033" default="true" />
<setting id="backup_thumbnails" type="bool" label="30034" default="true" /> <setting id="backup_thumbnails" type="bool" label="30034" default="true" />
<setting id="backup_config" type="bool" label="30035" default="true" /> <setting id="backup_config" type="bool" label="30035" default="true" />
<setting id="backup_dir" type="folder" label="Additional Directory" default="" /> <setting id="backup_custom_dir" type="folder" label="Additional Directory" default="" />
</category> </category>
<category id="scheduling" label="30013"> <category id="scheduling" label="30013">
<setting id="enable_scheduler" type="bool" label="30060" default="false" /> <setting id="enable_scheduler" type="bool" label="30060" default="false" />