Ported get_data_hash() and renamed to hash()
This commit is contained in:
parent
db14cc5074
commit
55075c09b6
@ -456,22 +456,26 @@ class BlendFileBlock:
|
|||||||
yield from self.get_recursive_iter(f.name.name_only, path_full, default=default,
|
yield from self.get_recursive_iter(f.name.name_only, path_full, default=default,
|
||||||
null_terminated=null_terminated, as_str=as_str)
|
null_terminated=null_terminated, as_str=as_str)
|
||||||
|
|
||||||
def get_data_hash(self): # TODO(Sybren): port to BAT
|
def hash(self) -> int:
|
||||||
|
"""Generate a pointer-independent hash for the block.
|
||||||
|
|
||||||
|
Generates a 'hash' that can be used instead of addr_old as block id,
|
||||||
|
which should be 'stable' across .blend file load & save (i.e. it does
|
||||||
|
not changes due to pointer addresses variations).
|
||||||
"""
|
"""
|
||||||
Generates a 'hash' that can be used instead of addr_old as block id, and that should be 'stable' across .blend
|
# TODO This implementation is most likely far from optimal... and CRC32
|
||||||
file load & save (i.e. it does not changes due to pointer addresses variations).
|
# is not kown as the best hashing algo either. But for now does the job!
|
||||||
"""
|
|
||||||
# TODO This implementation is most likely far from optimal... and CRC32 is not renown as the best hashing
|
|
||||||
# algo either. But for now does the job!
|
|
||||||
import zlib
|
import zlib
|
||||||
def _is_pointer(self, k):
|
|
||||||
return self.file.structs[self.sdna_index].field_from_path(
|
dna_type = self.dna_type
|
||||||
self.file.header, self.file.handle, k).dna_name.is_pointer
|
pointer_size = self.bfile.header.pointer_size
|
||||||
|
|
||||||
hsh = 1
|
hsh = 1
|
||||||
for k, v in self.items_recursive():
|
for path, value in self.items_recursive():
|
||||||
if not _is_pointer(self, k):
|
field, _ = dna_type.field_from_path(pointer_size, path)
|
||||||
hsh = zlib.adler32(str(v).encode(), hsh)
|
if field.name.is_pointer:
|
||||||
|
continue
|
||||||
|
hsh = zlib.adler32(str(value).encode(), hsh)
|
||||||
return hsh
|
return hsh
|
||||||
|
|
||||||
def set(self, path: dna.FieldPath, value): # TODO(Sybren): port to BAT
|
def set(self, path: dna.FieldPath, value): # TODO(Sybren): port to BAT
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
from blender_asset_tracer import blendfile
|
from blender_asset_tracer import blendfile
|
||||||
from abstract_test import AbstractBlendFileTest
|
from abstract_test import AbstractBlendFileTest
|
||||||
|
|
||||||
@ -25,14 +27,35 @@ class ModifyUncompressedTest(AbstractBlendFileTest):
|
|||||||
library[b'filepath'] = b'//basic_file.blend'
|
library[b'filepath'] = b'//basic_file.blend'
|
||||||
library[b'name'] = b'//basic_file.blend'
|
library[b'name'] = b'//basic_file.blend'
|
||||||
|
|
||||||
# Reload the blend file to inspect that it was written properly.
|
self.reload()
|
||||||
self.bf.close()
|
|
||||||
self.bf = blendfile.BlendFile(self.to_modify, mode='r+b')
|
|
||||||
|
|
||||||
library = self.bf.code_index[b'LI'][0]
|
library = self.bf.code_index[b'LI'][0]
|
||||||
self.assertEqual(b'//basic_file.blend', library[b'filepath'])
|
self.assertEqual(b'//basic_file.blend', library[b'filepath'])
|
||||||
self.assertEqual(b'//basic_file.blend', library[b'name'])
|
self.assertEqual(b'//basic_file.blend', library[b'name'])
|
||||||
|
|
||||||
|
def test_block_hash(self):
|
||||||
|
scene = self.bf.code_index[b'SC'][0]
|
||||||
|
assert isinstance(scene, blendfile.BlendFileBlock)
|
||||||
|
|
||||||
|
pre_hash = scene.hash()
|
||||||
|
self.assertIsInstance(pre_hash, int)
|
||||||
|
|
||||||
|
# Change the 'ed' pointer to some arbitrary value by hacking the blend file.
|
||||||
|
psize = self.bf.header.pointer_size
|
||||||
|
field, field_offset = scene.dna_type.field_from_path(psize, b'ed')
|
||||||
|
self.bf.fileobj.seek(scene.file_offset + field_offset, os.SEEK_SET)
|
||||||
|
self.bf.fileobj.write(b'12345678'[:psize])
|
||||||
|
|
||||||
|
self.reload()
|
||||||
|
|
||||||
|
scene = self.bf.code_index[b'SC'][0]
|
||||||
|
post_hash = scene.hash()
|
||||||
|
self.assertEqual(pre_hash, post_hash)
|
||||||
|
|
||||||
|
def reload(self):
|
||||||
|
self.bf.close()
|
||||||
|
self.bf = blendfile.BlendFile(self.to_modify, mode='r+b')
|
||||||
|
|
||||||
|
|
||||||
class ModifyCompressedTest(AbstractBlendFileTest):
|
class ModifyCompressedTest(AbstractBlendFileTest):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user