125 lines
3.4 KiB
Python
125 lines
3.4 KiB
Python
"""
|
|
revisionhistory_test
|
|
"""
|
|
from mceditlib.revisionhistory import RevisionHistory
|
|
from mceditlib.test.templevel import TempFile
|
|
|
|
import logging
|
|
|
|
log = logging.getLogger(__name__)
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
|
|
import pytest
|
|
|
|
from mceditlib import nbt
|
|
|
|
@pytest.fixture
|
|
def history():
|
|
filename = "AnvilWorld"
|
|
tmpname = TempFile(filename)
|
|
return RevisionHistory(tmpname)
|
|
|
|
def readChunkTag(rev, cx, cz):
|
|
return nbt.load(buf=rev.readChunkBytes(cx, cz, ""))
|
|
|
|
def writeChunkTag(rev, cx, cz, tag):
|
|
return rev.writeChunkBytes(cx, cz, "", tag.save(compressed=False))
|
|
|
|
|
|
def testRevision(history):
|
|
revA = history.createRevision()
|
|
log.info("revA")
|
|
# rev A @1 - touch chunk 1
|
|
cx, cz = iter(revA.chunkPositions("")).next()
|
|
chunk = readChunkTag(revA, cx, cz)
|
|
|
|
old_tag = tag = nbt.load(buf=history.rootFolder.readChunkBytes(cx, cz, ""))
|
|
|
|
assert readChunkTag(history.rootNode, cx, cz) == tag
|
|
assert chunk == tag
|
|
chunk["Level"]["test"] = nbt.TAG_String("test string")
|
|
|
|
writeChunkTag(revA, cx, cz, chunk)
|
|
|
|
tag = readChunkTag(revA, cx, cz)
|
|
assert "test" in tag["Level"] and tag["Level"]["test"].value == "test string"
|
|
|
|
revB = history.createRevision()
|
|
log.info("revB")
|
|
|
|
# rev B @2 - delete chunk 2
|
|
tag = readChunkTag(revB, cx, cz)
|
|
assert "test" in tag["Level"] and tag["Level"]["test"].value == "test string"
|
|
|
|
revB.deleteChunk(cx+1, cz, "")
|
|
assert not revB.containsChunk(cx+1, cz, "")
|
|
|
|
revC = history.createRevision()
|
|
log.info("revC")
|
|
|
|
# rev C @3 - delete file
|
|
assert not revC.containsChunk(cx+1, cz, "")
|
|
revC.deleteFile("level.dat")
|
|
|
|
assert not revC.containsFile("level.dat")
|
|
|
|
changes = revC.getChanges()
|
|
assert changes.chunks[""] == set()
|
|
assert changes.files == {"level.dat"}
|
|
|
|
tailRev = history.getRevision(0)
|
|
|
|
history.writeAllChanges()
|
|
|
|
# initial folder (rev idx 0) and following nodes replaced by reverse nodes
|
|
# rev C @3 replaced by initial folder
|
|
assert revC.invalid
|
|
|
|
revC = history.getHead()
|
|
assert tailRev is revC
|
|
|
|
changes = revC.getChanges()
|
|
assert changes.chunks[""] == set()
|
|
assert changes.files == {"level.dat"}
|
|
|
|
# rev D - create chunk 3
|
|
revD = history.createRevision()
|
|
log.info("revD")
|
|
|
|
assert not revD.containsFile("level.dat")
|
|
writeChunkTag(revD, 1000, 1000, old_tag)
|
|
|
|
assert not history.rootFolder.containsFile("level.dat")
|
|
assert not history.rootFolder.containsChunk(cx+1, cz, "")
|
|
|
|
assert "test" in tag["Level"]
|
|
tag = readChunkTag(history.rootFolder, cx, cz)
|
|
assert tag != old_tag
|
|
assert "test" in tag["Level"]
|
|
|
|
# grab rev B
|
|
revBagain = history.getRevision(2)
|
|
assert "test" in readChunkTag(revBagain, cx, cz)["Level"]
|
|
assert not revBagain.containsChunk(cx+1, cz, "")
|
|
|
|
# rev B should be read only
|
|
with pytest.raises(IOError):
|
|
writeChunkTag(revBagain, cx, cz, old_tag)
|
|
|
|
# check all changes so far
|
|
allChanges = history.getRevisionChanges(0, revD)
|
|
assert allChanges.chunks[""] == {(cx, cz), (cx+1, cz), (1000, 1000)}
|
|
assert allChanges.files == {"level.dat"}
|
|
|
|
# insert rev E after rev B
|
|
# world folder is now at the end of an orphan chain at rev @2
|
|
# orphaned revisions are read only and still valid, but do not appear in the history
|
|
revE = history.createRevision(2)
|
|
assert "test" in readChunkTag(revE, cx, cz)["Level"]
|
|
assert not revE.containsChunk(cx+1, cz, "")
|
|
|
|
history.close()
|
|
|
|
|