mirror of
https://github.com/c9moser/sgbackup.git
synced 2026-01-20 03:50:13 +00:00
2025.01.21 10:02:45
This commit is contained in:
parent
4f2a5676c1
commit
52c986846e
@ -26,6 +26,8 @@ from gi.repository.GObject import (
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
from ..game import Game
|
from ..game import Game
|
||||||
from ..settings import settings
|
from ..settings import settings
|
||||||
@ -67,9 +69,6 @@ class Archiver:
|
|||||||
|
|
||||||
self.emit('backup',game,filename)
|
self.emit('backup',game,filename)
|
||||||
|
|
||||||
def restore(self,game,file)->bool:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def generate_new_backup_filename(self,game:Game)->str:
|
def generate_new_backup_filename(self,game:Game)->str:
|
||||||
dt = datetime.datetime.now()
|
dt = datetime.datetime.now()
|
||||||
basename = '.'.join(game.savegame_name,
|
basename = '.'.join(game.savegame_name,
|
||||||
@ -79,7 +78,13 @@ class Archiver:
|
|||||||
self.extensions[0])
|
self.extensions[0])
|
||||||
return os.path.join(settings.backup_dir,game.savegame_name,game.subdir,basename)
|
return os.path.join(settings.backup_dir,game.savegame_name,game.subdir,basename)
|
||||||
|
|
||||||
|
def _backup_progress(self,game:Game,fraction:float,message:str|None):
|
||||||
|
if fraction > 1.0:
|
||||||
|
fraction = 1.0
|
||||||
|
elif fraction < 0.0:
|
||||||
|
fraction = 0.0
|
||||||
|
|
||||||
|
self.emit("progress",game,fraction,message)
|
||||||
|
|
||||||
|
|
||||||
@Signal(name="backup",flags=SignalFlags.RUN_FIRST,
|
@Signal(name="backup",flags=SignalFlags.RUN_FIRST,
|
||||||
@ -94,6 +99,13 @@ class Archiver:
|
|||||||
def do_restore(self,filanme:str):
|
def do_restore(self,filanme:str):
|
||||||
raise NotImplementedError("{_class}.{function}() is not implemented!",_class=__class__,function="do_restore")
|
raise NotImplementedError("{_class}.{function}() is not implemented!",_class=__class__,function="do_restore")
|
||||||
|
|
||||||
|
@Signal(name="backup_progress",flags=SignalFlags.RUN_FIRST,
|
||||||
|
return_type=bool,arg_types=(Game,float,str))
|
||||||
|
def do_backup_progress(self,game:Game,fraction:float,message:str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ArchiverManager(GObject):
|
class ArchiverManager(GObject):
|
||||||
__global_archiver_manager = None
|
__global_archiver_manager = None
|
||||||
|
|
||||||
@ -116,5 +128,52 @@ class ArchiverManager(GObject):
|
|||||||
except:
|
except:
|
||||||
return self.__archivers["zipfile"]
|
return self.__archivers["zipfile"]
|
||||||
|
|
||||||
|
def _on_archiver_backup_progress_single(self,archiver,game,fraction,message):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _on_archiver_backup_progress_multi(self,archiver,game,fraction,message):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def backup(self,game:Game):
|
||||||
|
archiver = self.standard_archiver
|
||||||
|
archiver.backup(game)
|
||||||
|
|
||||||
|
|
||||||
|
def backup_many(self,games:list[Game]):
|
||||||
|
def thread_function(game):
|
||||||
|
archiver = self.standard_archiver
|
||||||
|
self._on_archiver_backup_progress_multi(archiver,game,1.0,"Finished ...")
|
||||||
|
|
||||||
|
game_list = list(games)
|
||||||
|
threadpool = {}
|
||||||
|
|
||||||
|
if len(game_list) > 8:
|
||||||
|
n = 8
|
||||||
|
else:
|
||||||
|
n = len(games)
|
||||||
|
|
||||||
|
for i in range(n):
|
||||||
|
game=game_list[0]
|
||||||
|
del game_list[0]
|
||||||
|
|
||||||
|
thread = threading.Thread(thread_function,args=game,daemon=True)
|
||||||
|
threadpool.append(thread)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
while threadpool:
|
||||||
|
time.sleep(0.25)
|
||||||
|
for i in range(len(threadpool)):
|
||||||
|
thread = threadpool[i]
|
||||||
|
if thread.is_alive():
|
||||||
|
continue
|
||||||
|
del threadpool[i]
|
||||||
|
|
||||||
|
if game_list:
|
||||||
|
game = game_list[0]
|
||||||
|
del game_list[0]
|
||||||
|
thread = threading.Thread(thread_function,args=game,daemon=True)
|
||||||
|
threadpool.append(thread)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -28,15 +28,26 @@ class ZipfileArchiver(Archiver):
|
|||||||
Archiver.__init__(self,"zipfile","ZipFile",[".zip"],"Archiver for .zip files.")
|
Archiver.__init__(self,"zipfile","ZipFile",[".zip"],"Archiver for .zip files.")
|
||||||
|
|
||||||
def do_backup(self, game:Game, filename:str):
|
def do_backup(self, game:Game, filename:str):
|
||||||
|
_calc_fraction = lambda n,cnt: ((1.0 / n) * cnt)
|
||||||
|
|
||||||
|
self._backup_progress(game,0.0,"Starting {game} ...".format(game=game.name))
|
||||||
files = game.get_backup_files()
|
files = game.get_backup_files()
|
||||||
|
div = len(files + 2)
|
||||||
|
cnt=1
|
||||||
game_data = json.dumps(game.serialize(),ensure_ascii=False,indent=4)
|
game_data = json.dumps(game.serialize(),ensure_ascii=False,indent=4)
|
||||||
with zipfile.ZipFile(filename,mode="w",
|
with zipfile.ZipFile(filename,mode="w",
|
||||||
compression=settings.zipfile_compression,
|
compression=settings.zipfile_compression,
|
||||||
compresslevel=settings.zipfile_compresslevel) as zf:
|
compresslevel=settings.zipfile_compresslevel) as zf:
|
||||||
zf.writestr("game.conf",game_data)
|
self._backup_progress(game,_calc_fraction(div,cnt),"{} -> {}".format(game.name,"gameconf.json"))
|
||||||
|
zf.writestr("gameconf.json",game_data)
|
||||||
for path,arcname in files.items():
|
for path,arcname in files.items():
|
||||||
|
cnt+=1
|
||||||
|
self._backup_progress(game,_calc_fraction(div,cnt),"{} -> {}".format(game.name,arcname))
|
||||||
zf.write(path,arcname)
|
zf.write(path,arcname)
|
||||||
|
|
||||||
|
self._backup_progress("{game} ... FINISHED".format(game=game.name))
|
||||||
|
|
||||||
|
|
||||||
def is_archive(self,filename:str)->bool:
|
def is_archive(self,filename:str)->bool:
|
||||||
if zipfile.is_zipfile(filename):
|
if zipfile.is_zipfile(filename):
|
||||||
with zipfile.ZipFile(filename,"r") as zf:
|
with zipfile.ZipFile(filename,"r") as zf:
|
||||||
@ -47,6 +58,7 @@ class ZipfileArchiver(Archiver):
|
|||||||
def do_restore(self,filename:str):
|
def do_restore(self,filename:str):
|
||||||
# TODO: convert savegame dir if not the same SvaegameType!!!
|
# TODO: convert savegame dir if not the same SvaegameType!!!
|
||||||
|
|
||||||
|
|
||||||
if not zipfile.is_zipfile(filename):
|
if not zipfile.is_zipfile(filename):
|
||||||
raise RuntimeError("\"{filename}\" is not a valid sgbackup zipfile archive!")
|
raise RuntimeError("\"{filename}\" is not a valid sgbackup zipfile archive!")
|
||||||
|
|
||||||
|
|||||||
22
sgbackup/gui/_backupdialog.py
Normal file
22
sgbackup/gui/_backupdialog.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
###############################################################################
|
||||||
|
# sgbackup - The SaveGame Backup tool #
|
||||||
|
# Copyright (C) 2024 Christian Moser #
|
||||||
|
# #
|
||||||
|
# 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 <https://www.gnu.org/licenses/>. #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
from ..game import GameManager,Game
|
||||||
|
from ..archiver import ArchiverManager
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user