From 7b656127e3fc0139f13820ddbffc3840924d7dcb Mon Sep 17 00:00:00 2001 From: vg Date: Mon, 19 Sep 2022 18:30:16 +0200 Subject: git-sync on seele --- gamechestcli/__main__.py | 20 +++++- gamechestcli/gamechest/cliactions/install.py | 7 +- gamechestcli/gamechest/cliactions/remove.py | 7 +- gamechestcli/gamechest/cliactions/run.py | 3 +- gamechestcli/gamechest/gameconfig.py | 99 ++++++++++++++++++++++++++++ gamechestcli/gamechest/gamedb.py | 10 +-- gamechestcli/gamechest/paths.py | 36 ---------- gamechestcli/gamechest/processor.py | 4 +- gamechestcli/gamechest/runners/install.py | 4 +- 9 files changed, 135 insertions(+), 55 deletions(-) create mode 100644 gamechestcli/gamechest/gameconfig.py delete mode 100644 gamechestcli/gamechest/paths.py diff --git a/gamechestcli/__main__.py b/gamechestcli/__main__.py index 1497e40..8fe912d 100755 --- a/gamechestcli/__main__.py +++ b/gamechestcli/__main__.py @@ -4,12 +4,17 @@ Manage games. Install, remove, run them. Usage: gamechest install gamechest remove - gamechest run --profile_id= + gamechest run [--profile_id=] + gamechest set [--profile_id=] [--remote_basedir=] [--gamesaves_path] + ''' +import sys + import docopt from gamechest.cliactions import install, remove, run +from gamechest.gameconfig import config def main(): @@ -21,7 +26,18 @@ def main(): elif args['remove']: remove.remove(args['']) elif args['run']: - run.run(args[''], args['--profile_id']) + profile_id = args['--profile_id'] or config.get_profile_id() + if not profile_id: + print('profile_id must be not null', file=sys.stderr) + run.run(args[''], profile_id) + elif args['set']: + if args['--profile_id']: + config.set_profile_id(args['--profile_id']) + if args['--remote_basedir']: + config.set_remote_basedir(args['--remote_basedir']) + if args['--gamesaves_path'] + config.set_gamesaves_path(args['--gamesaves_path']) + config.save() if __name__ == "__main__": diff --git a/gamechestcli/gamechest/cliactions/install.py b/gamechestcli/gamechest/cliactions/install.py index 8584d35..508dd48 100644 --- a/gamechestcli/gamechest/cliactions/install.py +++ b/gamechestcli/gamechest/cliactions/install.py @@ -1,14 +1,15 @@ import functools -from .. import gamedb, paths, processor +from .. import gamedb, processor +from ..gameconfig import config from ..runners.install import Install from ..statusdb import StatusDB def install_game(status_db, game_info): - remote_basedir = paths.get_remote_basedir() + remote_basedir = config.get_remote_basedir() source = f'{remote_basedir}/{game_info["package_name"]}' - dest = paths.get_games_install_basedir() / game_info['id'] + dest = config.get_games_install_basedir() / game_info['id'] dest.mkdir(parents=True, exist_ok=True) title = 'Installing game...' task = functools.partial(Install, source, dest) diff --git a/gamechestcli/gamechest/cliactions/remove.py b/gamechestcli/gamechest/cliactions/remove.py index d5452d5..6573aff 100644 --- a/gamechestcli/gamechest/cliactions/remove.py +++ b/gamechestcli/gamechest/cliactions/remove.py @@ -5,15 +5,16 @@ import selectors from rich import print from rich.progress import Progress as RichProgress -from .. import gamedb, paths, processor +from .. import gamedb, processor +from ..gameconfig import config from ..runners.remove import Remove from ..statusdb import StatusDB def remove_game(status_db, game_info): - remote_basedir = paths.get_remote_basedir() + remote_basedir = config.get_remote_basedir() path = ( - paths.get_games_install_basedir() + config.get_games_install_basedir() / game_info['id'] ) title = 'Removing game...' diff --git a/gamechestcli/gamechest/cliactions/run.py b/gamechestcli/gamechest/cliactions/run.py index b5369aa..d6791d0 100644 --- a/gamechestcli/gamechest/cliactions/run.py +++ b/gamechestcli/gamechest/cliactions/run.py @@ -1,14 +1,13 @@ import subprocess import sys -from .. import paths from ..gamedb import GameDB from ..statusdb import StatusDB def run_game(game_db, profile_id, game_info): command = game_db.get_game_command(profile_id, game_info['id']) - #tools_bin_path = paths.get_games_saves_tools_bin_path() + #tools_bin_path = config.get_games_saves_tools_bin_path() #new_env = dict(os.environ) #new_env['PATH'] = f'{tools_bin_path}:{new_env["PATH"]}' # path to mod/run scripts are already prepended by get_game_command, no diff --git a/gamechestcli/gamechest/gameconfig.py b/gamechestcli/gamechest/gameconfig.py new file mode 100644 index 0000000..effacd0 --- /dev/null +++ b/gamechestcli/gamechest/gameconfig.py @@ -0,0 +1,99 @@ +import contextlib +from pathlib import Path + +import yaml +from xdg import xdg_data_home + +from . import consts + + +DEFAULT_CONFIG_DICT = { + 'remote_basedir': 'jibril:/storage/games', + 'gamesaves_path': Path('~/syncthing/gamesaves').expanduser(), + + # profile_id: no default for this, only set by user. + 'profile_id': None, +} + + +def path_relative_to_user(path): + # first ensure the path is a Path + path = Path(path) + with contextlib.suppress(ValueError): + return '~' / path.relative_to(Path.home()) + # in case the path is not relative to the user home ValueError is raised, + # thus we return a fallback value (the path unmodified). + return path + + +class GameConfig: + + def __init__(self): + self.config = {} + game_config_path = xdg_config_home() / consts.XDG_RESOURCE_NAME + game_config_path.mkdir(parents=True, exist_ok=True) + game_config_filepath = game_config_path / 'config.yaml' + self.game_config_filepath = game_config_filepath + with contextlib.ExitStack() as stack: + stack.enter_context(contextlib.suppress(FileNotFoundError)) + fdin = stack.enter_context(open(game_config_filepath, 'rb')) + self.config = yaml.safe_load(fdin) + self.config = { + **DEFAULT_CONFIG_DICT, + **self.config, + } + # convert game_saves_path to a path if not already the case (in case + # loaded from yaml file). + self.config['gamesaves_path'] = ( + Path(self.config['gamesaves_path']) + .expanduser() + ) + + def get_remote_basedir(self): + return self.config['remote_basedir'] + + def get_gamesaves_path(self): + return self.config['gamesaves_path'] + + def get_games_saves_tools_bin_path(self): + return self.get_gamesaves_path() / 'tools' / 'bin' + + def get_profile_dir(self, profile_id): + return self.get_gamesaves_path() / 'profiles' / profile_id + + def get_games_database_path(self): + return self.get_gamesaves_path() / 'gamedata.yaml' + + def get_profile_id(self): + return self.config['profile_id'] + + def save(self): + dict_transformed_for_save = { **self.config } + dict_transformed_for_save['gamesaves_path'] = str( + path_relative_to_user( + self.config['gamesaves_path'] + ) + ) + with open(self.game_config_filepath, 'wb') as fdout: + yaml.safe_dump(dict_transformed_for_save, fdout) + + def set_profile_id(self, profile_id): + self.config['profile_id'] = profile_id + + def set_remote_basedir(self, remote_basedir): + self.config['remote_basedir'] = remote_basedir + + def set_gamesaves_path(self, path): + self.config['gamesaves_path'] = Path(path).expanduser() + + def get_games_install_basedir(self): + games_install_path = ( + xdg_data_home() / consts.XDG_RESOURCE_NAME / 'games' + ) + games_install_path.mkdir(parents=True, exist_ok=True) + return games_install_path + + +# default instance of gameconfig, same instance intended to be shared through +# all modules which needs it. +config = GameConfig() diff --git a/gamechestcli/gamechest/gamedb.py b/gamechestcli/gamechest/gamedb.py index 2000c52..99d3c9a 100644 --- a/gamechestcli/gamechest/gamedb.py +++ b/gamechestcli/gamechest/gamedb.py @@ -1,12 +1,12 @@ import yaml -from . import paths +from .gameconfig import config class GameDB: def __init__(self): - database_path = paths.get_games_database_path() + database_path = config.get_games_database_path() with open(database_path, 'rb') as fdin: self.db = yaml.safe_load(fdin) self.last_game_info = None @@ -25,12 +25,12 @@ class GameDB: game_mods = game_info.get('mods', []) game_mods += ['locked-run-profiledir'] - game_dir = paths.get_games_install_basedir() / game_info['id'] + game_dir = config.get_games_install_basedir() / game_info['id'] # note: glob('*/') globs regular files too, thus I filter on is_dir. game_dir = next(item for item in game_dir.glob('*') if item.is_dir()) - tools_bin_path = paths.get_games_saves_tools_bin_path() - profile_dir = paths.get_profile_dir(profile_id) + tools_bin_path = config.get_games_saves_tools_bin_path() + profile_dir = config.get_profile_dir(profile_id) command = [ *[f'{tools_bin_path}/mod-{item}' for item in game_mods], diff --git a/gamechestcli/gamechest/paths.py b/gamechestcli/gamechest/paths.py deleted file mode 100644 index 5e009a6..0000000 --- a/gamechestcli/gamechest/paths.py +++ /dev/null @@ -1,36 +0,0 @@ -import os -from pathlib import Path - -from xdg import xdg_data_home - -from . import consts - - -def get_remote_basedir(): - # TODO: unhardcode this - return 'jibril:/storage/games' - - -def get_games_saves_path(): - # TODO: unhardcode this - return Path(os.path.expanduser('~/games/.saves')) - #return Path(os.path.expanduser('~/game-saves')) - - -def get_games_saves_tools_bin_path(): - return get_games_saves_path() / 'tools' / 'bin' - - -def get_profile_dir(profile_id): - return get_games_saves_path() / 'profiles' / profile_id - - -def get_games_database_path(): - return get_games_saves_path() / 'gamedata.yaml' - - -def get_games_install_basedir(): - games_install_path = xdg_data_home() / consts.XDG_RESOURCE_NAME / 'games' - games_install_path.mkdir(parents=True, exist_ok=True) - return games_install_path - diff --git a/gamechestcli/gamechest/processor.py b/gamechestcli/gamechest/processor.py index 89a340c..e31d023 100644 --- a/gamechestcli/gamechest/processor.py +++ b/gamechestcli/gamechest/processor.py @@ -36,6 +36,6 @@ def process_task(title, task): rich_progress.update(global_id, completed=known_total) #rich_progress.console.print('installation ended with code:', rc) if rc != 0: - # success, update db to say installed - status_db.set_installed(game_info) + print('Process failed, aborting') + raise SystemExit(1) print('ended with code:', rc) diff --git a/gamechestcli/gamechest/runners/install.py b/gamechestcli/gamechest/runners/install.py index 36b0153..7b2ff7c 100644 --- a/gamechestcli/gamechest/runners/install.py +++ b/gamechestcli/gamechest/runners/install.py @@ -1,5 +1,6 @@ import functools import os +from pathlib import Path from .download import Download from .extract import Extract @@ -10,8 +11,7 @@ from .runnermulti import MultiSequencialRunnerBase class Install(MultiSequencialRunnerBase): def __init__(self, source, dest): - filename = os.path.split(source)[1] - tmpdest = os.path.join(dest, f'{filename}.rsynctmp') + tmpdest = Path(dest) / 'archive.rsynctmp' runners = [ functools.partial(Download, source, tmpdest), functools.partial(Extract, tmpdest, dest), -- cgit v1.2.3