mirror of
https://github.com/ankitects/anki.git
synced 2025-09-22 07:52:24 -04:00
refactor media
- created->modified - size->refcnt - originalPath->chksum - remove description
This commit is contained in:
parent
edd8f79ab9
commit
2d1d946504
4 changed files with 50 additions and 54 deletions
|
@ -122,7 +122,7 @@ select models.id, models.modified from models, facts where
|
|||
facts.modelId = models.id and
|
||||
facts.id in %s""" % ids2str([f[0] for f in facts]))
|
||||
media = self.deck.db.all("""
|
||||
select id, created from media""")
|
||||
select id, modified from media""")
|
||||
return {
|
||||
# cards
|
||||
"cards": cards,
|
||||
|
|
|
@ -17,22 +17,10 @@ regexps = ("(?i)(\[sound:([^]]+)\])",
|
|||
mediaTable = Table(
|
||||
'media', metadata,
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('filename', UnicodeText, nullable=False),
|
||||
# reused as reference count
|
||||
Column('size', Integer, nullable=False),
|
||||
# treated as modification date, not creation date
|
||||
Column('created', Float, nullable=False),
|
||||
# reused as md5sum. empty string if file doesn't exist on disk
|
||||
Column('originalPath', UnicodeText, nullable=False, default=u""),
|
||||
# older versions stored original filename here, so we'll leave it for now
|
||||
# in case we add a feature to rename media back to its original name. in
|
||||
# the future we may want to zero this to save space
|
||||
Column('description', UnicodeText, nullable=False, default=u""))
|
||||
|
||||
class Media(object):
|
||||
pass
|
||||
|
||||
mapper(Media, mediaTable)
|
||||
Column('filename', UnicodeText, nullable=False, unique=True),
|
||||
Column('refcnt', Integer, nullable=False),
|
||||
Column('modified', Float, nullable=False),
|
||||
Column('chksum', UnicodeText, nullable=False, default=u""))
|
||||
|
||||
mediaDeletedTable = Table(
|
||||
'mediaDeleted', metadata,
|
||||
|
@ -51,7 +39,7 @@ If a file with the same name exists, return a unique name.
|
|||
This does not modify the media table."""
|
||||
# see if have duplicate contents
|
||||
newpath = deck.db.scalar(
|
||||
"select filename from media where originalPath = :cs",
|
||||
"select filename from media where chksum = :cs",
|
||||
cs=checksum(open(path, "rb").read()))
|
||||
# check if this filename already exists
|
||||
if not newpath:
|
||||
|
@ -88,7 +76,7 @@ def updateMediaCount(deck, file, count=1):
|
|||
if deck.db.scalar(
|
||||
"select 1 from media where filename = :file", file=file):
|
||||
deck.db.statement(
|
||||
"update media set size = size + :c, created = :t where filename = :file",
|
||||
"update media set refcnt = refcnt + :c, modified = :t where filename = :file",
|
||||
file=file, c=count, t=time.time())
|
||||
elif count > 0:
|
||||
try:
|
||||
|
@ -97,17 +85,17 @@ def updateMediaCount(deck, file, count=1):
|
|||
except:
|
||||
sum = u""
|
||||
deck.db.statement("""
|
||||
insert into media (id, filename, size, created, originalPath, description)
|
||||
values (:id, :file, :c, :mod, :sum, '')""",
|
||||
insert into media (id, filename, refcnt, modified, chksum)
|
||||
values (:id, :file, :c, :mod, :sum)""",
|
||||
id=genID(), file=file, c=count, mod=time.time(),
|
||||
sum=sum)
|
||||
|
||||
def removeUnusedMedia(deck):
|
||||
ids = deck.db.column0("select id from media where size = 0")
|
||||
ids = deck.db.column0("select id from media where refcnt = 0")
|
||||
for id in ids:
|
||||
deck.db.statement("insert into mediaDeleted values (:id, :t)",
|
||||
id=id, t=time.time())
|
||||
deck.db.statement("delete from media where size = 0")
|
||||
deck.db.statement("delete from media where refcnt = 0")
|
||||
|
||||
# String manipulation
|
||||
##########################################################################
|
||||
|
@ -147,7 +135,7 @@ def rebuildMediaDir(deck, delete=False, dirty=True):
|
|||
return (0, 0)
|
||||
deck.startProgress(title=_("Check Media DB"))
|
||||
# set all ref counts to 0
|
||||
deck.db.statement("update media set size = 0")
|
||||
deck.db.statement("update media set refcnt = 0")
|
||||
# look through cards for media references
|
||||
refs = {}
|
||||
normrefs = {}
|
||||
|
@ -186,8 +174,8 @@ def rebuildMediaDir(deck, delete=False, dirty=True):
|
|||
removeUnusedMedia(deck)
|
||||
# check md5s are up to date
|
||||
update = []
|
||||
for (file, created, md5) in deck.db.all(
|
||||
"select filename, created, originalPath from media"):
|
||||
for (file, md5) in deck.db.all(
|
||||
"select filename, chksum from media"):
|
||||
path = os.path.join(mdir, file)
|
||||
if not os.path.exists(path):
|
||||
if md5:
|
||||
|
@ -199,12 +187,12 @@ def rebuildMediaDir(deck, delete=False, dirty=True):
|
|||
update.append({'f':file, 'sum':sum, 'c':time.time()})
|
||||
if update:
|
||||
deck.db.statements("""
|
||||
update media set originalPath = :sum, created = :c where filename = :f""",
|
||||
update media set chksum = :sum, modified = :c where filename = :f""",
|
||||
update)
|
||||
# update deck and get return info
|
||||
if dirty:
|
||||
deck.flushMod()
|
||||
nohave = deck.db.column0("select filename from media where originalPath = ''")
|
||||
nohave = deck.db.column0("select filename from media where chksum = ''")
|
||||
deck.finishProgress()
|
||||
return (nohave, unused)
|
||||
|
||||
|
@ -220,7 +208,7 @@ def downloadMissing(deck):
|
|||
missing = 0
|
||||
grabbed = 0
|
||||
for c, (f, sum) in enumerate(deck.db.all(
|
||||
"select filename, originalPath from media")):
|
||||
"select filename, chksum from media")):
|
||||
path = os.path.join(mdir, f)
|
||||
if not os.path.exists(path):
|
||||
try:
|
||||
|
|
|
@ -29,35 +29,45 @@ def upgradeSchema(engine, s):
|
|||
except:
|
||||
pass
|
||||
if ver < 75:
|
||||
# migrate cards
|
||||
# cards
|
||||
###########
|
||||
moveTable(s, "cards")
|
||||
import cards
|
||||
metadata.create_all(engine, tables=[cards.cardsTable])
|
||||
# move data across
|
||||
s.execute("""
|
||||
insert into cards select id, factId, cardModelId, created, modified,
|
||||
question, answer, 0, ordinal, 0, relativeDelay, type, lastInterval, interval,
|
||||
due, factor, reps, successive, noCount from cards2""")
|
||||
s.execute("drop table cards2")
|
||||
# migrate tags
|
||||
# tags
|
||||
###########
|
||||
moveTable(s, "tags")
|
||||
moveTable(s, "cardTags")
|
||||
initTagTables(s)
|
||||
# move data across
|
||||
s.execute("insert or ignore into tags select id, tag, 0 from tags2")
|
||||
s.execute("""
|
||||
insert or ignore into cardTags select cardId, tagId, src from cardTags2""")
|
||||
s.execute("drop table tags2")
|
||||
s.execute("drop table cardTags2")
|
||||
# migrate facts
|
||||
# facts
|
||||
###########
|
||||
moveTable(s, "facts")
|
||||
import facts
|
||||
metadata.create_all(engine, tables=[facts.factsTable])
|
||||
# move data across
|
||||
s.execute("""
|
||||
insert or ignore into facts select id, modelId, created, modified, tags,
|
||||
spaceUntil from facts2""")
|
||||
s.execute("drop table facts2")
|
||||
# media
|
||||
###########
|
||||
moveTable(s, "media")
|
||||
import media
|
||||
metadata.create_all(engine, tables=[media.mediaTable])
|
||||
s.execute("""
|
||||
insert or ignore into media select id, filename, size, created,
|
||||
originalPath from media2""")
|
||||
s.execute("drop table media2")
|
||||
|
||||
return ver
|
||||
|
||||
def updateIndices(deck):
|
||||
|
@ -84,14 +94,10 @@ create index if not exists ix_cards_factId on cards (factId)""")
|
|||
deck.db.statement("""
|
||||
create index if not exists ix_fields_factId on fields (factId)""")
|
||||
deck.db.statement("""
|
||||
create index if not exists ix_fields_fieldModelId on fields (fieldModelId)""")
|
||||
deck.db.statement("""
|
||||
create index if not exists ix_fields_chksum on fields (chksum)""")
|
||||
# media
|
||||
deck.db.statement("""
|
||||
create unique index if not exists ix_media_filename on media (filename)""")
|
||||
deck.db.statement("""
|
||||
create index if not exists ix_media_originalPath on media (originalPath)""")
|
||||
create index if not exists ix_media_chksum on media (chksum)""")
|
||||
# deletion tracking
|
||||
deck.db.statement("""
|
||||
create index if not exists ix_cardsDeleted_cardId on cardsDeleted (cardId)""")
|
||||
|
@ -173,6 +179,8 @@ cast(min(thinkingTime, 60)*1000 as int), 0 from reviewHistory""")
|
|||
deck.db.execute("update cards set queue=-1 where queue between -3 and -1")
|
||||
deck.db.execute("update cards set queue=-2 where queue between 3 and 5")
|
||||
deck.db.execute("update cards set queue=-3 where queue between 6 and 8")
|
||||
# don't need an index on fieldModelId
|
||||
deck.db.statement("drop index if exists ix_fields_fieldModelId")
|
||||
# new indices for new cards table
|
||||
updateIndices(deck)
|
||||
deck.version = 75
|
||||
|
|
|
@ -34,7 +34,7 @@ def test_copy():
|
|||
assert m.copyToMedia(deck, path) == "foo.jpg"
|
||||
# dupe md5
|
||||
deck.db.statement("""
|
||||
insert into media values (null, 'foo.jpg', 0, 0, :sum, '')""",
|
||||
insert into media values (null, 'foo.jpg', 0, 0, :sum)""",
|
||||
sum=checksum("hello"))
|
||||
path = os.path.join(dir, "bar.jpg")
|
||||
open(path, "w").write("hello")
|
||||
|
@ -54,53 +54,53 @@ def test_db():
|
|||
deck.addFact(f)
|
||||
# 1 entry in the media db, with two references, and missing file
|
||||
assert deck.db.scalar("select count() from media") == 1
|
||||
assert deck.db.scalar("select size from media") == 2
|
||||
assert deck.db.scalar("select not originalPath from media")
|
||||
assert deck.db.scalar("select refcnt from media") == 2
|
||||
assert not deck.db.scalar("select group_concat(chksum, '') from media")
|
||||
# copy to media folder & check db
|
||||
path = m.copyToMedia(deck, path)
|
||||
m.rebuildMediaDir(deck)
|
||||
# md5 should be set now
|
||||
assert deck.db.scalar("select count() from media") == 1
|
||||
assert deck.db.scalar("select size from media") == 2
|
||||
assert deck.db.scalar("select originalPath from media")
|
||||
assert deck.db.scalar("select refcnt from media") == 2
|
||||
assert deck.db.scalar("select group_concat(chksum, '') from media")
|
||||
# edit the fact to remove a reference
|
||||
f['Back'] = u""
|
||||
f.setModified(True, deck)
|
||||
deck.db.flush()
|
||||
assert deck.db.scalar("select count() from media") == 1
|
||||
assert deck.db.scalar("select size from media") == 1
|
||||
assert deck.db.scalar("select refcnt from media") == 1
|
||||
# remove the front reference too
|
||||
f['Front'] = u""
|
||||
f.setModified(True, deck)
|
||||
assert deck.db.scalar("select size from media") == 0
|
||||
assert deck.db.scalar("select refcnt from media") == 0
|
||||
# add the reference back
|
||||
f['Front'] = u"<img src='foo.jpg'>"
|
||||
f.setModified(True, deck)
|
||||
assert deck.db.scalar("select size from media") == 1
|
||||
assert deck.db.scalar("select refcnt from media") == 1
|
||||
# detect file modifications
|
||||
oldsum = deck.db.scalar("select originalPath from media")
|
||||
oldsum = deck.db.scalar("select chksum from media")
|
||||
open(path, "w").write("world")
|
||||
m.rebuildMediaDir(deck)
|
||||
newsum = deck.db.scalar("select originalPath from media")
|
||||
newsum = deck.db.scalar("select chksum from media")
|
||||
assert newsum and newsum != oldsum
|
||||
# delete underlying file and check db
|
||||
os.unlink(path)
|
||||
m.rebuildMediaDir(deck)
|
||||
# md5 should be gone again
|
||||
assert deck.db.scalar("select count() from media") == 1
|
||||
assert deck.db.scalar("select not originalPath from media")
|
||||
assert deck.db.scalar("select not chksum from media")
|
||||
# media db should pick up media defined via templates & bulk update
|
||||
f['Back'] = u"bar.jpg"
|
||||
f.setModified(True, deck)
|
||||
deck.db.flush()
|
||||
# modify template & regenerate
|
||||
assert deck.db.scalar("select count() from media") == 1
|
||||
assert deck.db.scalar("select sum(size) from media") == 1
|
||||
assert deck.db.scalar("select sum(refcnt) from media") == 1
|
||||
deck.currentModel.cardModels[0].aformat=u'<img src="{{{Back}}}">'
|
||||
deck.updateCardsFromModel(deck.currentModel)
|
||||
assert deck.db.scalar("select sum(size) from media") == 2
|
||||
assert deck.db.scalar("select sum(refcnt) from media") == 2
|
||||
assert deck.db.scalar("select count() from media") == 2
|
||||
deck.currentModel.cardModels[0].aformat=u'{{{Back}}}'
|
||||
deck.updateCardsFromModel(deck.currentModel)
|
||||
assert deck.db.scalar("select count() from media") == 2
|
||||
assert deck.db.scalar("select sum(size) from media") == 1
|
||||
assert deck.db.scalar("select sum(refcnt) from media") == 1
|
||||
|
|
Loading…
Reference in a new issue