mirror of
https://github.com/robweber/xbmcbackup.git
synced 2024-11-15 04:45:49 +01:00
removed VFS library, now using xbmcvfs exclusively
This commit is contained in:
parent
1e5a524ae3
commit
e4f25f174f
44
default.py
44
default.py
@ -1,7 +1,7 @@
|
|||||||
import xbmc
|
import xbmc
|
||||||
import xbmcaddon
|
import xbmcaddon
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
import resources.lib.vfs as vfs
|
import xbmcvfs
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@ -13,6 +13,7 @@ class FileManager:
|
|||||||
addonDir = ''
|
addonDir = ''
|
||||||
fileArray = None
|
fileArray = None
|
||||||
verbose_log = False
|
verbose_log = False
|
||||||
|
not_dir = ['.zip','.xsp','.rar']
|
||||||
|
|
||||||
def __init__(self,path,addon_dir):
|
def __init__(self,path,addon_dir):
|
||||||
self.walk_path = path
|
self.walk_path = path
|
||||||
@ -29,13 +30,13 @@ class FileManager:
|
|||||||
#figure out which syncing options to run
|
#figure out which syncing options to run
|
||||||
if(Addon.getSetting('backup_addons') == 'true'):
|
if(Addon.getSetting('backup_addons') == 'true'):
|
||||||
self.addFile("-addons")
|
self.addFile("-addons")
|
||||||
self.walkTree(self.walk_path + "addons/")
|
self.walkTree(self.walk_path + "addons")
|
||||||
|
|
||||||
self.addFile("-userdata")
|
self.addFile("-userdata")
|
||||||
|
|
||||||
if(Addon.getSetting('backup_addon_data') == 'true'):
|
if(Addon.getSetting('backup_addon_data') == 'true'):
|
||||||
self.addFile("-userdata/addon_data")
|
self.addFile("-userdata/addon_data")
|
||||||
self.walkTree(self.walk_path + "userdata/addon_data/")
|
self.walkTree(self.walk_path + "userdata/addon_data")
|
||||||
|
|
||||||
if(Addon.getSetting('backup_database') == 'true'):
|
if(Addon.getSetting('backup_database') == 'true'):
|
||||||
self.addFile("-userdata/Database")
|
self.addFile("-userdata/Database")
|
||||||
@ -57,21 +58,28 @@ class FileManager:
|
|||||||
self.walkTree(self.walk_path + "userdata/peripheral_data")
|
self.walkTree(self.walk_path + "userdata/peripheral_data")
|
||||||
|
|
||||||
#this part is an oddity
|
#this part is an oddity
|
||||||
configFiles = vfs.listdir(self.walk_path + "userdata/",extra_metadata=True)
|
dirs,configFiles = xbmcvfs.listdir(self.walk_path + "userdata/")
|
||||||
for aFile in configFiles:
|
for aFile in configFiles:
|
||||||
if(aFile['file'].endswith(".xml")):
|
if(aFile.endswith(".xml")):
|
||||||
self.addFile(aFile['file'][len(self.walk_path):])
|
self.addFile("userdata/" + aFile)
|
||||||
|
|
||||||
def walkTree(self,directory):
|
def walkTree(self,directory):
|
||||||
for (path, dirs, files) in vfs.walk(directory):
|
dirs,files = xbmcvfs.listdir(directory)
|
||||||
|
|
||||||
#create all the subdirs first
|
#create all the subdirs first
|
||||||
for aDir in dirs:
|
for aDir in dirs:
|
||||||
self.addFile("-" + aDir[len(self.walk_path):])
|
dirPath = xbmc.translatePath(directory + "/" + aDir)
|
||||||
|
file_ext = aDir.split('.')[-1]
|
||||||
|
|
||||||
|
self.addFile("-" + dirPath[len(self.walk_path):].decode("UTF-8"))
|
||||||
|
#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
|
#copy all the files
|
||||||
for aFile in files:
|
for aFile in files:
|
||||||
filePath = aFile[len(self.walk_path):]
|
filePath = xbmc.translatePath(directory + "/" + aFile)
|
||||||
self.addFile(filePath)
|
self.addFile(filePath[len(self.walk_path):].decode("UTF-8"))
|
||||||
|
|
||||||
def addFile(self,filename):
|
def addFile(self,filename):
|
||||||
#write the full remote path name of this file
|
#write the full remote path name of this file
|
||||||
@ -117,6 +125,9 @@ class XbmcBackup:
|
|||||||
else:
|
else:
|
||||||
self.remote_path = ""
|
self.remote_path = ""
|
||||||
|
|
||||||
|
self.local_path = self.local_path.decode("UTF-8")
|
||||||
|
self.local_path = self.local_path.decode("UTF-8")
|
||||||
|
|
||||||
log(self.addon.getLocalizedString(30046))
|
log(self.addon.getLocalizedString(30046))
|
||||||
log(self.addon.getLocalizedString(30047) + ": " + self.local_path)
|
log(self.addon.getLocalizedString(30047) + ": " + self.local_path)
|
||||||
log(self.addon.getLocalizedString(30048) + ": " + self.remote_path)
|
log(self.addon.getLocalizedString(30048) + ": " + self.remote_path)
|
||||||
@ -132,7 +143,7 @@ class XbmcBackup:
|
|||||||
self.fileManager = FileManager(self.local_path,self.addon.getAddonInfo('profile'))
|
self.fileManager = FileManager(self.local_path,self.addon.getAddonInfo('profile'))
|
||||||
|
|
||||||
#for backups check if remote path exists
|
#for backups check if remote path exists
|
||||||
if(vfs.exists(self.remote_path)):
|
if(xbmcvfs.exists(self.remote_path)):
|
||||||
#this will fail - need a disclaimer here
|
#this will fail - need a disclaimer here
|
||||||
log(self.addon.getLocalizedString(30050))
|
log(self.addon.getLocalizedString(30050))
|
||||||
|
|
||||||
@ -141,7 +152,7 @@ class XbmcBackup:
|
|||||||
self.fileManager = FileManager(self.remote_path,self.addon.getAddonInfo('profile'))
|
self.fileManager = FileManager(self.remote_path,self.addon.getAddonInfo('profile'))
|
||||||
|
|
||||||
#for restores remote path must exist
|
#for restores remote path must exist
|
||||||
if(vfs.exists(self.remote_path)):
|
if(xbmcvfs.exists(self.remote_path)):
|
||||||
self.restoreFiles()
|
self.restoreFiles()
|
||||||
else:
|
else:
|
||||||
xbmcgui.Dialog().ok(self.addon.getLocalizedString(30010),self.addon.getLocalizedString(30045))
|
xbmcgui.Dialog().ok(self.addon.getLocalizedString(30010),self.addon.getLocalizedString(30045))
|
||||||
@ -149,7 +160,7 @@ class XbmcBackup:
|
|||||||
def syncFiles(self):
|
def syncFiles(self):
|
||||||
|
|
||||||
#make the remote directory
|
#make the remote directory
|
||||||
vfs.mkdir(self.remote_path)
|
xbmcvfs.mkdir(self.remote_path)
|
||||||
|
|
||||||
log(self.addon.getLocalizedString(30051))
|
log(self.addon.getLocalizedString(30051))
|
||||||
self.fileManager.createFileList(self.addon)
|
self.fileManager.createFileList(self.addon)
|
||||||
@ -182,9 +193,9 @@ class XbmcBackup:
|
|||||||
log('Writing file: ' + source + aFile,xbmc.LOGDEBUG)
|
log('Writing file: ' + source + aFile,xbmc.LOGDEBUG)
|
||||||
self.updateProgress(aFile)
|
self.updateProgress(aFile)
|
||||||
if (aFile.startswith("-")):
|
if (aFile.startswith("-")):
|
||||||
vfs.mkdir(xbmc.makeLegalFilename(dest + aFile[1:],False))
|
xbmcvfs.mkdir(xbmc.makeLegalFilename(dest + aFile[1:],False))
|
||||||
else:
|
else:
|
||||||
vfs.copy(xbmc.makeLegalFilename(source + aFile),xbmc.makeLegalFilename(dest + aFile,False))
|
xbmcvfs.copy(xbmc.makeLegalFilename(source + aFile),xbmc.makeLegalFilename(dest + aFile,False))
|
||||||
|
|
||||||
if(self.addon.getSetting('run_silent') == 'false'):
|
if(self.addon.getSetting('run_silent') == 'false'):
|
||||||
self.progressBar.close()
|
self.progressBar.close()
|
||||||
@ -209,7 +220,8 @@ class XbmcBackup:
|
|||||||
|
|
||||||
#global functions for logging and encoding
|
#global functions for logging and encoding
|
||||||
def log(message,loglevel=xbmc.LOGNOTICE):
|
def log(message,loglevel=xbmc.LOGNOTICE):
|
||||||
xbmc.log(encode(__Addon.getLocalizedString(30010) + ": " + message),level=loglevel)
|
logM = encode(__Addon.getLocalizedString(30010) + ": " + message)
|
||||||
|
xbmc.log(logM,level=loglevel)
|
||||||
|
|
||||||
def encode(string):
|
def encode(string):
|
||||||
return string.encode('UTF-8','replace')
|
return string.encode('UTF-8','replace')
|
||||||
|
@ -1,256 +0,0 @@
|
|||||||
'''
|
|
||||||
Convenience wrappers and extensions for some commonly used VFS functions
|
|
||||||
in XBMC addons. This module exposes all the functionality of xbmcvfs plus
|
|
||||||
some extra functions.
|
|
||||||
|
|
||||||
Copyright (C) 2012 Patrick Carey
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
'''
|
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import xbmc
|
|
||||||
import xbmcvfs
|
|
||||||
import urllib
|
|
||||||
|
|
||||||
def walk(path):
|
|
||||||
|
|
||||||
'''
|
|
||||||
Reimplementation of os.walk using XBMC's jsonrpc API.
|
|
||||||
|
|
||||||
This has the nice added benefits of being able to walk remote
|
|
||||||
directories and inside compressed files such as rars/zips.
|
|
||||||
'''
|
|
||||||
|
|
||||||
dir_tree = [[path]]
|
|
||||||
|
|
||||||
current_depth = 0
|
|
||||||
|
|
||||||
not_dir = ['.zip','.xsp','.rar']
|
|
||||||
|
|
||||||
while True:
|
|
||||||
|
|
||||||
if current_depth > -1:
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
current_path = dir_tree[current_depth].pop(0)
|
|
||||||
current_dirs, current_files = [], []
|
|
||||||
|
|
||||||
for x in listdir(current_path, extra_metadata=True):
|
|
||||||
|
|
||||||
file_ext = x['file'].split('.')[-1]
|
|
||||||
|
|
||||||
if x['filetype'] == 'directory' and not any(file_ext in s for s in not_dir):
|
|
||||||
|
|
||||||
current_dirs.append(urllib.unquote(x['file']))
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
current_files.append(urllib.unquote(x['file']))
|
|
||||||
|
|
||||||
except IndexError:
|
|
||||||
|
|
||||||
current_depth -= 1
|
|
||||||
|
|
||||||
dir_tree.pop()
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
yield (current_path, current_dirs, current_files)
|
|
||||||
|
|
||||||
if current_dirs:
|
|
||||||
|
|
||||||
current_depth += 1
|
|
||||||
|
|
||||||
dir_tree.append(current_dirs)
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def listdir(path, extra_metadata=False):
|
|
||||||
|
|
||||||
'''
|
|
||||||
Reimplementation of os.listdir using XBMC's jsonrpc API.
|
|
||||||
|
|
||||||
Returns a list of file/directory names from the specified path
|
|
||||||
|
|
||||||
Accepts an optional boolean 'extra_metadata' as the second argument
|
|
||||||
which will cause the function to instead return a list of dictionaries
|
|
||||||
containing all of the metadata about each file that was retrieved from
|
|
||||||
XBMC.
|
|
||||||
'''
|
|
||||||
|
|
||||||
fileList = []
|
|
||||||
|
|
||||||
json_response = xbmc.executeJSONRPC('{ "jsonrpc" : "2.0" , "method" : "Files.GetDirectory" , "params" : { "directory" : "%s" , "sort" : { "method" : "file" } } , "id" : 1 }' % path.encode('utf-8').replace('\\', '\\\\'))
|
|
||||||
|
|
||||||
jsonobject = json.loads(json_response)
|
|
||||||
|
|
||||||
if jsonobject.has_key('result') and jsonobject['result']['files']:
|
|
||||||
|
|
||||||
for item in jsonobject['result']['files']:
|
|
||||||
|
|
||||||
if extra_metadata:
|
|
||||||
|
|
||||||
fileList.append(item)
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
fileList.append(item['file'])
|
|
||||||
|
|
||||||
return fileList
|
|
||||||
|
|
||||||
|
|
||||||
def copy(source, destination):
|
|
||||||
|
|
||||||
"""
|
|
||||||
copy(source, destination) -- Copy file to destination, returns true/false.
|
|
||||||
|
|
||||||
source : file to copy.
|
|
||||||
destination : destination file
|
|
||||||
|
|
||||||
example:
|
|
||||||
- success = vfs.copy(source, destination)
|
|
||||||
"""
|
|
||||||
|
|
||||||
return xbmcvfs.copy(source, destination)
|
|
||||||
|
|
||||||
|
|
||||||
def delete(path):
|
|
||||||
|
|
||||||
"""
|
|
||||||
delete(file) -- Delete file
|
|
||||||
|
|
||||||
file : file to delete
|
|
||||||
|
|
||||||
example:
|
|
||||||
- vfs.delete(file)
|
|
||||||
"""
|
|
||||||
|
|
||||||
return xbmcvfs.delete(path)
|
|
||||||
|
|
||||||
|
|
||||||
def exists(path):
|
|
||||||
|
|
||||||
"""
|
|
||||||
exists(path) -- Check if file exists, returns true/false.
|
|
||||||
|
|
||||||
path : file or folder
|
|
||||||
|
|
||||||
example:
|
|
||||||
- success = vfs.exists(path)
|
|
||||||
"""
|
|
||||||
|
|
||||||
return xbmcvfs.exists(path)
|
|
||||||
|
|
||||||
|
|
||||||
def mkdir(path):
|
|
||||||
|
|
||||||
"""
|
|
||||||
mkdir(path) -- Create a folder.
|
|
||||||
|
|
||||||
path : folder
|
|
||||||
|
|
||||||
example:
|
|
||||||
- success = vfs.mkdir(path)
|
|
||||||
"""
|
|
||||||
|
|
||||||
return xbmcvfs.mkdir(path)
|
|
||||||
|
|
||||||
|
|
||||||
def rename(source, target):
|
|
||||||
|
|
||||||
"""
|
|
||||||
rename(file, newFileName) -- Rename file, returns true/false.
|
|
||||||
|
|
||||||
file : file to reaname
|
|
||||||
newFileName : new filename, including the full path
|
|
||||||
|
|
||||||
example:
|
|
||||||
- success = vfs.rename(file, newFileName)
|
|
||||||
"""
|
|
||||||
|
|
||||||
return xbmcvfs.rename(source, target)
|
|
||||||
|
|
||||||
|
|
||||||
def rmdir(path):
|
|
||||||
|
|
||||||
"""
|
|
||||||
rmdir(path) -- Remove a folder.
|
|
||||||
|
|
||||||
path : folder
|
|
||||||
|
|
||||||
example:
|
|
||||||
- success = vfs.rmdir(path)
|
|
||||||
"""
|
|
||||||
|
|
||||||
return xbmcvfs.rmdir(path)
|
|
||||||
|
|
||||||
|
|
||||||
def comparepathlists(list1, list2, fullpath=False):
|
|
||||||
|
|
||||||
"""
|
|
||||||
comparepathlists(list1, list2) -- Compare two lists of paths
|
|
||||||
|
|
||||||
list1 : list, contains paths (local or remote, absolute or relative)
|
|
||||||
list2 : list, contains paths (local or remote, absolute or relative)
|
|
||||||
fullpath : boolean, set True to compare perform straight comparison of lists
|
|
||||||
set False (default) to compare on filename portions of each list
|
|
||||||
|
|
||||||
returns: dictionary:
|
|
||||||
common_items: list, contains paths of items common to both lists
|
|
||||||
list1_items: list, contains paths of items found only in list1
|
|
||||||
list2_items: list, contains paths of items found only in list2
|
|
||||||
|
|
||||||
example:
|
|
||||||
- compare = comparepathlists(list1, list2)
|
|
||||||
"""
|
|
||||||
|
|
||||||
# initialise dict to store results and temp data
|
|
||||||
results = {}
|
|
||||||
temp_data = {}
|
|
||||||
|
|
||||||
if fullpath:
|
|
||||||
|
|
||||||
temp_path = lambda x: x
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
temp_path = lambda x: os.path.split(x)[1]
|
|
||||||
|
|
||||||
for path in list1:
|
|
||||||
|
|
||||||
temp_data['list1'].append(temp_path(path))
|
|
||||||
|
|
||||||
for path in list2:
|
|
||||||
|
|
||||||
temp_data['list2'].append(temp_path(path))
|
|
||||||
|
|
||||||
# get items not in list 2
|
|
||||||
results['list1_items'] = []
|
|
||||||
gen = (i for i, x in enumerate(temp_data['list1']) if not x in temp_data['list2'])
|
|
||||||
for i in gen:
|
|
||||||
results['list1_items'].append(list1[i])
|
|
||||||
|
|
||||||
# get items not in list 1
|
|
||||||
results['list2_items'] = []
|
|
||||||
gen = (i for i, x in enumerate(temp_data['list2']) if not x in temp_data['list1'])
|
|
||||||
for i in gen:
|
|
||||||
results['list2_items'].append(list2[i])
|
|
||||||
|
|
||||||
return results
|
|
Loading…
Reference in New Issue
Block a user