mirror of
https://github.com/robweber/xbmcbackup.git
synced 2024-11-14 20:35:48 +01:00
added a "restore.txt" document that can be used to reverse the flow from remote to local.
Added restore mode in settings
This commit is contained in:
parent
140965733c
commit
f520d58c6b
@ -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.
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<addon id="script.xbmcbackup"
|
||||
name="XBMC Backup" version="0.0.3" provider-name="robweber">
|
||||
name="XBMC Backup" version="0.0.4" provider-name="robweber">
|
||||
<requires>
|
||||
<import addon="xbmc.python" version="2.0"/>
|
||||
</requires>
|
||||
@ -8,7 +8,7 @@
|
||||
<provides>executable</provides>
|
||||
</extension>
|
||||
<extension point="xbmc.addon.metadata">
|
||||
<summary lang="en">Backup your XBMC database and configuration files before an upgrade or in the even of a crash.</summary>
|
||||
<summary lang="en">Backup abd restore your XBMC database and configuration files in the event of a crash or file corruption.</summary>
|
||||
<description lang="en">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.</description>
|
||||
<platform>all</platform>
|
||||
</extension>
|
||||
|
184
default.py
184
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')
|
||||
|
@ -2,11 +2,12 @@
|
||||
<strings>
|
||||
<string id="30010">XBMC Backup</string>
|
||||
<string id="30011">General</string>
|
||||
<string id="30012">Backup Selection</string>
|
||||
<string id="30012">File Selection</string>
|
||||
|
||||
<string id="30020">Remote Path</string>
|
||||
<string id="30021">Backup Folder Name</string>
|
||||
<string id="30022">Run Silent</string>
|
||||
<string id="30023">Mode</string>
|
||||
|
||||
<string id="30030">User Addons</string>
|
||||
<string id="30031">Addon Data</string>
|
||||
|
@ -3,6 +3,7 @@
|
||||
<category id="general" label="30011">
|
||||
<setting id="remote_path" type="folder" label="30020" />
|
||||
<setting id="backup_name" type="text" label="30021" default="xbmc_backup"/>
|
||||
<setting id="addon_mode" type="enum" values="Backup|Restore" default="Backup" label="30023" />
|
||||
<setting id="run_silent" type="bool" label="30022" default="false" />
|
||||
</category>
|
||||
<category id="selection" label="30012">
|
||||
|
Loading…
Reference in New Issue
Block a user