summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rwxr-xr-xgamechestcli/__main__.py28
-rw-r--r--gamechestcli/gamechest/cli.py1
-rw-r--r--gamechestcli/gamechest/cliactions/install.py5
-rw-r--r--gamechestcli/gamechest/cliactions/remove.py4
-rw-r--r--gamechestcli/gamechest/cliactions/run.py31
-rw-r--r--gamechestcli/gamechest/gamedb.py34
-rw-r--r--gamechestcli/gamechest/paths.py23
-rw-r--r--gamechestcli/gamechest/statusdb.py24
-rw-r--r--gamechestcli/requirements.txt3
10 files changed, 134 insertions, 27 deletions
diff --git a/Makefile b/Makefile
index 6dde37e..a7c6f06 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,11 @@
static-fix:
isort --order-by-type --atomic gamechestcli
+zipapp:
+ mkdir /tmp/gamechest.zipapp
+ pip3 install --target /tmp/gamechest.zipapp -r gamechestcli/requirements.txt
+ #pip3 install --target /tmp/gamechest.zipapp gamechestcli
+ rsync -Pa gamechestcli/. /tmp/gamechest.zipapp/.
+ python3 -m zipapp -p "/usr/bin/env python3" /tmp/gamechest.zipapp
+ rm -r /tmp/gamechest.zipapp
+ if [ -e ~/games/.saves ]; then mv /tmp/gamechest.pyz ~/games/.saves/tools/bin/. ; elif [ -e ~/game-saves ]; then mv /tmp/gamechest.pyz ~/game-saves/tools/bin/. ; fi
diff --git a/gamechestcli/__main__.py b/gamechestcli/__main__.py
new file mode 100755
index 0000000..1497e40
--- /dev/null
+++ b/gamechestcli/__main__.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python3
+'''
+Manage games. Install, remove, run them.
+
+Usage: gamechest install <GAME_ID>
+ gamechest remove <GAME_ID>
+ gamechest run --profile_id=<PROFILE_ID> <GAME_ID>
+'''
+
+import docopt
+
+from gamechest.cliactions import install, remove, run
+
+
+def main():
+ args = docopt.docopt(__doc__)
+ #print(args); raise SystemExit(0)
+
+ if args['install']:
+ install.install(args['<GAME_ID>'])
+ elif args['remove']:
+ remove.remove(args['<GAME_ID>'])
+ elif args['run']:
+ run.run(args['<GAME_ID>'], args['--profile_id'])
+
+
+if __name__ == "__main__":
+ main()
diff --git a/gamechestcli/gamechest/cli.py b/gamechestcli/gamechest/cli.py
deleted file mode 100644
index 8b13789..0000000
--- a/gamechestcli/gamechest/cli.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/gamechestcli/gamechest/cliactions/install.py b/gamechestcli/gamechest/cliactions/install.py
index ed2437f..8584d35 100644
--- a/gamechestcli/gamechest/cliactions/install.py
+++ b/gamechestcli/gamechest/cliactions/install.py
@@ -8,7 +8,8 @@ from ..statusdb import StatusDB
def install_game(status_db, game_info):
remote_basedir = paths.get_remote_basedir()
source = f'{remote_basedir}/{game_info["package_name"]}'
- dest = paths.get_games_install_basedir()
+ dest = paths.get_games_install_basedir() / game_info['id']
+ dest.mkdir(parents=True, exist_ok=True)
title = 'Installing game...'
task = functools.partial(Install, source, dest)
processor.process_task(title, task)
@@ -16,7 +17,7 @@ def install_game(status_db, game_info):
def install(game_id):
- game_db = gamdb.GameDB()
+ game_db = gamedb.GameDB()
game_info = game_db.get_game_info(game_id)
status_db = StatusDB()
if status_db.is_installed(game_info):
diff --git a/gamechestcli/gamechest/cliactions/remove.py b/gamechestcli/gamechest/cliactions/remove.py
index 1668e63..d5452d5 100644
--- a/gamechestcli/gamechest/cliactions/remove.py
+++ b/gamechestcli/gamechest/cliactions/remove.py
@@ -14,7 +14,7 @@ def remove_game(status_db, game_info):
remote_basedir = paths.get_remote_basedir()
path = (
paths.get_games_install_basedir()
- / status_db.get_installed_game_name(game_info['id'])
+ / game_info['id']
)
title = 'Removing game...'
task = functools.partial(Remove, path)
@@ -23,7 +23,7 @@ def remove_game(status_db, game_info):
def remove(game_id):
- game_db = gamdb.GameDB()
+ game_db = gamedb.GameDB()
game_info = game_db.get_game_info(game_id)
status_db = StatusDB()
if status_db.is_installed(game_info):
diff --git a/gamechestcli/gamechest/cliactions/run.py b/gamechestcli/gamechest/cliactions/run.py
index e69de29..b5369aa 100644
--- a/gamechestcli/gamechest/cliactions/run.py
+++ b/gamechestcli/gamechest/cliactions/run.py
@@ -0,0 +1,31 @@
+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()
+ #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
+ # need to modify the path environment variable.
+ subprocess.run(command)
+
+
+def run(game_id, profile_id):
+ game_db = GameDB()
+ status_db = StatusDB()
+ game_info = game_db.get_game_info(game_id)
+ if not status_db.is_installed(game_info):
+ # games is already installed
+ print('Game', game_id, 'is not installed, aborting.', file=sys.stderr)
+ return
+ run_game(game_db, profile_id, game_info)
+
+
+if __name__ == "__main__":
+ run(*sys.argv[1:])
diff --git a/gamechestcli/gamechest/gamedb.py b/gamechestcli/gamechest/gamedb.py
index d932438..2000c52 100644
--- a/gamechestcli/gamechest/gamedb.py
+++ b/gamechestcli/gamechest/gamedb.py
@@ -9,9 +9,35 @@ class GameDB:
database_path = paths.get_games_database_path()
with open(database_path, 'rb') as fdin:
self.db = yaml.safe_load(fdin)
+ self.last_game_info = None
+ def get_game_info(self, game_id=None):
+ if self.last_game_info and self.last_game_info['id'] == game_id:
+ return self.last_game_info
+ game_info = next(game_info
+ for game_info in self.db['games']
+ if game_info['id'] == game_id)
+ self.last_game_info = game_info
+ return game_info
- def get_game_info(self, game_id):
- return next(game_info
- for game_info in self.db['games']
- if game_info['id'] == game_id)
+ def get_game_command(self, profile_id, game_id=None):
+ game_info = self.get_game_info(game_id)
+ game_mods = game_info.get('mods', [])
+ game_mods += ['locked-run-profiledir']
+
+ game_dir = paths.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)
+
+ command = [
+ *[f'{tools_bin_path}/mod-{item}' for item in game_mods],
+ profile_dir,
+ game_dir,
+ *[item if index > 0 else f'{tools_bin_path}/{item}'
+ for index, item in enumerate(game_info['command'])],
+ ]
+
+ return command
diff --git a/gamechestcli/gamechest/paths.py b/gamechestcli/gamechest/paths.py
index 53cafe0..5e009a6 100644
--- a/gamechestcli/gamechest/paths.py
+++ b/gamechestcli/gamechest/paths.py
@@ -1,19 +1,32 @@
import os
+from pathlib import Path
from xdg import xdg_data_home
from . import consts
-def get_games_database_path():
+def get_remote_basedir():
# TODO: unhardcode this
- #return os.path.expanduser('~/games/.saves/gamedata.yaml')
- return os.path.expanduser('~/game-saves/gamedata.yaml')
+ return 'jibril:/storage/games'
-def get_remote_basedir():
+def get_games_saves_path():
# TODO: unhardcode this
- return 'jibril:/storage/games'
+ 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():
diff --git a/gamechestcli/gamechest/statusdb.py b/gamechestcli/gamechest/statusdb.py
index a41fe32..e343d8e 100644
--- a/gamechestcli/gamechest/statusdb.py
+++ b/gamechestcli/gamechest/statusdb.py
@@ -66,18 +66,18 @@ class StatusDB:
game_info['id'],
))
- def get_installed_game_name(self, game_id):
- row = (
- self.conn
- .execute('SELECT version_installed FROM status WHERE game_id = ?',
- (game_id, ))
- .fetchone()
- )
- if row is None:
- #return False
- raise ValueError('Game not found')
- version_installed = row[0]
- return f'{game_id}_v{version_installed}'
+ #def get_installed_game_name(self, game_id):
+ # row = (
+ # self.conn
+ # .execute('SELECT version_installed FROM status WHERE game_id = ?',
+ # (game_id, ))
+ # .fetchone()
+ # )
+ # if row is None:
+ # #return False
+ # raise ValueError('Game not found')
+ # version_installed = row[0]
+ # return f'{game_id}_v{version_installed}'
def set_uninstalled(self, game_info):
return self.set_installed(game_info, installed=False)
diff --git a/gamechestcli/requirements.txt b/gamechestcli/requirements.txt
index 576e0b3..638d583 100644
--- a/gamechestcli/requirements.txt
+++ b/gamechestcli/requirements.txt
@@ -1,4 +1,5 @@
+docopt
humanfriendly
pyyaml
-xdg
rich
+xdg