Installer rewrite (WIP)

This commit is contained in:
Mathieu Comandon 2013-05-25 13:08:39 +02:00
parent 26f59c9bc7
commit 14a6881627
4 changed files with 105 additions and 84 deletions

View file

@ -3,6 +3,17 @@ Writing installers
==================
Displaying an 'Insert disc' dialog
----------------------------------
The ``insert-disc`` command will display a message box to the user requesting
him to insert the game's disc into the optical drive. A link to CDEmu homepage's
and PPA will also be displayed if the program isn't detected on the machine,
otherwise it will be replaced with a button to open gCDEmu.
An optional parameter ``message`` will override the default text if given.
Moving files
------------

View file

@ -33,6 +33,7 @@ from lutris.util.log import logger
from lutris.util import http
from lutris.util.strings import slugify
from lutris.util.files import calculate_md5
from lutris.util import extract
from lutris.game import LutrisGame
#from lutris.config import LutrisConfig
from lutris.gui.dialogs import ErrorDialog, FileDialog
@ -42,39 +43,6 @@ from lutris import settings
from lutris.runners import import_task
def unzip(filename, dest=None):
"""Unzips a file"""
command = ["unzip", '-o', filename]
if dest:
command = command + ['-d', dest]
subprocess.call(command)
def unrar(filename):
"""Unrar a file"""
subprocess.call(["unrar", "x", filename])
def untar(filename, dest=None, method='gzip'):
"""Untar a file"""
cwd = os.getcwd()
if dest is None or not os.path.exists(dest):
dest = cwd
logger.debug("Will extract to %s" % dest)
os.chdir(dest)
if method == 'gzip':
compression_flag = 'z'
elif method == 'bzip2':
compression_flag = 'j'
else:
compression_flag = ''
cmd = "tar x%sf %s" % (compression_flag, filename)
logger.debug(cmd)
subprocess.Popen(cmd, shell=True)
os.chdir(cwd)
def run_installer(filename):
"""Run an installer of .sh or .run type"""
subprocess.call(["chmod", "+x", filename])
@ -108,18 +76,24 @@ class ScriptInterpreter(object):
for field in required_fields:
if not self.script.get(field):
self.errors.append("Missing field '%s'" % field)
print self.errors
return not bool(self.errors)
#def parse_config(self):
# """ Reads the installer file. """
# self.game = self.rules['name']
# self.game_slug = os.path.basename(self.installer_path)[:-4]
@classmethod
def _map_command(cls, command_data):
if isinstance(command_data, dict):
command_name = command_data.keys()[0]
command_params = command_data[command_name]
else:
command_name = command_data
command_params = ""
command_name = command_name.replace("-", "_")
command_name = command_name.strip("_")
if not hasattr(cls, command_name):
raise ScriptingError("The command %s does not exists"
% command_name)
return getattr(cls, command_name), command_params
# self.actions = self.rules['installer']
# self.lutris_config = LutrisConfig(runner=self.game_info['runner'])
# return True
def substitute(self, path_ref, path_type):
def _substitute(self, path_ref, path_type):
if not path_ref.startswith("$%s" % path_type):
return
if path_type == "GAMEDIR":
@ -141,13 +115,13 @@ class ScriptInterpreter(object):
)
src_ref = params['src']
src = (self.files.get(src_ref)
or self.substitute(src_ref, 'CACHE')
or self.substitute(src_ref, 'GAMEDIR'))
or self._substitute(src_ref, 'CACHE')
or self._substitute(src_ref, 'GAMEDIR'))
if not src:
raise ScriptingError("Wrong value for 'src' param", src_ref)
dst_ref = params['dst']
dst = (self.substitute(dst_ref, 'GAMEDIR')
or self.substitute(dst_ref, 'HOME'))
dst = (self._substitute(dst_ref, 'GAMEDIR')
or self._substitute(dst_ref, 'HOME'))
if not dst:
raise ScriptingError("Wrong value for 'dst' param", dst_ref)
return (src, dst)
@ -167,6 +141,32 @@ class ScriptInterpreter(object):
return False
return True
def extract(self, data):
""" Extracts a file, guessing the compression method """
filename = self.files.get(data.get('file'))
if not filename:
logger.error("No file for '%s' in game files" % data)
return False
if not os.path.exists(filename):
logger.error("%s does not exists" % filename)
return False
msg = "Extracting %s" % filename
logger.debug(msg)
self.set_status(msg)
_, extension = os.path.splitext(filename)
if extension == ".zip":
extract.unzip(filename, self.game_dir)
elif filename.endswith('.tgz') or filename.endswith('.tar.gz'):
extract.untar(filename, None)
elif filename.endswith('.tar.bz2'):
extract.untar(filename, None, 'bzip2')
else:
logger.error("unrecognised file extension %s" % extension)
return False
def _delete(self, data):
print "Script has requested to delete %s" % data
# pylint: disable=R0904
class Installer(Gtk.Dialog):
@ -425,7 +425,6 @@ class Installer(Gtk.Dialog):
'insert-disc': self._insert_disc,
'extract': self._extract,
'move': self._move,
'request_media': self._request_media,
'run': self._run,
'runner': self._runner_task,
'check_md5': self._check_md5,
@ -527,43 +526,6 @@ class Installer(Gtk.Dialog):
print self.gamefiles
print data
def _insert_disc(self, _data):
print "Insert disc"
def _extract(self, data):
""" Extracts a file, guessing the compression method """
filename = self.gamefiles.get(data.get('file'))
if not filename:
logger.error("No file for '%s' in game files" % data)
return False
if not os.path.exists(filename):
logger.error("%s does not exists" % filename)
return False
msg = "Extracting %s" % filename
logger.debug(msg)
self.status_label.set_text(msg)
_, extension = os.path.splitext(filename)
if extension == ".zip":
unzip(filename, self.game_dir)
elif filename.endswith('.tgz') or filename.endswith('.tar.gz'):
untar(filename, None)
elif filename.endswith('.tar.bz2'):
untar(filename, None, 'bzip2')
else:
logger.error("unrecognised file extension %s" % extension)
return False
def _delete(self, data):
print "Script has requested to delete %s" % data
def _request_media(self, data):
"""Prompt user to insert a removable media"""
path = data.get('default', '')
if os.path.exists(os.path.join(path, data['contains'])):
return True
else:
return False
def _run(self, executable):
"""Run an executable script"""
exec_path = os.path.join(settings.CACHE_DIR, self.game_slug,

View file

@ -2,6 +2,7 @@ import os
import tarfile
import zipfile
import gzip
import subprocess
from lutris.util.log import logger
@ -42,3 +43,36 @@ def decompress_gz(file_path):
dest_file.close()
return dest_path
def unzip(filename, dest=None):
"""Unzips a file"""
command = ["unzip", '-o', filename]
if dest:
command = command + ['-d', dest]
subprocess.call(command)
def unrar(filename):
"""Unrar a file"""
subprocess.call(["unrar", "x", filename])
def untar(filename, dest=None, method='gzip'):
"""Untar a file"""
cwd = os.getcwd()
if dest is None or not os.path.exists(dest):
dest = cwd
logger.debug("Will extract to %s" % dest)
os.chdir(dest)
if method == 'gzip':
compression_flag = 'z'
elif method == 'bzip2':
compression_flag = 'j'
else:
compression_flag = ''
cmd = "tar x%sf %s" % (compression_flag, filename)
logger.debug(cmd)
subprocess.Popen(cmd, shell=True)
os.chdir(cwd)

View file

@ -17,3 +17,17 @@ class TestScriptInterpreter(TestCase):
interpreter = ScriptInterpreter("")
with self.assertRaises(ScriptingError):
interpreter._get_move_paths({})
def test_get_command_returns_a_method(self):
command, params = ScriptInterpreter._map_command({'move': 'whatever'})
self.assertIn("bound method ScriptInterpreter.move", str(command))
self.assertEqual(params, "whatever")
def test_get_command_doesnt_return_private_methods(self):
""" """
with self.assertRaises(ScriptingError) as ex:
command, params = ScriptInterpreter._map_command(
{'_substitute': 'foo'}
)
self.assertEqual(ex.exception.message,
"The command substitute does not exists")