Package horizons :: Package util :: Module savegameupgrader
[hide private]
[frames] | no frames]

Source Code for Module horizons.util.savegameupgrader

  1  # ################################################### 
  2  # Copyright (C) 2008-2017 The Unknown Horizons Team 
  3  # team@unknown-horizons.org 
  4  # This file is part of Unknown Horizons. 
  5  # 
  6  # Unknown Horizons is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the 
 18  # Free Software Foundation, Inc., 
 19  # 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 20  # ################################################### 
 21   
 22  import json 
 23  import logging 
 24  import os 
 25  import os.path 
 26  import shutil 
 27  import tempfile 
 28  from collections import defaultdict 
 29  from sqlite3 import OperationalError 
 30  from typing import Any, DefaultDict, List, Optional, Tuple 
 31   
 32  from yaml.parser import ParserError 
 33   
 34  from horizons.constants import BUILDINGS, UNITS, VERSION 
 35  from horizons.entities import Entities 
 36  from horizons.util.dbreader import DbReader 
 37  from horizons.util.shapes import Rect 
 38  from horizons.util.yamlcache import YamlCache 
39 40 41 -class SavegameTooOld(Exception):
42 - def __init__(self, msg=None, revision=None):
43 if msg is None: 44 msg = "The savegame is too old!" 45 if revision is not None: 46 msg += " Revision: " + str(revision) 47 super().__init__(msg)
48
49 50 -class SavegameUpgrader:
51 """The class that prepares saved games to be loaded by the current version.""" 52 53 log = logging.getLogger("util.savegameupgrader") 54
55 - def __init__(self, path):
56 super().__init__() # TODO: check if this call is needed 57 self.original_path = path 58 self.using_temp = False 59 self.final_path = None # type: Optional[str]
60
61 - def _upgrade_to_rev77(self, db):
62 #placeholder for future upgrade methods 63 pass
64
65 - def _upgrade(self):
66 # fix import loop 67 from horizons.savegamemanager import SavegameManager 68 metadata = SavegameManager.get_metadata(self.original_path) 69 rev = metadata['savegamerev'] 70 71 if rev < VERSION.SAVEGAMEREVISION: 72 if not SavegameUpgrader.can_upgrade(rev): 73 raise SavegameTooOld(revision=rev) 74 75 self.log.warning('Discovered old savegame file, auto-upgrading: {} -> {}' 76 .format(rev, VERSION.SAVEGAMEREVISION)) 77 db = DbReader(self.final_path) 78 db('BEGIN TRANSACTION') 79 80 # placeholder for future upgrade calls 81 if rev < 77: 82 self._upgrade_to_rev77(db) 83 84 db('COMMIT') 85 db.close()
86 87 @classmethod
88 - def can_upgrade(cls, from_savegame_version):
89 """Checks whether a savegame can be upgraded from the current version""" 90 if from_savegame_version >= VERSION.SAVEGAME_LEAST_UPGRADABLE_REVISION: 91 return True 92 else: 93 return False
94
95 - def get_path(self):
96 """Return the path to the up-to-date version of the saved game.""" 97 if self.final_path is None: 98 self.using_temp = True 99 handle, self.final_path = tempfile.mkstemp(prefix='uh-savegame.' + os.path.basename(os.path.splitext(self.original_path)[0]) + '.', suffix='.sqlite') 100 os.close(handle) 101 shutil.copyfile(self.original_path, self.final_path) 102 self._upgrade() 103 return self.final_path
104
105 - def close(self):
106 if self.using_temp: 107 self.using_temp = False 108 os.unlink(self.final_path) 109 self.final_path = None
110