mirror of
https://github.com/c9moser/sgbackup.git
synced 2026-01-19 19:40:13 +00:00
2025.01.26 18:36:15 (desktop)
This commit is contained in:
parent
2daf302e54
commit
604d753d1b
@ -33,12 +33,12 @@ from ..game import Game
|
||||
from ..settings import settings
|
||||
|
||||
class Archiver(GObject):
|
||||
def __init__(self,key:str,name:str,extensions:list[str],decription:str|None=None):
|
||||
def __init__(self,key:str,name:str,extensions:list[str],description:str|None=None):
|
||||
GObject.__init__(self)
|
||||
self.__key = key
|
||||
self.__name = name
|
||||
if decription:
|
||||
self.__description = decription
|
||||
if description:
|
||||
self.__description = description
|
||||
else:
|
||||
self.__description = ""
|
||||
|
||||
|
||||
157
sgbackup/archiver/tarfilearchiver.py
Normal file
157
sgbackup/archiver/tarfilearchiver.py
Normal file
@ -0,0 +1,157 @@
|
||||
###############################################################################
|
||||
# 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 gi.repository.GObject import Property
|
||||
from gi.repository import GLib
|
||||
|
||||
from ._archiver import Archiver
|
||||
from tarfile import TarFile
|
||||
from tempfile import mkdtemp,NamedTemporaryFile
|
||||
import json
|
||||
import os
|
||||
from ..game import Game
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class TarfileArchiver(Archiver):
|
||||
def __init__(self,
|
||||
key='tarfile',
|
||||
name="TarFile",
|
||||
extensions=['.tar'],
|
||||
description="Archiver for .tar files.",
|
||||
compression=None):
|
||||
Archiver.__init__(self,key,name,extensions,description)
|
||||
if compression is None:
|
||||
self.__compression=""
|
||||
else:
|
||||
self.__compression=compression
|
||||
|
||||
@Property
|
||||
def compression(self):
|
||||
return self.__compression
|
||||
|
||||
def is_archive(self, filename):
|
||||
if (Archiver.is_archive()):
|
||||
try:
|
||||
with TarFile(filename,"r:{}".format(self.compression)) as tf:
|
||||
return ("gameconf.json" in tf.getnames())
|
||||
except:
|
||||
pass
|
||||
return False
|
||||
|
||||
def do_backup(self, game, filename):
|
||||
_calc_fraction = lambda n,cnt: ((1.0 / n) * cnt)
|
||||
|
||||
self._backup_progress(game,0.0,"Starting {game} ...".format(game.name))
|
||||
files = game.get_backup_files()
|
||||
|
||||
n = len(files) + 2
|
||||
cnt=1
|
||||
data=json.dumps(game.serialize(),ensure_ascii=False,indent=4)
|
||||
|
||||
with TarFile(filename,'x:{}'.format(self.compression)) as tf:
|
||||
self._backup_progress(game,_calc_fraction(n,cnt),"gameconf.json")
|
||||
gcf = os.path.join(GLib.get_tmp_dir(),"sgbackup-" + GLib.get_user_name() + "." + "backup." + game.key + ".gameconf.tmp")
|
||||
with open(gcf,"wt",encoding="utf-8") as gcfile:
|
||||
gcfile.write(data)
|
||||
|
||||
tf.add(gcf,"gameconf.json")
|
||||
|
||||
for path,arcname in files:
|
||||
cnt += 1
|
||||
self._backup_progress(game,_calc_fraction(n,cnt),"arcname")
|
||||
tf.add(path,arcname)
|
||||
|
||||
self._backup_progress(game,1.0,message="Finished ...")
|
||||
return True
|
||||
|
||||
def do_restore(self,filename):
|
||||
def rmdir_recursive(dir):
|
||||
for dirent in os.listdir(dir):
|
||||
fname = os.path.join(dirent)
|
||||
|
||||
if os.path.islink(fname):
|
||||
os.unlink(fname)
|
||||
elif os.path.isdir(fname):
|
||||
rmdir_recursive(fname)
|
||||
else:
|
||||
os.unlink(fname)
|
||||
os.rmdir(dir)
|
||||
|
||||
if not self.is_archive(filename):
|
||||
raise RuntimeError("{file} is not a vaild {archiver} archive!".format(file=filename,archiver=self.name))
|
||||
|
||||
tempdir = mkdtemp(suffix="-sgbackup")
|
||||
tempfile= os.path.join(tempdir,"gameconf.json")
|
||||
try:
|
||||
with TarFile(filename,'r:{}'.format(self.compression)) as tf:
|
||||
tf.extract("gameconf.json",tempdir)
|
||||
with open(tempfile,"r",encoding="utf-8") as ifile:
|
||||
game = Game.new_from_json_file(tempfile)
|
||||
if not os.path.isdir(game.savegame_root):
|
||||
os.makedirs(game.savegame_root)
|
||||
|
||||
for arcname in [i for i in tf.getnames() if i not in ("gameconf.json",'.','..')]:
|
||||
tf.extract(arcname,path=game.savegame_root)
|
||||
|
||||
rmdir_recursive(tempdir)
|
||||
return True
|
||||
except Exception as ex:
|
||||
logger.error("Restoring archive {file} failed! ({message})".format(
|
||||
file=filename,
|
||||
message=str(ex)))
|
||||
|
||||
if os.path.isdir(tempdir):
|
||||
rmdir_recursive(tempdir)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class TarfileBz2Archiver(TarfileArchiver):
|
||||
def __init__(self):
|
||||
TarfileArchiver.__init__(self,
|
||||
'tarfile-bz2',
|
||||
"TarfileBzip2",
|
||||
['.tbz','.tar.bz2','tar.bzip2'],
|
||||
"Archiver for bzip2 compressedd tar archives.",
|
||||
"bz2")
|
||||
|
||||
class TarfileGzArchiver(TarfileArchiver):
|
||||
def __init__(self):
|
||||
TarfileArchiver.__init__(self,
|
||||
'tarfile-gz',
|
||||
"TarfileGzip",
|
||||
['.tgz','.tar.gz'],
|
||||
"Archiver for gzip compressed tar archives.",
|
||||
"gz")
|
||||
|
||||
class TarfileXzArchiver(TarfileArchiver):
|
||||
def __init__(self):
|
||||
TarfileArchiver.__init__(self,
|
||||
'tarfile-xz',
|
||||
"TarfileXz",
|
||||
['.txz','.tar.xz'],
|
||||
"Archiver for xz compressed tar archives.",
|
||||
'xz')
|
||||
|
||||
ARCHIVERS=[
|
||||
TarfileArchiver(),
|
||||
TarfileBz2Archiver(),
|
||||
TarfileGzArchiver(),
|
||||
TarfileXzArchiver(),
|
||||
]
|
||||
@ -68,7 +68,7 @@ class ZipfileArchiver(Archiver):
|
||||
except:
|
||||
game = zip_game
|
||||
|
||||
if not game.savegame_root:
|
||||
if not os.path.isdir(game.savegame_root):
|
||||
os.makedirs(game.savegame_root)
|
||||
|
||||
extract_files = [i for i in zf.filelist if i.startswith(zip_game.savegame_dir + "/")]
|
||||
|
||||
@ -534,7 +534,7 @@ class AppWindow(Gtk.ApplicationWindow):
|
||||
builder = Gtk.Builder.new()
|
||||
|
||||
Gtk.ApplicationWindow.__init__(self,**kwargs)
|
||||
self.set_default_size(800,600)
|
||||
self.set_default_size(800,700)
|
||||
self.set_icon_name('org.sgbackup.sgbackup-symbolic')
|
||||
|
||||
self.__builder = builder
|
||||
@ -561,6 +561,7 @@ class AppWindow(Gtk.ApplicationWindow):
|
||||
self.__vpaned.set_end_child(self.backupview)
|
||||
self.__vpaned.set_resize_start_child(True)
|
||||
self.__vpaned.set_resize_end_child(True)
|
||||
self.__vpaned.set_position(400)
|
||||
|
||||
vbox.append(self.__vpaned)
|
||||
|
||||
|
||||
@ -43,6 +43,13 @@ for _zc,_zs in ZIPFILE_COMPRESSION_STR.items():
|
||||
del _zc
|
||||
del _zs
|
||||
|
||||
if sys.platform.lower() == 'win32':
|
||||
PLATFORM_WINDOWS = True
|
||||
import winreg
|
||||
else:
|
||||
PLATFORM_WINDOWS = False
|
||||
|
||||
|
||||
class Settings(GObject.GObject):
|
||||
__gtype_name__ = "Settings"
|
||||
|
||||
@ -129,6 +136,27 @@ class Settings(GObject.GObject):
|
||||
for v in vars:
|
||||
self.parser.set('variables',v[0],v[1])
|
||||
|
||||
@GObject.Property(type=str)
|
||||
def steam_installpath(self):
|
||||
if self.parser.has_section('steam') and self.parser.has_option('installpath'):
|
||||
return self.parser.get('steam','installdir')
|
||||
|
||||
if PLATFORM_WINDOWS:
|
||||
for i in ('SOFTWARE\\WOW6432Node\\Valve\\Steam','SOFTWARE\\Valve\\Steam'):
|
||||
try:
|
||||
skey = None
|
||||
skey = winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE,i)
|
||||
svalue = winreg.QueryValueEx(skey,'InstallPath')[0]
|
||||
if svalue:
|
||||
self.parser.set('steam','installpath',svalue)
|
||||
return svalue
|
||||
except:
|
||||
continue
|
||||
finally:
|
||||
if skey:
|
||||
skey.Close()
|
||||
return ""
|
||||
|
||||
def add_variable(self,name:str,value:str):
|
||||
self.parser.set('variables',name,value)
|
||||
|
||||
@ -149,6 +177,8 @@ class Settings(GObject.GObject):
|
||||
ret.update({
|
||||
"DOCUMENTS": GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DOCUMENTS),
|
||||
"DOCUMENTS_DIR": GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DOCUMENTS),
|
||||
"DATADIR": GLib.get_user_data_dir(),
|
||||
"STEAM_INSTALLPATH": self.steam_installpath,
|
||||
})
|
||||
ret.update(self.variables)
|
||||
return ret
|
||||
|
||||
Loading…
Reference in New Issue
Block a user