Create RuntimeUpdater class

This commit is contained in:
Mathieu Comandon 2016-09-02 18:31:24 -07:00
parent 17962d9832
commit 9c95bfc853
3 changed files with 93 additions and 97 deletions

View file

@ -42,7 +42,8 @@ if LAUNCH_PATH != "/usr/bin":
from lutris.migrations import migrate
from lutris import pga, runtime
from lutris import pga
from lutris.runtime import RuntimeUpdater
from lutris.config import check_config # , register_handler
from lutris.util.log import logger
from lutris.game import Game
@ -182,12 +183,14 @@ if game_slug or installer:
or pga.get_game_by_field(game_slug, 'slug')
or pga.get_game_by_field(game_slug, 'installer_slug'))
runtime_updater = RuntimeUpdater()
if db_game and db_game['installed'] and not options.reinstall:
logger.info("Launching %s", db_game['name'])
if lutris.is_running():
lutris.run_game(db_game['id'])
else:
runtime.update()
runtime_updater.update()
lutris_game = Game(db_game['id'])
lutris_game.exit_main_loop = True
lutris_game.play()
@ -200,7 +203,7 @@ if game_slug or installer:
if lutris.is_running():
lutris.install_game(installer or game_slug)
else:
runtime.update()
runtime_updater.update()
InstallerDialog(installer or game_slug)
GObject.threads_init()
Gtk.main()

View file

@ -6,9 +6,10 @@ import subprocess
from gi.repository import Gtk, Gdk, GLib, Gio
from lutris import api, pga, runtime, settings, shortcuts
from lutris import api, pga, settings, shortcuts
from lutris.game import Game, get_game_list
from lutris.sync import Sync
from lutris.runtime import RuntimeUpdater
from lutris.util import display, resources
from lutris.util.log import logger
@ -54,6 +55,7 @@ class LutrisWindow(Gtk.Application):
raise IOError('File %s not found' % ui_filename)
self.service = service
self.runtime_updater = RuntimeUpdater()
self.running_game = None
self.threads_stoppers = []
@ -345,7 +347,8 @@ class LutrisWindow(Gtk.Application):
self.set_status("")
def update_runtime(self):
cancellables = runtime.update(self.set_status)
cancellables = self.runtime_updater.update(self.set_status)
self.threads_stoppers += cancellables
def sync_icons(self, stop_request=None):

View file

