Merge branch 'master' into leia

This commit is contained in:
Rob Weber 2019-09-11 10:16:14 -05:00
commit d93589ecad
8 changed files with 58 additions and 79 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.xbmcbackup" <addon id="script.xbmcbackup"
name="Backup" version="1.5.1~beta1" provider-name="robweber"> name="Backup" version="1.6.0~beta1" provider-name="robweber">
<requires> <requires>
<import addon="xbmc.python" version="2.26.0"/> <import addon="xbmc.python" version="2.26.0"/>
<import addon="script.module.kodi-six" version="0.1.0"/> <import addon="script.module.kodi-six" version="0.1.0"/>
@ -92,10 +92,8 @@
<screenshot>resources/images/screenshot3.png</screenshot> <screenshot>resources/images/screenshot3.png</screenshot>
<screenshot>resources/images/screenshot4.png</screenshot> <screenshot>resources/images/screenshot4.png</screenshot>
</assets> </assets>
<news>Version 1.1.4 <news>Version 1.5.1
- added file chunk support for dropbox uploads - fix guisettings restores not working - thanks Bluerayx
- fixed settings duplicate ids, thanks aster-anto
- added scheduler delay to assist with time sync (rpi mostly)
</news> </news>
</extension> </extension>
</addon> </addon>

View File

@ -1,3 +1,7 @@
Version 1.5.1
fix guisettings restores not working - thanks Bluerayx
Version 1.5.0 Version 1.5.0
Overhaul of file selection and restore procedures. Breaking Change with previous versions PR117 Overhaul of file selection and restore procedures. Breaking Change with previous versions PR117

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

View File

@ -3,6 +3,7 @@ import time
import json import json
from kodi_six import xbmc, xbmcgui, xbmcvfs from kodi_six import xbmc, xbmcgui, xbmcvfs
from . import utils as utils from . import utils as utils
import os
from datetime import datetime from datetime import datetime
from . vfs import XBMCFileSystem,DropboxFileSystem,ZipFileSystem from . vfs import XBMCFileSystem,DropboxFileSystem,ZipFileSystem
from . progressbar import BackupProgressBar from . progressbar import BackupProgressBar
@ -316,10 +317,10 @@ class XbmcBackup:
self.xbmc_vfs.rmfile(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) self.xbmc_vfs.rmdir(self.remote_vfs.root_path)
if(utils.getSetting("backup_config") == "true"):
#update the guisettings information (or what we can from it) #update the guisettings information (or what we can from it)
gui_settings = GuiSettingsManager('special://home/userdata/guisettings.xml') gui_settings = GuiSettingsManager()
gui_settings.run() gui_settings.run()
#call update addons to refresh everything #call update addons to refresh everything
xbmc.executebuiltin('UpdateLocalAddons') xbmc.executebuiltin('UpdateLocalAddons')
@ -393,13 +394,15 @@ class XbmcBackup:
dest.mkdir(dest.root_path + aFile[len(source.root_path) + 1:]) dest.mkdir(dest.root_path + aFile[len(source.root_path) + 1:])
else: else:
self._updateProgress() self._updateProgress()
wroteFile = True wroteFile = True
destFile = dest.root_path + aFile[len(source.root_path):]
if(isinstance(source,DropboxFileSystem)): if(isinstance(source,DropboxFileSystem)):
#if copying from cloud storage we need the file handle, use get_file #if copying from cloud storage we need the file handle, use get_file
wroteFile = source.get_file(aFile,dest.root_path + aFile[len(source.root_path):]) wroteFile = source.get_file(aFile,destFile)
else: else:
#copy using normal method #copy using normal method
wroteFile = dest.put(aFile,dest.root_path + aFile[len(source.root_path):]) wroteFile = dest.put(aFile,destFile)
#if result is still true but this file failed #if result is still true but this file failed
if(not wroteFile and result): if(not wroteFile and result):
@ -550,13 +553,13 @@ class FileManager:
if(directory[-1:] == '/' or directory[-1:] == '\\'): if(directory[-1:] == '/' or directory[-1:] == '\\'):
directory = directory[:-1] directory = directory[:-1]
if(self.vfs.exists(directory + "/")): if(self.vfs.exists(directory + os.path.sep)):
dirs,files = self.vfs.listdir(directory) dirs,files = self.vfs.listdir(directory)
if(recurse): if(recurse):
#create all the subdirs first #create all the subdirs first
for aDir in dirs: for aDir in dirs:
dirPath = xbmc.validatePath(xbmc.translatePath(directory + "/" + aDir)) dirPath = xbmc.validatePath(xbmc.translatePath(directory + os.path.sep + aDir))
file_ext = aDir.split('.')[-1] file_ext = aDir.split('.')[-1]
#check if directory is excluded #check if directory is excluded
@ -576,7 +579,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 + os.path.sep + aFile)
self.addFile(filePath) self.addFile(filePath)
def addDir(self,dirMeta): def addDir(self,dirMeta):

View File

