setup profile earlier in startup, but defer warning message until qt init

This commit is contained in:
Damien Elmes 2019-12-19 09:38:36 +10:00
parent c61bc8859c
commit 5ce3de0e98
2 changed files with 35 additions and 15 deletions

View file

@ -303,6 +303,7 @@ def _run(argv=None, exec=True):
# profile manager # profile manager
from aqt.profiles import ProfileManager from aqt.profiles import ProfileManager
pm = ProfileManager(opts.base) pm = ProfileManager(opts.base)
pmLoadResult = pm.setupMeta()
# gl workarounds # gl workarounds
setupGL(pm) setupGL(pm)
@ -355,7 +356,11 @@ No usable temporary folder found. Make sure C:\\temp exists or TEMP in your \
environment points to a valid, writable folder.""") environment points to a valid, writable folder.""")
return return
pm.setupMeta() if pmLoadResult.loadError:
QMessageBox.warning(
None, "Preferences Corrupt", """\
Anki's prefs21.db file was corrupt and has been recreated. If you were using multiple \
profiles, please add them back using the same names to recover your cards.""")
if opts.profile: if opts.profile:
pm.openProfile(opts.profile) pm.openProfile(opts.profile)

View file

@ -61,6 +61,10 @@ profileConf: Dict[str,Any] = dict(
importMode=1, importMode=1,
) )
class LoadMetaResult:
firstTime: bool
loadError: bool
class ProfileManager: class ProfileManager:
def __init__(self, base=None): def __init__(self, base=None):
@ -71,9 +75,11 @@ class ProfileManager:
anki.sound.setMpvConfigBase(self.base) anki.sound.setMpvConfigBase(self.base)
def setupMeta(self): def setupMeta(self) -> LoadMetaResult:
# load metadata # load metadata
self.firstRun = self._loadMeta() res = self._loadMeta()
self.firstRun = res.firstTime
return res
# profile load on startup # profile load on startup
def openProfile(self, profile): def openProfile(self, profile):
@ -299,13 +305,17 @@ and no other programs are accessing your profile folders, then try again."""))
os.makedirs(dataDir) os.makedirs(dataDir)
return os.path.join(dataDir, "Anki2") return os.path.join(dataDir, "Anki2")
def _loadMeta(self): def _loadMeta(self, retrying = False) -> LoadMetaResult:
result = LoadMetaResult()
result.firstTime = False
result.loadError = retrying
opath = os.path.join(self.base, "prefs.db") opath = os.path.join(self.base, "prefs.db")
path = os.path.join(self.base, "prefs21.db") path = os.path.join(self.base, "prefs21.db")
if os.path.exists(opath) and not os.path.exists(path): if os.path.exists(opath) and not os.path.exists(path):
shutil.copy(opath, path) shutil.copy(opath, path)
new = not os.path.exists(path) result.firstTime = not os.path.exists(path)
def recover(): def recover():
# if we can't load profile, start with a new one # if we can't load profile, start with a new one
if self.db: if self.db:
@ -317,10 +327,8 @@ and no other programs are accessing your profile folders, then try again."""))
fpath = path + suffix fpath = path + suffix
if os.path.exists(fpath): if os.path.exists(fpath):
os.unlink(fpath) os.unlink(fpath)
QMessageBox.warning(
None, "Preferences Corrupt", """\ # open DB file and read data
Anki's prefs21.db file was corrupt and has been recreated. If you were using multiple \
profiles, please add them back using the same names to recover your cards.""")
try: try:
self.db = DB(path) self.db = DB(path)
assert self.db.scalar("pragma integrity_check") == "ok" assert self.db.scalar("pragma integrity_check") == "ok"
@ -330,21 +338,28 @@ create table if not exists profiles
data = self.db.scalar( data = self.db.scalar(
"select cast(data as blob) from profiles where name = '_global'") "select cast(data as blob) from profiles where name = '_global'")
except: except:
if result.loadError:
# already failed, prevent infinite loop
raise
# delete files and try again
recover() recover()
return self._loadMeta() return self._loadMeta(retrying=True)
if not new:
# load previously created data # try to read data
if not result.firstTime:
try: try:
self.meta = self._unpickle(data) self.meta = self._unpickle(data)
return return result
except: except:
print("resetting corrupt _global") print("resetting corrupt _global")
# create a default global profile result.loadError = True
# if new or read failed, create a default global profile
self.meta = metaConf.copy() self.meta = metaConf.copy()
self.db.execute("insert or replace into profiles values ('_global', ?)", self.db.execute("insert or replace into profiles values ('_global', ?)",
self._pickle(metaConf)) self._pickle(metaConf))
self._setDefaultLang() self._setDefaultLang()
return True return result
def _ensureProfile(self): def _ensureProfile(self):
"Create a new profile if none exists." "Create a new profile if none exists."