mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-18 16:53:38 +00:00
Merge branch 'feature/AddConfigBackup' into dev
This commit is contained in:
commit
71787f010f
3 changed files with 125 additions and 3 deletions
|
@ -13,7 +13,6 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with SickGear. If not, see <http://www.gnu.org/licenses/>.
|
# along with SickGear. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
|
@ -23,6 +22,7 @@ import os
|
||||||
import re
|
import re
|
||||||
import signal
|
import signal
|
||||||
import socket
|
import socket
|
||||||
|
import time
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
# apparently py2exe won't build these unless they're imported somewhere
|
# apparently py2exe won't build these unless they're imported somewhere
|
||||||
|
@ -54,6 +54,7 @@ from configobj import ConfigObj
|
||||||
from api_trakt import TraktAPI
|
from api_trakt import TraktAPI
|
||||||
|
|
||||||
from _23 import b64encodestring, decode_bytes, scandir
|
from _23 import b64encodestring, decode_bytes, scandir
|
||||||
|
from sg_helpers import remove_file_perm
|
||||||
from six import iteritems, string_types
|
from six import iteritems, string_types
|
||||||
import sg_helpers
|
import sg_helpers
|
||||||
|
|
||||||
|
@ -2423,7 +2424,69 @@ def save_config():
|
||||||
new_config['ANIME'] = {}
|
new_config['ANIME'] = {}
|
||||||
new_config['ANIME']['anime_treat_as_hdtv'] = int(ANIME_TREAT_AS_HDTV)
|
new_config['ANIME']['anime_treat_as_hdtv'] = int(ANIME_TREAT_AS_HDTV)
|
||||||
|
|
||||||
|
from sg_helpers import copy_file
|
||||||
|
backup_config = re.sub(r'\.ini$', '.bak', CONFIG_FILE)
|
||||||
|
from .config import check_valid_config
|
||||||
|
try:
|
||||||
|
copy_file(CONFIG_FILE, backup_config)
|
||||||
|
if not check_valid_config(backup_config):
|
||||||
|
logger.error('config file seams to be invalid, not backing up.')
|
||||||
|
remove_file_perm(backup_config)
|
||||||
|
backup_config = None
|
||||||
|
except (BaseException, Exception):
|
||||||
|
backup_config = None
|
||||||
|
|
||||||
|
for _ in range(0, 3):
|
||||||
new_config.write()
|
new_config.write()
|
||||||
|
if check_valid_config(CONFIG_FILE):
|
||||||
|
return
|
||||||
|
logger.warning('saving config file failed, retrying...')
|
||||||
|
remove_file_perm(CONFIG_FILE)
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# we only get here if the config saving failed multiple times
|
||||||
|
if None is not backup_config and os.path.isfile(backup_config):
|
||||||
|
logger.error('saving config file failed, using backup file')
|
||||||
|
try:
|
||||||
|
copy_file(backup_config, CONFIG_FILE)
|
||||||
|
logger.log('using old backup config file')
|
||||||
|
return
|
||||||
|
except (BaseException, Exception):
|
||||||
|
logger.error('failed to use backup config file')
|
||||||
|
|
||||||
|
from sg_helpers import scantree
|
||||||
|
try:
|
||||||
|
target_base = os.path.join(BACKUP_DB_PATH or os.path.join(DATA_DIR, 'backup'))
|
||||||
|
file_list = [f for f in scantree(target_base, include='config', filter_kind=False)]
|
||||||
|
if file_list:
|
||||||
|
logger.log('trying to use latest config.ini backup')
|
||||||
|
# sort newest to oldest backup
|
||||||
|
file_list.sort(key=lambda _f: _f.stat(follow_symlinks=False).st_mtime)
|
||||||
|
import zipfile
|
||||||
|
try:
|
||||||
|
with zipfile.ZipFile(file_list[0].path, mode='r') as zf:
|
||||||
|
zf.extractall(target_base)
|
||||||
|
backup_config_file = os.path.join(target_base, 'config.ini')
|
||||||
|
if os.path.isfile(backup_config_file):
|
||||||
|
os.replace(backup_config_file, CONFIG_FILE)
|
||||||
|
if check_valid_config(CONFIG_FILE):
|
||||||
|
logger.log(f'used latest config.ini backup file: {file_list[0].name}')
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
logger.error(f'failed to use latest config.ini backup file: {file_list[0].name}')
|
||||||
|
remove_file_perm(CONFIG_FILE)
|
||||||
|
except (BaseException, Exception):
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
remove_file_perm(backup_config_file)
|
||||||
|
except (BaseException, Exception):
|
||||||
|
pass
|
||||||
|
logger.error('failed to use latest config.ini')
|
||||||
|
except (BaseException, Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
logger.error('saving config file failed and no backup available')
|
||||||
|
|
||||||
|
|
||||||
def launch_browser(start_port=None):
|
def launch_browser(start_port=None):
|
||||||
|
|
|
@ -24,6 +24,7 @@ from . import db, helpers, logger, naming
|
||||||
from lib.api_trakt import TraktAPI
|
from lib.api_trakt import TraktAPI
|
||||||
|
|
||||||
from _23 import urlsplit, urlunsplit
|
from _23 import urlsplit, urlunsplit
|
||||||
|
from sg_helpers import compress_file, copy_file, remove_file_perm, scantree, try_int
|
||||||
from six import string_types
|
from six import string_types
|
||||||
|
|
||||||
|
|
||||||
|
@ -455,6 +456,58 @@ def check_setting_str(config, cfg_name, item_name, def_val, log=True):
|
||||||
|
|
||||||
return (my_val, def_val)['None' == my_val]
|
return (my_val, def_val)['None' == my_val]
|
||||||
|
|
||||||
|
def check_valid_config(filename):
|
||||||
|
# type: (str) -> bool
|
||||||
|
"""
|
||||||
|
check if file appears to be a vaild config file
|
||||||
|
:param filename: full path config file name
|
||||||
|
"""
|
||||||
|
from configobj import ConfigObj
|
||||||
|
try:
|
||||||
|
conf_obj = ConfigObj(filename)
|
||||||
|
if not (all(section in conf_obj for section in ('General', 'GUI')) and 'config_version' in conf_obj['General']
|
||||||
|
and isinstance(try_int(conf_obj['General']['config_version'], None), int)):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
except (BaseException, Exception):
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
del conf_obj
|
||||||
|
except (BaseException, Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def backup_config():
|
||||||
|
"""
|
||||||
|
backup config.ini
|
||||||
|
"""
|
||||||
|
logger.log('backing up config.ini')
|
||||||
|
try:
|
||||||
|
if not check_valid_config(sickgear.CONFIG_FILE):
|
||||||
|
logger.error('config file seams to be invalid, not backing up.')
|
||||||
|
return
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
d = datetime.datetime.strftime(now, '%Y-%m-%d')
|
||||||
|
t = datetime.datetime.strftime(now, '%H-%M')
|
||||||
|
target_base = os.path.join(sickgear.BACKUP_DB_PATH or os.path.join(sickgear.DATA_DIR, 'backup'))
|
||||||
|
target = os.path.join(target_base, 'config.ini')
|
||||||
|
copy_file(sickgear.CONFIG_FILE, target)
|
||||||
|
if not check_valid_config(target):
|
||||||
|
logger.error('config file seams to be invalid, not backing up.')
|
||||||
|
remove_file_perm(target)
|
||||||
|
return
|
||||||
|
compress_file(target, 'config.ini')
|
||||||
|
os.rename(re.sub(r'\.ini$', '.zip', target), os.path.join(target_base, f'config_{d}_{t}.zip'))
|
||||||
|
# remove old files
|
||||||
|
use_count = (1, sickgear.BACKUP_DB_MAX_COUNT)[not sickgear.BACKUP_DB_ONEDAY]
|
||||||
|
file_list = [f for f in scantree(target_base, include='config', filter_kind=False)]
|
||||||
|
if use_count < len(file_list):
|
||||||
|
file_list.sort(key=lambda _f: _f.stat(follow_symlinks=False).st_mtime, reverse=True)
|
||||||
|
for direntry in file_list[use_count:]:
|
||||||
|
remove_file_perm(direntry.path)
|
||||||
|
except (BaseException, Exception):
|
||||||
|
logger.error('backup config.ini error')
|
||||||
|
|
||||||
|
|
||||||
class ConfigMigrator(object):
|
class ConfigMigrator(object):
|
||||||
def __init__(self, config_obj):
|
def __init__(self, config_obj):
|
||||||
|
@ -926,3 +979,4 @@ class ConfigMigrator(object):
|
||||||
|
|
||||||
def _migrate_v22(self):
|
def _migrate_v22(self):
|
||||||
self.deprecate_anon_service()
|
self.deprecate_anon_service()
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ from exceptions_helper import ex
|
||||||
import sickgear
|
import sickgear
|
||||||
from . import db, logger, network_timezones, properFinder, ui
|
from . import db, logger, network_timezones, properFinder, ui
|
||||||
from .scheduler import Job
|
from .scheduler import Job
|
||||||
|
from .config import backup_config
|
||||||
|
|
||||||
# noinspection PyUnreachableCode
|
# noinspection PyUnreachableCode
|
||||||
if False:
|
if False:
|
||||||
|
@ -70,7 +71,11 @@ class ShowUpdater(Job):
|
||||||
if sickgear.db.db_supports_backup and 0 < sickgear.BACKUP_DB_MAX_COUNT:
|
if sickgear.db.db_supports_backup and 0 < sickgear.BACKUP_DB_MAX_COUNT:
|
||||||
logger.log('backing up all db\'s')
|
logger.log('backing up all db\'s')
|
||||||
try:
|
try:
|
||||||
sickgear.db.backup_all_dbs(sickgear.BACKUP_DB_PATH or os.path.join(sickgear.DATA_DIR, 'backup'))
|
backup_success = sickgear.db.backup_all_dbs(
|
||||||
|
sickgear.BACKUP_DB_PATH or os.path.join(sickgear.DATA_DIR, 'backup'))
|
||||||
|
if isinstance(backup_success, tuple) and backup_success[0]:
|
||||||
|
# backup config.ini
|
||||||
|
backup_config()
|
||||||
except (BaseException, Exception):
|
except (BaseException, Exception):
|
||||||
logger.error('backup db error')
|
logger.error('backup db error')
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue