#!python3 import contextlib from logging import debug, info, warning, critical from enum import Enum, auto as enum_auto import yaml #from . import utils from stepper import Stepper import steps_install, steps_remove def strip_tar_ext(name): ext = '.tar.lzip' return name[:-len(ext)] if name.lower().endswith(ext) else name _installer_steps_dict = { 'download': steps_install.step_rsync, 'extract': steps_install.step_extract, 'clean': steps_install.step_clean, } _remover_steps_dict = { 'remove': steps_remove.step_remove, } _updater_steps_dict = dict(**_remover_steps_dict, **_installer_steps_dict) class GameStepper: def __init__(self, conf): self.game_installer = Stepper(conf, installer_steps_dict) self.game_remover = Stepper(conf, remover_steps_dict) self.game_updater = Stepper(conf, updater_steps_dict) self.curent = None def install(self, game_id): if self.current: return self.current = self.game_installer self.game_installer.start(self.conf.get_status(game_id)) def remove(self, game_id): if self.current: return self.current = self.game_remover self.game_remover.start(self.conf.get_status(game_id)) def update(self, game_id): if self.current: return self.current = self.game_updater self.game_updater.start(self.conf.get_status(game_id)) def stop(self): if self.current: self.current.stop() self.current = None def poll(self): if self.current: return self.current.poll() class GameManager: class State(Enum): IDLE = enum_auto() ONGOING = enum_auto() def __init__(self, conf): self.game_installer = Stepper(conf, installer_steps_dict) self.game_remover = Stepper(conf, remover_steps_dict) self.game_updater = Stepper(conf, updater_steps_dict) #def __init__(self, games_data_yaml_path, games_dir): # self.games_data_yaml_path = games_data_yaml_path # self.games_dir = games_dir # self.state = self.State.IDLE # self.update_state = self.State.IDLE # self.current_game_name = None # self.current_game_item = None # self.current_game_status = {} # with open(games_data_yaml_path) as stream: # self.games_data = yaml.safe_load(stream) # self.game_installer = GameInstaller( # self.games_data['repository']['host'], # self.games_data['repository']['path'], # self.games_dir, # ) # self.game_remover = GameRemover( # self.games_data['repository']['host'], # self.games_data['repository']['path'], # self.games_dir, # ) def get_game_item(self, name): self.current_game_item = next( item for item in self.games_data['games'] if item['name'] == name ) return self.current_game_item def get_game_status(self, name): self.current_game_status = {} with contextlib.suppress(FileNotFoundError): with open(f'{self.conf.gamedir}/{name}.yaml') as stream: self.current_game_status = yaml.safe_load(stream) return self.current_game_status def is_game_updatable(self, name): #self. ### FIXME: Stopped here ? if not self.current_game_name: return False ivers = self.current_game_status.get('installed_version', None) # only call "updatable" if there was at least a version installed # else, this is just an "installable" package. if ivers is not None and ivers < self.current_game_item['version']: return True return False def set_current_game(self, game_id): if self.current_game_name == name: return self.current_game_name = name self.get_game_item(name) self.get_game_status(name) def start_install(self, game_id): if self.state != self.State.IDLE: return self.status = self.State.INSTALLING self.set_current_game(name) self.game_installer.start( self.current_game_item, game_status=self.current_game_status, ) def start_remove(self, name): if self.state != self.State.IDLE: return self.status = self.State.REMOVING self.set_current_game(name) self.game_remover.start( self.current_game_item, game_status=self.current_game_status, ) def start_update(self, name): if self.state != self.State.IDLE: return self.status = self.State.UPDATING_REMOVING self.set_current_game(name) self.game_remover.start( self.current_game_item, game_status=self.current_game_status, ) def stop(self): self.state = self.State.IDLE self.game_remover.stop() self.game_installer.stop() def poll(self): entry_state = self.state return_value = { self.State.IDLE: (lambda: GameManagerBase.State.IDLE, 0, 0), self.State.INSTALLING: self.game_installer.poll, self.State.REMOVING: self.game_remover.poll, self.State.UPDATING_REMOVING: self.game_remover.poll, self.State.UPDATING_INSTALLING: self.game_installer.poll, }[entry_state]() if return_value[0] == GameManagerBase.Sate.IDLE: self.state = self.State.IDLE if entry_state == self.State.UPDATING_REMOVING: self.start_install(self.current_game_name) return_value = self.poll() return self.state, return_value[1], return_value[2]