mirror of
https://github.com/ankitects/anki.git
synced 2025-11-09 14:17:13 -05:00
move upgrade code into separate file
This commit is contained in:
parent
4302306fe9
commit
72a1cd73a9
2 changed files with 249 additions and 257 deletions
263
anki/deck.py
263
anki/deck.py
|
|
@ -28,6 +28,7 @@ from anki.hooks import runHook, hookEmpty
|
||||||
from anki.template import render
|
from anki.template import render
|
||||||
from anki.media import updateMediaCount, mediaFiles, \
|
from anki.media import updateMediaCount, mediaFiles, \
|
||||||
rebuildMediaDir
|
rebuildMediaDir
|
||||||
|
from anki.upgrade import upgradeSchema, updateIndices, upgradeDeck
|
||||||
import anki.latex # sets up hook
|
import anki.latex # sets up hook
|
||||||
|
|
||||||
# ensure all the DB metadata in other files is loaded before proceeding
|
# ensure all the DB metadata in other files is loaded before proceeding
|
||||||
|
|
@ -3155,7 +3156,7 @@ where id = :id""", fid=f.id, cmid=m.cardModels[0].id, id=id)
|
||||||
"Please restore from automatic backup (see FAQ).")
|
"Please restore from automatic backup (see FAQ).")
|
||||||
# ensure correct views and indexes are available
|
# ensure correct views and indexes are available
|
||||||
self.updateProgress()
|
self.updateProgress()
|
||||||
DeckStorage._addIndices(self)
|
updateIndices(self)
|
||||||
# does the user have a model?
|
# does the user have a model?
|
||||||
self.updateProgress()
|
self.updateProgress()
|
||||||
if not self.s.scalar("select count(id) from models"):
|
if not self.s.scalar("select count(id) from models"):
|
||||||
|
|
@ -3556,15 +3557,7 @@ class DeckStorage(object):
|
||||||
metadata.create_all(engine)
|
metadata.create_all(engine)
|
||||||
deck = DeckStorage._init(s)
|
deck = DeckStorage._init(s)
|
||||||
else:
|
else:
|
||||||
ver = s.scalar("select version from decks limit 1")
|
ver = upgradeSchema(s)
|
||||||
# add a checksum to fields
|
|
||||||
if ver < 71:
|
|
||||||
try:
|
|
||||||
s.execute(
|
|
||||||
"alter table fields add column chksum text "+
|
|
||||||
"not null default ''")
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
# add any possibly new tables if we're upgrading
|
# add any possibly new tables if we're upgrading
|
||||||
if ver < DECK_VERSION:
|
if ver < DECK_VERSION:
|
||||||
metadata.create_all(engine)
|
metadata.create_all(engine)
|
||||||
|
|
@ -3589,10 +3582,7 @@ class DeckStorage(object):
|
||||||
deck.s = SessionHelper(s, lock=lock)
|
deck.s = SessionHelper(s, lock=lock)
|
||||||
# force a write lock
|
# force a write lock
|
||||||
deck.s.execute("update decks set modified = modified")
|
deck.s.execute("update decks set modified = modified")
|
||||||
needUnpack = False
|
if deck.utcOffset == -2:
|
||||||
if deck.utcOffset in (-1, -2):
|
|
||||||
# do the rest later
|
|
||||||
needUnpack = deck.utcOffset == -1
|
|
||||||
# make sure we do this before initVars
|
# make sure we do this before initVars
|
||||||
DeckStorage._setUTCOffset(deck)
|
DeckStorage._setUTCOffset(deck)
|
||||||
deck.created = time.time()
|
deck.created = time.time()
|
||||||
|
|
@ -3606,19 +3596,14 @@ class DeckStorage(object):
|
||||||
deck.s.execute("vacuum")
|
deck.s.execute("vacuum")
|
||||||
# add tags and indices
|
# add tags and indices
|
||||||
initTagTables(deck.s)
|
initTagTables(deck.s)
|
||||||
DeckStorage._addIndices(deck)
|
updateIndices(deck)
|
||||||
deck.s.statement("analyze")
|
deck.s.statement("analyze")
|
||||||
deck._initVars()
|
deck._initVars()
|
||||||
else:
|
else:
|
||||||
if backup:
|
if backup:
|
||||||
DeckStorage.backup(deck, path)
|
DeckStorage.backup(deck, path)
|
||||||
deck._initVars()
|
deck._initVars()
|
||||||
try:
|
upgradeDeck(deck)
|
||||||
deck = DeckStorage._upgradeDeck(deck, path)
|
|
||||||
except:
|
|
||||||
traceback.print_exc()
|
|
||||||
deck.fixIntegrity()
|
|
||||||
deck = DeckStorage._upgradeDeck(deck, path)
|
|
||||||
except OperationalError, e:
|
except OperationalError, e:
|
||||||
engine.dispose()
|
engine.dispose()
|
||||||
if (str(e.orig).startswith("database table is locked") or
|
if (str(e.orig).startswith("database table is locked") or
|
||||||
|
|
@ -3632,12 +3617,6 @@ class DeckStorage(object):
|
||||||
deck._globalStats = globalStats(deck)
|
deck._globalStats = globalStats(deck)
|
||||||
deck._dailyStats = dailyStats(deck)
|
deck._dailyStats = dailyStats(deck)
|
||||||
return deck
|
return deck
|
||||||
if needUnpack:
|
|
||||||
deck.startProgress()
|
|
||||||
DeckStorage._addIndices(deck)
|
|
||||||
for m in deck.models:
|
|
||||||
deck.updateCardsFromModel(m)
|
|
||||||
deck.finishProgress()
|
|
||||||
oldMod = deck.modified
|
oldMod = deck.modified
|
||||||
# fix a bug with current model being unset
|
# fix a bug with current model being unset
|
||||||
if not deck.currentModel and deck.models:
|
if not deck.currentModel and deck.models:
|
||||||
|
|
@ -3700,236 +3679,6 @@ class DeckStorage(object):
|
||||||
return deck
|
return deck
|
||||||
_init = staticmethod(_init)
|
_init = staticmethod(_init)
|
||||||
|
|
||||||
def _addIndices(deck):
|
|
||||||
"Add indices to the DB."
|
|
||||||
# counts, failed cards
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_cards_typeCombined on cards
|
|
||||||
(type, combinedDue, factId)""")
|
|
||||||
# scheduler-agnostic type
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_cards_relativeDelay on cards
|
|
||||||
(relativeDelay)""")
|
|
||||||
# index on modified, to speed up sync summaries
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_cards_modified on cards
|
|
||||||
(modified)""")
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_facts_modified on facts
|
|
||||||
(modified)""")
|
|
||||||
# priority - temporary index to make compat code faster. this can be
|
|
||||||
# removed when all clients are on 1.2, as can the ones below
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_cards_priority on cards
|
|
||||||
(priority)""")
|
|
||||||
# average factor
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_cards_factor on cards
|
|
||||||
(type, factor)""")
|
|
||||||
# card spacing
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_cards_factId on cards (factId)""")
|
|
||||||
# stats
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_stats_typeDay on stats (type, day)""")
|
|
||||||
# fields
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_fields_factId on fields (factId)""")
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_fields_fieldModelId on fields (fieldModelId)""")
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_fields_chksum on fields (chksum)""")
|
|
||||||
# media
|
|
||||||
deck.s.statement("""
|
|
||||||
create unique index if not exists ix_media_filename on media (filename)""")
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_media_originalPath on media (originalPath)""")
|
|
||||||
# deletion tracking
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_cardsDeleted_cardId on cardsDeleted (cardId)""")
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_modelsDeleted_modelId on modelsDeleted (modelId)""")
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_factsDeleted_factId on factsDeleted (factId)""")
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_mediaDeleted_factId on mediaDeleted (mediaId)""")
|
|
||||||
# tags
|
|
||||||
txt = "create unique index if not exists ix_tags_tag on tags (tag)"
|
|
||||||
try:
|
|
||||||
deck.s.statement(txt)
|
|
||||||
except:
|
|
||||||
deck.s.statement("""
|
|
||||||
delete from tags where exists (select 1 from tags t2 where tags.tag = t2.tag
|
|
||||||
and tags.rowid > t2.rowid)""")
|
|
||||||
deck.s.statement(txt)
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_cardTags_tagCard on cardTags (tagId, cardId)""")
|
|
||||||
deck.s.statement("""
|
|
||||||
create index if not exists ix_cardTags_cardId on cardTags (cardId)""")
|
|
||||||
_addIndices = staticmethod(_addIndices)
|
|
||||||
|
|
||||||
def _upgradeDeck(deck, path):
|
|
||||||
"Upgrade deck to the latest version."
|
|
||||||
if deck.version < DECK_VERSION:
|
|
||||||
prog = True
|
|
||||||
deck.startProgress()
|
|
||||||
deck.updateProgress(_("Upgrading Deck..."))
|
|
||||||
if deck.utcOffset == -1:
|
|
||||||
# we're opening a shared deck with no indices - we'll need
|
|
||||||
# them if we want to rebuild the queue
|
|
||||||
DeckStorage._addIndices(deck)
|
|
||||||
oldmod = deck.modified
|
|
||||||
else:
|
|
||||||
prog = False
|
|
||||||
deck.path = path
|
|
||||||
if deck.version < 43:
|
|
||||||
raise Exception("oldDeckVersion")
|
|
||||||
if deck.version < 44:
|
|
||||||
# leaner indices
|
|
||||||
deck.s.statement("drop index if exists ix_cards_factId")
|
|
||||||
deck.version = 44
|
|
||||||
deck.s.commit()
|
|
||||||
if deck.version < 48:
|
|
||||||
deck.updateFieldCache(deck.s.column0("select id from facts"))
|
|
||||||
deck.version = 48
|
|
||||||
deck.s.commit()
|
|
||||||
if deck.version < 52:
|
|
||||||
dname = deck.name()
|
|
||||||
sname = deck.syncName
|
|
||||||
if sname and dname != sname:
|
|
||||||
deck.notify(_("""\
|
|
||||||
When syncing, Anki now uses the same deck name on the server as the deck \
|
|
||||||
name on your computer. Because you had '%(dname)s' set to sync to \
|
|
||||||
'%(sname)s' on the server, syncing has been temporarily disabled.
|
|
||||||
|
|
||||||
If you want to keep your changes to the online version, please use \
|
|
||||||
File>Download>Personal Deck to download the online version.
|
|
||||||
|
|
||||||
If you want to keep the version on your computer, please enable \
|
|
||||||
syncing again via Settings>Deck Properties>Synchronisation.
|
|
||||||
|
|
||||||
If you have syncing disabled in the preferences, you can ignore \
|
|
||||||
this message. (ERR-0101)""") % {
|
|
||||||
'sname':sname, 'dname':dname})
|
|
||||||
deck.disableSyncing()
|
|
||||||
elif sname:
|
|
||||||
deck.enableSyncing()
|
|
||||||
deck.version = 52
|
|
||||||
deck.s.commit()
|
|
||||||
if deck.version < 53:
|
|
||||||
if deck.getBool("perDay"):
|
|
||||||
if deck.hardIntervalMin == 0.333:
|
|
||||||
deck.hardIntervalMin = max(1.0, deck.hardIntervalMin)
|
|
||||||
deck.hardIntervalMax = max(1.1, deck.hardIntervalMax)
|
|
||||||
deck.version = 53
|
|
||||||
deck.s.commit()
|
|
||||||
if deck.version < 54:
|
|
||||||
# broken versions of the DB orm die if this is a bool with a
|
|
||||||
# non-int value
|
|
||||||
deck.s.statement("update fieldModels set editFontFamily = 1");
|
|
||||||
deck.version = 54
|
|
||||||
deck.s.commit()
|
|
||||||
if deck.version < 61:
|
|
||||||
# do our best to upgrade templates to the new style
|
|
||||||
txt = '''\
|
|
||||||
<span style="font-family: %s; font-size: %spx; color: %s; white-space: pre-wrap;">%s</span>'''
|
|
||||||
for m in deck.models:
|
|
||||||
unstyled = []
|
|
||||||
for fm in m.fieldModels:
|
|
||||||
# find which fields had explicit formatting
|
|
||||||
if fm.quizFontFamily or fm.quizFontSize or fm.quizFontColour:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
unstyled.append(fm.name)
|
|
||||||
# fill out missing info
|
|
||||||
fm.quizFontFamily = fm.quizFontFamily or u"Arial"
|
|
||||||
fm.quizFontSize = fm.quizFontSize or 20
|
|
||||||
fm.quizFontColour = fm.quizFontColour or "#000000"
|
|
||||||
fm.editFontSize = fm.editFontSize or 20
|
|
||||||
unstyled = set(unstyled)
|
|
||||||
for cm in m.cardModels:
|
|
||||||
# embed the old font information into card templates
|
|
||||||
cm.qformat = txt % (
|
|
||||||
cm.questionFontFamily,
|
|
||||||
cm.questionFontSize,
|
|
||||||
cm.questionFontColour,
|
|
||||||
cm.qformat)
|
|
||||||
cm.aformat = txt % (
|
|
||||||
cm.answerFontFamily,
|
|
||||||
cm.answerFontSize,
|
|
||||||
cm.answerFontColour,
|
|
||||||
cm.aformat)
|
|
||||||
# escape fields that had no previous styling
|
|
||||||
for un in unstyled:
|
|
||||||
cm.qformat = cm.qformat.replace("%("+un+")s", "{{{%s}}}"%un)
|
|
||||||
cm.aformat = cm.aformat.replace("%("+un+")s", "{{{%s}}}"%un)
|
|
||||||
# rebuild q/a for the above & because latex has changed
|
|
||||||
for m in deck.models:
|
|
||||||
deck.updateCardsFromModel(m, dirty=False)
|
|
||||||
# rebuild the media db based on new format
|
|
||||||
rebuildMediaDir(deck, dirty=False)
|
|
||||||
deck.version = 61
|
|
||||||
deck.s.commit()
|
|
||||||
if deck.version < 62:
|
|
||||||
# updated indices
|
|
||||||
deck.s.statement("drop index if exists ix_cards_typeCombined")
|
|
||||||
DeckStorage._addIndices(deck)
|
|
||||||
deck.version = 62
|
|
||||||
deck.s.commit()
|
|
||||||
if deck.version < 64:
|
|
||||||
# remove old static indices, as all clients should be libanki1.2+
|
|
||||||
for d in ("ix_cards_duePriority",
|
|
||||||
"ix_cards_priorityDue"):
|
|
||||||
deck.s.statement("drop index if exists %s" % d)
|
|
||||||
deck.version = 64
|
|
||||||
deck.s.commit()
|
|
||||||
# note: we keep the priority index for now
|
|
||||||
if deck.version < 65:
|
|
||||||
# we weren't correctly setting relativeDelay when answering cards
|
|
||||||
# in previous versions, so ensure everything is set correctly
|
|
||||||
deck.rebuildTypes()
|
|
||||||
deck.version = 65
|
|
||||||
deck.s.commit()
|
|
||||||
# skip a few to allow for updates to stable tree
|
|
||||||
if deck.version < 70:
|
|
||||||
# update dynamic indices given we don't use priority anymore
|
|
||||||
for d in ("intervalDesc", "intervalAsc", "randomOrder",
|
|
||||||
"dueAsc", "dueDesc"):
|
|
||||||
deck.s.statement("drop index if exists ix_cards_%s2" % d)
|
|
||||||
deck.s.statement("drop index if exists ix_cards_%s" % d)
|
|
||||||
deck.updateDynamicIndices()
|
|
||||||
# remove old views
|
|
||||||
for v in ("failedCards", "revCardsOld", "revCardsNew",
|
|
||||||
"revCardsDue", "revCardsRandom", "acqCardsRandom",
|
|
||||||
"acqCardsOld", "acqCardsNew"):
|
|
||||||
deck.s.statement("drop view if exists %s" % v)
|
|
||||||
deck.version = 70
|
|
||||||
deck.s.commit()
|
|
||||||
if deck.version < 71:
|
|
||||||
# remove the expensive value cache
|
|
||||||
deck.s.statement("drop index if exists ix_fields_value")
|
|
||||||
# add checksums and index
|
|
||||||
deck.updateAllFieldChecksums()
|
|
||||||
DeckStorage._addIndices(deck)
|
|
||||||
deck.s.execute("vacuum")
|
|
||||||
deck.s.execute("analyze")
|
|
||||||
deck.version = 71
|
|
||||||
deck.s.commit()
|
|
||||||
# executing a pragma here is very slow on large decks, so we store
|
|
||||||
# our own record
|
|
||||||
if not deck.getInt("pageSize") == 4096:
|
|
||||||
deck.s.commit()
|
|
||||||
deck.s.execute("pragma page_size = 4096")
|
|
||||||
deck.s.execute("pragma legacy_file_format = 0")
|
|
||||||
deck.s.execute("vacuum")
|
|
||||||
deck.setVar("pageSize", 4096, mod=False)
|
|
||||||
deck.s.commit()
|
|
||||||
if prog:
|
|
||||||
assert deck.modified == oldmod
|
|
||||||
deck.finishProgress()
|
|
||||||
return deck
|
|
||||||
_upgradeDeck = staticmethod(_upgradeDeck)
|
|
||||||
|
|
||||||
def _setUTCOffset(deck):
|
def _setUTCOffset(deck):
|
||||||
# 4am
|
# 4am
|
||||||
deck.utcOffset = time.timezone + 60*60*4
|
deck.utcOffset = time.timezone + 60*60*4
|
||||||
|
|
|
||||||
243
anki/upgrade.py
Normal file
243
anki/upgrade.py
Normal file
|
|
@ -0,0 +1,243 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||||
|
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
|
||||||
|
|
||||||
|
def upgradeSchema(s):
|
||||||
|
"Alter tables prior to ORM initialization."
|
||||||
|
ver = s.scalar("select version from decks limit 1")
|
||||||
|
# add a checksum to fields
|
||||||
|
if ver < 71:
|
||||||
|
try:
|
||||||
|
s.execute(
|
||||||
|
"alter table fields add column chksum text "+
|
||||||
|
"not null default ''")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return ver
|
||||||
|
|
||||||
|
def updateIndices(deck):
|
||||||
|
"Add indices to the DB."
|
||||||
|
# counts, failed cards
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_cards_typeCombined on cards
|
||||||
|
(type, combinedDue, factId)""")
|
||||||
|
# scheduler-agnostic type
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_cards_relativeDelay on cards
|
||||||
|
(relativeDelay)""")
|
||||||
|
# index on modified, to speed up sync summaries
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_cards_modified on cards
|
||||||
|
(modified)""")
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_facts_modified on facts
|
||||||
|
(modified)""")
|
||||||
|
# priority - temporary index to make compat code faster. this can be
|
||||||
|
# removed when all clients are on 1.2, as can the ones below
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_cards_priority on cards
|
||||||
|
(priority)""")
|
||||||
|
# average factor
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_cards_factor on cards
|
||||||
|
(type, factor)""")
|
||||||
|
# card spacing
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_cards_factId on cards (factId)""")
|
||||||
|
# stats
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_stats_typeDay on stats (type, day)""")
|
||||||
|
# fields
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_fields_factId on fields (factId)""")
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_fields_fieldModelId on fields (fieldModelId)""")
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_fields_chksum on fields (chksum)""")
|
||||||
|
# media
|
||||||
|
deck.s.statement("""
|
||||||
|
create unique index if not exists ix_media_filename on media (filename)""")
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_media_originalPath on media (originalPath)""")
|
||||||
|
# deletion tracking
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_cardsDeleted_cardId on cardsDeleted (cardId)""")
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_modelsDeleted_modelId on modelsDeleted (modelId)""")
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_factsDeleted_factId on factsDeleted (factId)""")
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_mediaDeleted_factId on mediaDeleted (mediaId)""")
|
||||||
|
# tags
|
||||||
|
txt = "create unique index if not exists ix_tags_tag on tags (tag)"
|
||||||
|
try:
|
||||||
|
deck.s.statement(txt)
|
||||||
|
except:
|
||||||
|
deck.s.statement("""
|
||||||
|
delete from tags where exists (select 1 from tags t2 where tags.tag = t2.tag
|
||||||
|
and tags.rowid > t2.rowid)""")
|
||||||
|
deck.s.statement(txt)
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_cardTags_tagCard on cardTags (tagId, cardId)""")
|
||||||
|
deck.s.statement("""
|
||||||
|
create index if not exists ix_cardTags_cardId on cardTags (cardId)""")
|
||||||
|
|
||||||
|
def upgradeDeck(deck):
|
||||||
|
"Upgrade deck to the latest version."
|
||||||
|
from anki.deck import DECK_VERSION
|
||||||
|
if deck.version < DECK_VERSION:
|
||||||
|
prog = True
|
||||||
|
deck.startProgress()
|
||||||
|
deck.updateProgress(_("Upgrading Deck..."))
|
||||||
|
if deck.utcOffset == -1:
|
||||||
|
# we're opening a shared deck with no indices - we'll need
|
||||||
|
# them if we want to rebuild the queue
|
||||||
|
updateIndices(deck)
|
||||||
|
oldmod = deck.modified
|
||||||
|
else:
|
||||||
|
prog = False
|
||||||
|
if deck.version < 43:
|
||||||
|
raise Exception("oldDeckVersion")
|
||||||
|
if deck.version < 44:
|
||||||
|
# leaner indices
|
||||||
|
deck.s.statement("drop index if exists ix_cards_factId")
|
||||||
|
deck.version = 44
|
||||||
|
deck.s.commit()
|
||||||
|
if deck.version < 48:
|
||||||
|
deck.updateFieldCache(deck.s.column0("select id from facts"))
|
||||||
|
deck.version = 48
|
||||||
|
deck.s.commit()
|
||||||
|
if deck.version < 52:
|
||||||
|
dname = deck.name()
|
||||||
|
sname = deck.syncName
|
||||||
|
if sname and dname != sname:
|
||||||
|
deck.notify(_("""\
|
||||||
|
When syncing, Anki now uses the same deck name on the server as the deck \
|
||||||
|
name on your computer. Because you had '%(dname)s' set to sync to \
|
||||||
|
'%(sname)s' on the server, syncing has been temporarily disabled.
|
||||||
|
|
||||||
|
If you want to keep your changes to the online version, please use \
|
||||||
|
File>Download>Personal Deck to download the online version.
|
||||||
|
|
||||||
|
If you want to keep the version on your computer, please enable \
|
||||||
|
syncing again via Settings>Deck Properties>Synchronisation.
|
||||||
|
|
||||||
|
If you have syncing disabled in the preferences, you can ignore \
|
||||||
|
this message. (ERR-0101)""") % {
|
||||||
|
'sname':sname, 'dname':dname})
|
||||||
|
deck.disableSyncing()
|
||||||
|
elif sname:
|
||||||
|
deck.enableSyncing()
|
||||||
|
deck.version = 52
|
||||||
|
deck.s.commit()
|
||||||
|
if deck.version < 53:
|
||||||
|
if deck.getBool("perDay"):
|
||||||
|
if deck.hardIntervalMin == 0.333:
|
||||||
|
deck.hardIntervalMin = max(1.0, deck.hardIntervalMin)
|
||||||
|
deck.hardIntervalMax = max(1.1, deck.hardIntervalMax)
|
||||||
|
deck.version = 53
|
||||||
|
deck.s.commit()
|
||||||
|
if deck.version < 54:
|
||||||
|
# broken versions of the DB orm die if this is a bool with a
|
||||||
|
# non-int value
|
||||||
|
deck.s.statement("update fieldModels set editFontFamily = 1");
|
||||||
|
deck.version = 54
|
||||||
|
deck.s.commit()
|
||||||
|
if deck.version < 61:
|
||||||
|
# do our best to upgrade templates to the new style
|
||||||
|
txt = '''\
|
||||||
|
<span style="font-family: %s; font-size: %spx; color: %s; white-space: pre-wrap;">%s</span>'''
|
||||||
|
for m in deck.models:
|
||||||
|
unstyled = []
|
||||||
|
for fm in m.fieldModels:
|
||||||
|
# find which fields had explicit formatting
|
||||||
|
if fm.quizFontFamily or fm.quizFontSize or fm.quizFontColour:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
unstyled.append(fm.name)
|
||||||
|
# fill out missing info
|
||||||
|
fm.quizFontFamily = fm.quizFontFamily or u"Arial"
|
||||||
|
fm.quizFontSize = fm.quizFontSize or 20
|
||||||
|
fm.quizFontColour = fm.quizFontColour or "#000000"
|
||||||
|
fm.editFontSize = fm.editFontSize or 20
|
||||||
|
unstyled = set(unstyled)
|
||||||
|
for cm in m.cardModels:
|
||||||
|
# embed the old font information into card templates
|
||||||
|
cm.qformat = txt % (
|
||||||
|
cm.questionFontFamily,
|
||||||
|
cm.questionFontSize,
|
||||||
|
cm.questionFontColour,
|
||||||
|
cm.qformat)
|
||||||
|
cm.aformat = txt % (
|
||||||
|
cm.answerFontFamily,
|
||||||
|
cm.answerFontSize,
|
||||||
|
cm.answerFontColour,
|
||||||
|
cm.aformat)
|
||||||
|
# escape fields that had no previous styling
|
||||||
|
for un in unstyled:
|
||||||
|
cm.qformat = cm.qformat.replace("%("+un+")s", "{{{%s}}}"%un)
|
||||||
|
cm.aformat = cm.aformat.replace("%("+un+")s", "{{{%s}}}"%un)
|
||||||
|
# rebuild q/a for the above & because latex has changed
|
||||||
|
for m in deck.models:
|
||||||
|
deck.updateCardsFromModel(m, dirty=False)
|
||||||
|
# rebuild the media db based on new format
|
||||||
|
rebuildMediaDir(deck, dirty=False)
|
||||||
|
deck.version = 61
|
||||||
|
deck.s.commit()
|
||||||
|
if deck.version < 62:
|
||||||
|
# updated indices
|
||||||
|
deck.s.statement("drop index if exists ix_cards_typeCombined")
|
||||||
|
updateIndices(deck)
|
||||||
|
deck.version = 62
|
||||||
|
deck.s.commit()
|
||||||
|
if deck.version < 64:
|
||||||
|
# remove old static indices, as all clients should be libanki1.2+
|
||||||
|
for d in ("ix_cards_duePriority",
|
||||||
|
"ix_cards_priorityDue"):
|
||||||
|
deck.s.statement("drop index if exists %s" % d)
|
||||||
|
deck.version = 64
|
||||||
|
deck.s.commit()
|
||||||
|
# note: we keep the priority index for now
|
||||||
|
if deck.version < 65:
|
||||||
|
# we weren't correctly setting relativeDelay when answering cards
|
||||||
|
# in previous versions, so ensure everything is set correctly
|
||||||
|
deck.rebuildTypes()
|
||||||
|
deck.version = 65
|
||||||
|
deck.s.commit()
|
||||||
|
# skip a few to allow for updates to stable tree
|
||||||
|
if deck.version < 70:
|
||||||
|
# update dynamic indices given we don't use priority anymore
|
||||||
|
for d in ("intervalDesc", "intervalAsc", "randomOrder",
|
||||||
|
"dueAsc", "dueDesc"):
|
||||||
|
deck.s.statement("drop index if exists ix_cards_%s2" % d)
|
||||||
|
deck.s.statement("drop index if exists ix_cards_%s" % d)
|
||||||
|
deck.updateDynamicIndices()
|
||||||
|
# remove old views
|
||||||
|
for v in ("failedCards", "revCardsOld", "revCardsNew",
|
||||||
|
"revCardsDue", "revCardsRandom", "acqCardsRandom",
|
||||||
|
"acqCardsOld", "acqCardsNew"):
|
||||||
|
deck.s.statement("drop view if exists %s" % v)
|
||||||
|
deck.version = 70
|
||||||
|
deck.s.commit()
|
||||||
|
if deck.version < 71:
|
||||||
|
# remove the expensive value cache
|
||||||
|
deck.s.statement("drop index if exists ix_fields_value")
|
||||||
|
# add checksums and index
|
||||||
|
deck.updateAllFieldChecksums()
|
||||||
|
updateIndices(deck)
|
||||||
|
deck.s.execute("vacuum")
|
||||||
|
deck.s.execute("analyze")
|
||||||
|
deck.version = 71
|
||||||
|
deck.s.commit()
|
||||||
|
# executing a pragma here is very slow on large decks, so we store
|
||||||
|
# our own record
|
||||||
|
if not deck.getInt("pageSize") == 4096:
|
||||||
|
deck.s.commit()
|
||||||
|
deck.s.execute("pragma page_size = 4096")
|
||||||
|
deck.s.execute("pragma legacy_file_format = 0")
|
||||||
|
deck.s.execute("vacuum")
|
||||||
|
deck.setVar("pageSize", 4096, mod=False)
|
||||||
|
deck.s.commit()
|
||||||
|
if prog:
|
||||||
|
assert deck.modified == oldmod
|
||||||
|
deck.finishProgress()
|
||||||
Loading…
Reference in a new issue