new backup-friendly backup handling

This commit is contained in:
Damien Elmes 2009-06-20 02:05:11 +09:00
parent 1f0a8edfa4
commit f94104ed9f

View file

@ -3234,48 +3234,48 @@ nextFactor, reps, thinkingTime, yesCount, noCount from reviewHistory""")
_setUTCOffset = staticmethod(_setUTCOffset) _setUTCOffset = staticmethod(_setUTCOffset)
def backup(modified, path): def backup(modified, path):
# need a non-unicode path """Path must not be unicode."""
def backupName(path, num): #path = os.path.join(backupDir, path)
if not numBackups:
return
def escape(path):
path = os.path.abspath(path) path = os.path.abspath(path)
path = path.replace("\\", "!") path = path.replace("\\", "!")
path = path.replace("/", "!") path = path.replace("/", "!")
path = path.replace(":", "") path = path.replace(":", "")
path = os.path.join(backupDir, path)
path = re.sub("\.anki$", ".backup-%d.anki" % num, path)
return path return path
if not numBackups: escp = escape(path)
return # find existing backups
if not os.path.exists(backupDir): gen = re.sub("\.anki$", ".backup-(\d+).anki", re.escape(escp))
os.makedirs(backupDir) backups = []
# if the mod time is identical, don't make a new backup for file in os.listdir(backupDir):
firstBack = backupName(path, 0) m = re.match(gen, file)
if os.path.exists(firstBack): if m:
s1 = int(modified) backups.append((int(m.group(1)), file))
s2 = int(os.stat(firstBack)[stat.ST_MTIME]) backups.sort()
if s1 == s2: # check if last backup is the same
if backups:
latest = os.path.join(backupDir, backups[-1][1])
if int(modified) == int(
os.stat(latest)[stat.ST_MTIME]):
return return
# remove the oldest backup if it exists # get next num
oldest = backupName(path, numBackups) if not backups:
if os.path.exists(oldest): n = 1
os.chmod(oldest, 0666) else:
os.unlink(oldest) n = backups[-1][0] + 1
# move all the other backups up one # do backup
for n in range(numBackups - 1, -1, -1): newpath = os.path.join(backupDir, os.path.basename(
name = backupName(path, n) re.sub("\.anki$", ".backup-%s.anki" % n, escp)))
if os.path.exists(name):
newname = backupName(path, n+1)
if os.path.exists(newname):
os.chmod(newname, 0666)
os.unlink(newname)
os.rename(name, newname)
# save the current path
newpath = backupName(path, 0)
if os.path.exists(newpath):
os.chmod(newpath, 0666)
os.unlink(newpath)
shutil.copy2(path, newpath) shutil.copy2(path, newpath)
# set mtimes to be identical # set mtimes to be identical
os.utime(newpath, (modified, modified)) os.utime(newpath, (modified, modified))
# remove if over
if len(backups) + 1 > numBackups:
delete = len(backups) + 1 - numBackups
delete = backups[:delete]
for file in delete:
os.unlink(os.path.join(backupDir, file[1]))
backup = staticmethod(backup) backup = staticmethod(backup)
def newCardOrderLabels(): def newCardOrderLabels():