This commit is contained in:
Soren I. Bjornstad 2013-10-11 09:03:42 -05:00
commit 019249269b
7 changed files with 42 additions and 13 deletions

View file

@ -2,7 +2,13 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import time, os, random, stat, datetime, copy import time
import os
import random
import stat
import datetime
import copy
from anki.lang import _, ngettext from anki.lang import _, ngettext
from anki.utils import ids2str, fieldChecksum, stripHTML, \ from anki.utils import ids2str, fieldChecksum, stripHTML, \
intTime, splitFields, joinFields, maxID, json intTime, splitFields, joinFields, maxID, json
@ -15,9 +21,12 @@ from anki.tags import TagManager
from anki.consts import * from anki.consts import *
from anki.errors import AnkiError from anki.errors import AnkiError
from anki.sound import stripSounds from anki.sound import stripSounds
import anki.latex # sets up hook import anki.latex # sets up hook
import anki.cards, anki.notes, anki.template, anki.find import anki.cards
import anki.notes
import anki.template
import anki.find
defaultConf = { defaultConf = {
# review options # review options
@ -176,15 +185,20 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""",
def beforeUpload(self): def beforeUpload(self):
"Called before a full upload." "Called before a full upload."
tbls = "notes", "cards", "revlog", "graves" tbls = "notes", "cards", "revlog"
for t in tbls: for t in tbls:
self.db.execute("update %s set usn=0 where usn=-1" % t) self.db.execute("update %s set usn=0 where usn=-1" % t)
# we can save space by removing the log of deletions
self.db.execute("delete from graves")
self._usn += 1 self._usn += 1
self.models.beforeUpload() self.models.beforeUpload()
self.tags.beforeUpload() self.tags.beforeUpload()
self.decks.beforeUpload() self.decks.beforeUpload()
self.modSchema() self.modSchema()
self.ls = self.scm self.ls = self.scm
# ensure db is compacted before upload
self.db.execute("vacuum")
self.db.execute("analyze")
self.close() self.close()
# Object creation helpers # Object creation helpers

View file

@ -47,7 +47,7 @@ SCHEMA_VERSION = 11
SYNC_ZIP_SIZE = int(2.5*1024*1024) SYNC_ZIP_SIZE = int(2.5*1024*1024)
SYNC_ZIP_COUNT = 100 SYNC_ZIP_COUNT = 100
SYNC_URL = os.environ.get("SYNC_URL") or "https://ankiweb.net/sync/" SYNC_URL = os.environ.get("SYNC_URL") or "https://ankiweb.net/sync/"
SYNC_VER = 7 SYNC_VER = 8
HELP_SITE="http://ankisrs.net/docs/manual.html" HELP_SITE="http://ankisrs.net/docs/manual.html"

View file

@ -152,7 +152,8 @@ class AnkiExporter(Exporter):
else: else:
# need to reset card state # need to reset card state
self.dst.sched.resetCards(cids) self.dst.sched.resetCards(cids)
# models # models - start with zero
self.dst.models.models = {}
for m in self.src.models.all(): for m in self.src.models.all():
if int(m['id']) in mids: if int(m['id']) in mids:
self.dst.models.update(m) self.dst.models.update(m)

View file

@ -124,8 +124,8 @@ class ModelManager(object):
"Get all models." "Get all models."
return self.models.values() return self.models.values()
def allNames(self, curm=None): def allNames(self):
return [m['name'] for m in self.all() if m!=curm] return [m['name'] for m in self.all()]
def byName(self, name): def byName(self, name):
"Get model with NAME." "Get model with NAME."
@ -171,6 +171,7 @@ select id from cards where nid in (select id from notes where mid = ?)""",
if (mcur['name'] == m['name'] and if (mcur['name'] == m['name'] and
mcur['id'] != m['id']): mcur['id'] != m['id']):
m['name'] += "-" + checksum(str(time.time()))[:5] m['name'] += "-" + checksum(str(time.time()))[:5]
break
def update(self, m): def update(self, m):
"Add or update an existing model. Used for syncing and merging." "Add or update an existing model. Used for syncing and merging."

View file

@ -2,10 +2,16 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import urllib, os, sys, httplib2, gzip import urllib
import os
import sys
import gzip
import random
from cStringIO import StringIO from cStringIO import StringIO
import httplib2
from anki.db import DB from anki.db import DB
from anki.utils import ids2str, intTime, json, isWin, isMac, platDesc from anki.utils import ids2str, intTime, json, isWin, isMac, platDesc, checksum
from anki.consts import * from anki.consts import *
from hooks import runHook from hooks import runHook
import anki import anki
@ -519,6 +525,7 @@ class HttpSyncer(object):
def __init__(self, hkey=None, con=None): def __init__(self, hkey=None, con=None):
self.hkey = hkey self.hkey = hkey
self.skey = checksum(str(random.random()))[:8]
self.con = con or httpCon() self.con = con or httpCon()
def assertOk(self, resp): def assertOk(self, resp):
@ -541,6 +548,7 @@ class HttpSyncer(object):
vars['c'] = 1 if comp else 0 vars['c'] = 1 if comp else 0
if hkey: if hkey:
vars['k'] = self.hkey vars['k'] = self.hkey
vars['s'] = self.skey
for (key, value) in vars.items(): for (key, value) in vars.items():
buf.write(bdry + "\r\n") buf.write(bdry + "\r\n")
buf.write( buf.write(

View file

@ -236,7 +236,7 @@ class DataModel(QAbstractTableModel):
elif type == "cardLapses": elif type == "cardLapses":
return str(c.lapses) return str(c.lapses)
elif type == "noteTags": elif type == "noteTags":
return str(" ".join(c.note().tags)) return " ".join(c.note().tags)
elif type == "note": elif type == "note":
return c.model()['name'] return c.model()['name']
elif type == "cardIvl": elif type == "cardIvl":

View file

@ -2,8 +2,12 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import division from __future__ import division
import socket
import time
import traceback
import gc
from aqt.qt import * from aqt.qt import *
import socket, time, traceback, gc
import aqt import aqt
from anki import Collection from anki import Collection
from anki.sync import Syncer, RemoteServer, FullSyncer, MediaSyncer, \ from anki.sync import Syncer, RemoteServer, FullSyncer, MediaSyncer, \
@ -11,6 +15,7 @@ from anki.sync import Syncer, RemoteServer, FullSyncer, MediaSyncer, \
from anki.hooks import addHook, remHook from anki.hooks import addHook, remHook
from aqt.utils import tooltip, askUserDialog, showWarning, showText, showInfo from aqt.utils import tooltip, askUserDialog, showWarning, showText, showInfo
# Sync manager # Sync manager
###################################################################### ######################################################################
@ -161,7 +166,7 @@ AnkiWeb is too busy at the moment. Please try again in a few minutes.""")
elif "504" in err: elif "504" in err:
return _("504 gateway timeout error received. Please try temporarily disabling your antivirus.") return _("504 gateway timeout error received. Please try temporarily disabling your antivirus.")
elif "409" in err: elif "409" in err:
return _("A previous sync failed; please try again in a few minutes.") return _("Only one client can access AnkiWeb at a time. If a previous sync failed, please try again in a few minutes.")
elif "10061" in err or "10013" in err: elif "10061" in err or "10013" in err:
return _( return _(
"Antivirus or firewall software is preventing Anki from connecting to the internet.") "Antivirus or firewall software is preventing Anki from connecting to the internet.")