@ -8,104 +8,94 @@ from lutris.util import http, jobs, system
from lutris.util.extract import extract_archive
from lutris.util.log import logger
CURRENT_UPDATES = None
STATUS_UPDATER = None
class RuntimeUpdater:
current_updates = None
status_updater = None
def is_updating(include_pending_updates=True):
if include_pending_updates and CURRENT_UPDATES is None:
def is_updating(self, include_pending_updates=True):
if include_pending_updates and self.current_updates is None:
return True
if self.current_updates:
return self.current_updates > 0
return False
def get_created_at(self, name):
path = os.path.join(RUNTIME_DIR, name)
if not os.path.exists(path):
return time.gmtime(0)
return time.gmtime(os.path.getctime(path))
def update(self, status_updater=None):
if self.is_updating(False):
logger.debug("Runtime already updating")
return []
if status_updater:
self.status_updater = status_updater
return self.get_runtimes()
def get_runtimes(self):
if self.current_updates is None:
self.current_updates = 0
request = http.Request(RUNTIME_URL)
response = request.get()
cancellables = []
runtimes = response.json or []
for runtime in runtimes:
name = runtime['name']
if '64' in name and not system.is_64bit:
continue
created_at = runtime['created_at']
created_at = time.strptime(created_at[:created_at.find('.')],
"%Y-%m-%dT%H:%M:%S")
if self.get_created_at(name) < created_at:
if self.status_updater:
self.status_updater("Updating Runtime")
logger.debug('Updating runtime %s', name)
url = runtime['url']
archive_path = os.path.join(RUNTIME_DIR, os.path.basename(url))
self.current_updates += 1
downloader = Downloader(url, archive_path, overwrite=True)
cancellables.append(downloader.cancel)
downloader.start()
GLib.timeout_add(100, self.check_download_progress, downloader)
else:
logger.debug("Runtime %s up to date", name)
return cancellables
def check_download_progress(self, downloader):
"""Call download.check_progress(), return True if download finished."""
if (not downloader or downloader.state in [downloader.CANCELLED,
downloader.ERROR]):
logger.debug("Runtime update interrupted")
return False
downloader.check_progress()
if downloader.state == downloader.COMPLETED:
self.on_downloaded(downloader.dest)
return False
return True
if CURRENT_UPDATES:
return CURRENT_UPDATES > 0
return False
def on_downloaded(self, path):
dir, filename = os.path.split(path)
folder = os.path.join(dir, filename[:filename.find('.')])
system.remove_folder(folder)
jobs.AsyncCall(extract_archive, self.on_extracted, path, RUNTIME_DIR,
merge_single=False)
def get_created_at(name):
path = os.path.join(RUNTIME_DIR, name)
if not os.path.exists(path):
return time.gmtime(0)
return time.gmtime(os.path.getctime(path))
def on_extracted(self, result, error):
self.current_updates -= 1
if error:
logger.debug("Runtime update failed")
return
archive_path = result[0]
os.unlink(archive_path)
def update(status_updater=None):
global STATUS_UPDATER
if is_updating(False):
logger.debug("Runtime already updating")
return []
if status_updater:
STATUS_UPDATER = status_updater
return get_runtimes()
def get_runtimes():
global CURRENT_UPDATES
global STATUS_UPDATER
if CURRENT_UPDATES is None:
CURRENT_UPDATES = 0
request = http.Request(RUNTIME_URL)
response = request.get()
cancellables = []
runtimes = response.json or []
for runtime in runtimes:
name = runtime['name']
if '64' in name and not system.is_64bit:
continue
created_at = runtime['created_at']
created_at = time.strptime(created_at[:created_at.find('.')],
"%Y-%m-%dT%H:%M:%S")
if get_created_at(name) < created_at:
if STATUS_UPDATER:
STATUS_UPDATER("Updating Runtime")
logger.debug('Updating runtime %s', name)
url = runtime['url']
archive_path = os.path.join(RUNTIME_DIR, os.path.basename(url))
CURRENT_UPDATES += 1
downloader = Downloader(url, archive_path, overwrite=True)
cancellables.append(downloader.cancel)
downloader.start()
GLib.timeout_add(100, check_download_progress, downloader)
else:
logger.debug("Runtime %s up to date", name)
return cancellables
def check_download_progress(downloader):
"""Call download.check_progress(), return True if download finished."""
if (not downloader or downloader.state in [downloader.CANCELLED,
downloader.ERROR]):
logger.debug("Runtime update interrupted")
return False
downloader.check_progress()
if downloader.state == downloader.COMPLETED:
on_downloaded(downloader.dest)
return False
return True
def on_downloaded(path):
dir, filename = os.path.split(path)
folder = os.path.join(dir, filename[:filename.find('.')])
system.remove_folder(folder)
jobs.AsyncCall(extract_archive, on_extracted, path, RUNTIME_DIR,
merge_single=False)
def on_extracted(result, error):
global CURRENT_UPDATES
global STATUS_UPDATER
CURRENT_UPDATES -= 1
if error:
logger.debug("Runtime update failed")
return
archive_path = result[0]
os.unlink(archive_path)
if STATUS_UPDATER and CURRENT_UPDATES == 0:
STATUS_UPDATER("Runtime updated")
logger.debug("Runtime updated")
if self.status_updater and self.current_updates == 0:
self.status_updater("Runtime updated")
logger.debug("Runtime updated")
def get_env():