@ -6,94 +6,68 @@ from xml.parsers.expat import ExpatError
class GuiSettingsManager: class GuiSettingsManager:
settingsFile = None
doc = None doc = None
settings_allowed = list()
found_settings = list()
def __init__(self,settingsFile): def __init__(self):
self._readFile(xbmc.translatePath(settingsFile)) #first make a copy of the file
xbmcvfs.copy(xbmc.translatePath('special://home/userdata/guisettings.xml'), xbmc.translatePath("special://home/userdata/guisettings.xml.restored"))
#read in the copy
self._readFile(xbmc.translatePath('special://home/userdata/guisettings.xml.restored'))
def run(self): def run(self):
#get a list of all the settings we can manipulate via json #get a list of all the settings we can manipulate via json
json_response = json.loads(xbmc.executeJSONRPC('{"jsonrpc":"2.0", "id":1, "method":"Settings.GetSettings","params":{"level":"advanced"}}')) json_response = json.loads(xbmc.executeJSONRPC('{"jsonrpc":"2.0", "id":1, "method":"Settings.GetSettings","params":{"level":"advanced"}}'))
settings = json_response['result']['settings'] settings = json_response['result']['settings']
currentSettings = {}
for aSetting in settings:
self.settings_allowed.append(aSetting['id'])
#parse the existing xml file and get all the settings
root_nodes = self.__parseNodes(self.doc.documentElement)
for aNode in root_nodes: for aSetting in settings:
secondary_list = self.__parseNodes(self.doc.getElementsByTagName(aNode.name)[0]) if('value' in aSetting):
currentSettings[aSetting['id']] = aSetting['value']
for secondNode in secondary_list: #parse the existing xml file and get all the settings we need to restore
#if the node does not have children and is not default restoreSettings = self.__parseNodes(self.doc.getElementsByTagName('setting'))
if(not secondNode.hasChildren and not secondNode.isDefault):
#get a list where the restore setting value != the current value
if(secondNode.json_name() in self.settings_allowed): updateSettings = {k: v for k, v in restoreSettings.items() if (k in currentSettings and currentSettings[k] != v)}
self.found_settings.append(secondNode)
#go through all the found settings and update them #go through all the found settings and update them
for aSetting in self.found_settings: jsonObj = {"jsonrpc":"2.0","id":1,"method":"Settings.SetSettingValue","params":{"setting":"","value":""}}
utils.log("updating: " + aSetting.json_name() + ", value: " + aSetting.value) for anId, aValue in updateSettings.items():
utils.log("updating: " + anId + ", value: " + str(aValue))
jsonObj['params']['setting'] = anId
jsonObj['params']['value'] = aValue
#check for boolean and numeric values xbmc.executeJSONRPC(json.dumps(jsonObj))
if(aSetting.value.isdigit() or (aSetting.value == 'true' or aSetting.value == 'false')):
xbmc.executeJSONRPC('{"jsonrpc":"2.0", "id":1, "method":"Settings.SetSettingValue","params":{"setting":"' + aSetting.json_name() + '","value":' + aSetting.value + '}}')
else:
xbmc.executeJSONRPC('{"jsonrpc":"2.0", "id":1, "method":"Settings.SetSettingValue","params":{"setting":"' + aSetting.json_name() + '","value":"' + utils.encode(aSetting.value) + '"}}')
#make a copy of the guisettings file to make user based restores easier
xbmcvfs.copy(self.settingsFile, xbmc.translatePath("special://home/userdata/guisettings.xml.restored"))
def __parseNodes(self,nodeList): def __parseNodes(self,nodeList):
result = [] result = {}
for node in nodeList.childNodes: for node in nodeList:
if(node.nodeType == self.doc.ELEMENT_NODE): nodeValue = ''
aSetting = SettingNode(node.nodeName) if(node.firstChild != None):
nodeValue = node.firstChild.nodeValue
#detect if there are any element nodes
if(len(node.childNodes) > 0): #check for numbers and booleans
for child_node in node.childNodes: if(nodeValue.isdigit()):
if(child_node.nodeType == self.doc.ELEMENT_NODE): nodeValue = int(nodeValue)
aSetting.hasChildren = True elif(nodeValue == 'true'):
nodeValue = True
if(not aSetting.hasChildren and len(node.childNodes) > 0): elif(nodeValue == 'false'):
aSetting.value = node.firstChild.nodeValue nodeValue = False
if('default' not in node.attributes.keys()): result[node.getAttribute('id')] = nodeValue
aSetting.isDefault = False
aSetting.parent = node.parentNode.nodeName
result.append(aSetting)
return result return result
def _readFile(self,fileLoc): def _readFile(self,fileLoc):
if(xbmcvfs.exists(fileLoc)): if(xbmcvfs.exists(fileLoc)):
try: try:
self.doc = minidom.parse(fileLoc) self.doc = minidom.parse(fileLoc)
self.settingsFile = fileLoc
except ExpatError: except ExpatError:
utils.log("Can't read " + fileLoc) utils.log("Can't read " + fileLoc)
class SettingNode:
name = ''
value = ''
hasChildren = False
isDefault = True
parent = ''
def __init__(self,name):
self.name = name
def json_name(self):
return self.parent + "." + self.name