mirror of
https://github.com/lutris/lutris
synced 2024-09-30 04:54:18 +00:00
Do not move a game that can't be moved; abort before making any changes instead.
However, we handle the exception here and show a warning dialog about this. The user can choose to just set the location without moving or updating anything - they'll have to fix things up themselves. Should help with #5223
This commit is contained in:
parent
6f283f21a4
commit
bf169bc0ef
|
@ -95,6 +95,10 @@ class MissingGameExecutableError(MissingExecutableError):
|
|||
self.filename = filename
|
||||
|
||||
|
||||
class InvalidGameMoveError(LutrisError):
|
||||
"""Raised when a game can't be moved as desired; we may have to just set the location."""
|
||||
|
||||
|
||||
class EsyncLimitError(Exception):
|
||||
"""Raised when the ESYNC limit is not set correctly."""
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ from lutris.database import categories as categories_db
|
|||
from lutris.database import games as games_db
|
||||
from lutris.database import sql
|
||||
from lutris.exception_backstops import watch_game_errors
|
||||
from lutris.exceptions import GameConfigError, MissingExecutableError
|
||||
from lutris.exceptions import GameConfigError, InvalidGameMoveError, MissingExecutableError
|
||||
from lutris.runner_interpreter import export_bash_script, get_launch_parameters
|
||||
from lutris.runners import InvalidRunnerError, import_runner
|
||||
from lutris.runners.runner import Runner
|
||||
|
@ -960,16 +960,22 @@ class Game(GObject.Object):
|
|||
logger.info("Moving %s to %s", self, new_location)
|
||||
new_config = ""
|
||||
old_location = self.directory
|
||||
if os.path.exists(old_location):
|
||||
game_directory = os.path.basename(old_location)
|
||||
target_directory = os.path.join(new_location, game_directory)
|
||||
else:
|
||||
target_directory = new_location
|
||||
target_directory = self._get_move_target_directory(new_location)
|
||||
|
||||
# Raise errors before actually changing anything!
|
||||
if not old_location:
|
||||
raise InvalidGameMoveError(_("The game has no location currently set, so it can't be moved."))
|
||||
|
||||
if not system.path_exists(old_location):
|
||||
raise InvalidGameMoveError(
|
||||
_("The location '%s' does not exist, perhaps the files have already been moved?") % old_location)
|
||||
|
||||
if new_location.startswith(old_location):
|
||||
raise InvalidGameMoveError(
|
||||
_("Lutris can't move '%s' to a location inside of itself, '%s'.") % (old_location, new_location))
|
||||
|
||||
self.directory = target_directory
|
||||
self.save()
|
||||
if not old_location:
|
||||
logger.info("Previous location wasn't set. Cannot continue moving")
|
||||
return target_directory
|
||||
|
||||
with open(self.config.game_config_path, encoding='utf-8') as config_file:
|
||||
for line in config_file.readlines():
|
||||
|
@ -980,12 +986,6 @@ class Game(GObject.Object):
|
|||
with open(self.config.game_config_path, "w", encoding='utf-8') as config_file:
|
||||
config_file.write(new_config)
|
||||
|
||||
if not system.path_exists(old_location):
|
||||
logger.warning("Location %s doesn't exist, files already moved?", old_location)
|
||||
return target_directory
|
||||
if new_location.startswith(old_location):
|
||||
logger.warning("Can't move %s to one of its children %s", old_location, new_location)
|
||||
return target_directory
|
||||
try:
|
||||
shutil.move(old_location, new_location)
|
||||
except OSError as ex:
|
||||
|
@ -995,6 +995,20 @@ class Game(GObject.Object):
|
|||
)
|
||||
return target_directory
|
||||
|
||||
def set_location(self, new_location):
|
||||
target_directory = self._get_move_target_directory(new_location)
|
||||
self.directory = target_directory
|
||||
self.save()
|
||||
return target_directory
|
||||
|
||||
def _get_move_target_directory(self, new_location):
|
||||
old_location = self.directory
|
||||
if old_location and os.path.exists(old_location):
|
||||
game_directory = os.path.basename(old_location)
|
||||
return os.path.join(new_location, game_directory)
|
||||
|
||||
return new_location
|
||||
|
||||
|
||||
def export_game(slug, dest_dir):
|
||||
"""Export a full game folder along with some lutris metadata"""
|
||||
|
|
|
@ -11,6 +11,7 @@ gi.require_version('Gtk', '3.0')
|
|||
from gi.repository import Gdk, GLib, GObject, Gtk
|
||||
|
||||
from lutris import api, settings
|
||||
from lutris.exceptions import InvalidGameMoveError
|
||||
from lutris.gui.widgets.log_text_view import LogTextView
|
||||
from lutris.util import datapath
|
||||
from lutris.util.jobs import AsyncCall
|
||||
|
@ -522,19 +523,6 @@ class InstallerSourceDialog(ModelessDialog):
|
|||
self.show_all()
|
||||
|
||||
|
||||
class WarningMessageDialog(Gtk.MessageDialog):
|
||||
def __init__(self, message, secondary_message="", parent=None):
|
||||
super().__init__(type=Gtk.MessageType.WARNING, buttons=Gtk.ButtonsType.OK, parent=parent)
|
||||
|
||||
self.set_default_response(Gtk.ResponseType.OK)
|
||||
self.set_markup("<b>%s</b>" % message)
|
||||
if secondary_message:
|
||||
self.props.secondary_use_markup = True
|
||||
self.props.secondary_text = secondary_message
|
||||
self.run()
|
||||
self.destroy()
|
||||
|
||||
|
||||
class MoveDialog(ModelessDialog):
|
||||
__gsignals__ = {
|
||||
"game-moved": (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||
|
@ -564,7 +552,7 @@ class MoveDialog(ModelessDialog):
|
|||
GLib.source_remove(self.progress_source_id)
|
||||
|
||||
def move(self):
|
||||
AsyncCall(self._move_game, self.on_game_moved)
|
||||
AsyncCall(self._move_game, self._move_game_cb)
|
||||
|
||||
def show_progress(self):
|
||||
self.progress.pulse()
|
||||
|
@ -573,6 +561,20 @@ class MoveDialog(ModelessDialog):
|
|||
def _move_game(self):
|
||||
self.new_directory = self.game.move(self.destination)
|
||||
|
||||
def _move_game_cb(self, _result, error):
|
||||
if error and isinstance(error, InvalidGameMoveError):
|
||||
secondary = _("Do you want to change the game location anyway? No files can be moved, "
|
||||
"and the game configuration may need to be adjusted.")
|
||||
dlg = WarningDialog(str(error), secondary=secondary, parent=self)
|
||||
if dlg.result == Gtk.ResponseType.OK:
|
||||
self.new_directory = self.game.set_location(self.destination)
|
||||
self.on_game_moved(None, None)
|
||||
else:
|
||||
self.destroy()
|
||||
return
|
||||
|
||||
self.on_game_moved(_result, error)
|
||||
|
||||
def on_game_moved(self, _result, error):
|
||||
if error:
|
||||
ErrorDialog(error, parent=self)
|
||||
|
|
Loading…
Reference in a new issue