Skip to content

Commit b190867

Browse files
InfernioSharlikran
authored andcommitted
Gracefully handle reverting to corrupt files
Offer the user an option to abort the revert procedure, restoring the original file again. Randomly stumbled across this due to the FIXME (at least I'm assuming this is what the FIXME referred to?) for snapshots, but this also implements it for backups. Note that I'm keeping the temp backup around - gets cleaned up at exit anyways, and it may give computer-savvy users an out if they accidentally click 'No' on the new popup. Also no longer swallows the traceback for the FileError, deprinting it to the BugDump instead so that one can actually figure out why the reverting failed.
1 parent a0c3b43 commit b190867

1 file changed

Lines changed: 43 additions & 14 deletions

File tree

Mopy/bash/basher/files_links.py

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,11 @@ def Execute(self):
219219
#--Copy file
220220
self.window.data_store.copy_info(fileName, destDir, destName)
221221

222-
class File_RevertToSnapshot(OneItemLink): # MODS LINK !
222+
class File_RevertToSnapshot(OneItemLink):
223223
"""Revert to Snapshot."""
224224
_text = _(u'Revert to Snapshot...')
225-
_help = _(u"Revert to a previously created snapshot from the Bash/Snapshots dir.")
225+
_help = _(u'Revert to a previously created snapshot from the '
226+
u'Bash/Snapshots dir.')
226227

227228
@balt.conversation
228229
def Execute(self):
@@ -239,20 +240,32 @@ def Execute(self):
239240
if not snapPath: return
240241
snapName = snapPath.tail
241242
#--Warning box
242-
message = (_(u"Revert %s to snapshot %s dated %s?") % (
243+
message = (_(u'Revert %s to snapshot %s dated %s?') % (
243244
fileName.s, snapName.s, format_date(snapPath.mtime)))
244245
if not self._askYes(message, _(u'Revert to Snapshot')): return
245246
with balt.BusyCursor():
246-
destPath = self._selected_info.getPath()
247+
destPath = self._selected_info.abs_path
247248
current_mtime = destPath.mtime
249+
# Make a temp backup first in case reverting to snapshot fails
250+
destPath.copyTo(destPath.temp)
248251
snapPath.copyTo(destPath)
249252
# keep load order but recalculate the crc
250253
self._selected_info.setmtime(current_mtime, crc_changed=True)
251254
try:
252255
self.window.data_store.new_info(fileName, notify_bain=True)
253-
except exception.FileError: # FIXME(ut) - we just lost the correct file
254-
balt.showError(self,_(u'Snapshot file is corrupt!'))
256+
except exception.FileError:
257+
# Reverting to snapshot failed - may be corrupt
258+
bolt.deprint(u'Failed to revert to snapshot', traceback=True)
255259
self.window.panel.ClearDetails()
260+
if self._askYes(
261+
_(u'Failed to revert %s to snapshot %s. The snapshot file '
262+
u'may be corrupt. Do you want to restore the original '
263+
u"file again? 'No' keeps the reverted, possibly broken "
264+
u'snapshot instead.') % (fileName.s, snapName.s),
265+
title=_(u'Revert to Snapshot - Error')):
266+
# Restore the known good file again - no error check needed
267+
destPath.untemp()
268+
self.window.data_store.new_info(fileName, notify_bain=True)
256269
# don't refresh saves as neither selection state nor load order change
257270
self.window.RefreshUI(redraw=[fileName], refreshSaves=False)
258271

@@ -277,8 +290,8 @@ def _initData(self, window, selection):
277290
super(_RevertBackup, self)._initData(window, selection)
278291
self.backup_path = self._selected_info.backup_dir.join(
279292
self._selected_item) + (u'f' if self.first else u'')
280-
self._help = _(u"Revert %(file)s to its first backup") if self.first \
281-
else _(u"Revert %(file)s to its last backup")
293+
self._help = _(u'Revert %(file)s to its first backup') if self.first \
294+
else _(u'Revert %(file)s to its last backup')
282295
self._help %= {'file': self._selected_item}
283296

284297
def _enable(self):
@@ -288,17 +301,33 @@ def _enable(self):
288301
@balt.conversation
289302
def Execute(self):
290303
#--Warning box
291-
message = _(u"Revert %s to backup dated %s?") % (
292-
self._selected_item.s, format_date(self.backup_path.mtime))
304+
sel_file = self._selected_item
305+
backup_date = format_date(self.backup_path.mtime)
306+
message = _(u'Revert %s to backup dated %s?') % (sel_file.s,
307+
backup_date)
293308
if not self._askYes(message): return
294309
with balt.BusyCursor():
310+
# Make a temp backup first in case reverting to backup fails
311+
info_path = self._selected_info.abs_path
312+
info_path.copyTo(info_path.temp)
295313
try:
296314
self._selected_info.revert_backup(self.first)
297-
self.window.RefreshUI(redraw=[self._selected_item],
298-
refreshSaves=False)
299315
except exception.FileError:
300-
self._showError(_(u'Old file is corrupt!'))
301-
self.window.RefreshUI(refreshSaves=True)
316+
# Reverting to backup failed - may be corrupt
317+
bolt.deprint(u'Failed to revert to backup', traceback=True)
318+
self.window.panel.ClearDetails()
319+
if self._askYes(
320+
_(u'Failed to revert %s to backup dated %s. The backup '
321+
u'file may be corrupt. Do you want to restore the '
322+
u"original file again? 'No' keeps the reverted, "
323+
u'possibly broken backup instead.') % (sel_file.s,
324+
backup_date),
325+
title=_(u'Revert to Backup - Error')):
326+
# Restore the known good file again - no error check needed
327+
info_path.untemp()
328+
self.window.data_store.new_info(sel_file, notify_bain=True)
329+
# don't refresh saves as neither selection state nor load order change
330+
self.window.RefreshUI(redraw=[sel_file], refreshSaves=False)
302331

303332
class File_RevertToBackup(ChoiceLink):
304333
"""Revert to last or first backup."""

0 commit comments

Comments
 (0)