We are now able to retrieve any object from a repo, but if you cast your mind back through the mists of time to when we were reconstructing delta'fied objects, you might remember that there were two types of delta'fied object, but we only handled one of them (OFS_DELTA's). We now have the infrastructure to handle the other one (REF_DELTA's).
The two types of delta'fied object differ only in how they specify what their base object is. We saw that OFS_DELTA's have an offset to the base object within the same pack data file:
def _read_ofs_delta_obj( fp, obj_size, fpos, depth ): """Read an OBJ_OFS_DELTA object.""" # read the base object offset offset = read_vli_be( fp, offset=True ) base_obj_offset = fpos - offset trace( "- offset = 0x{:x} (relative=0x{:x})", base_obj_offset, offset, depth=depth ) # get the base object ...
REF_DELTA's instead specify the name of their base object, so all we need to do is read it in, then load that object:
def _read_ref_delta_obj( fp, obj_size, fpos, depth ): """Read an OBJ_REF_DELTA object.""" # initialize trace( "Reading OBJ_REF_DELTA object: fpos=0x{:x}", fpos, depth=depth ) # read the base object name base_obj_name = read_obj_name( fp ) trace( "- base_obj_name = {}", base_obj_name, depth=depth ) # get the base object base_obj_type, base_obj_data, _, _ = find_object( base_obj_name ) # reconstruct the delta'fied object return _make_delta_obj( fp, base_obj_type, base_obj_data, obj_size, depth=depth )
Once the base object has been loaded, everything else is exactly the same.
Testing this change is a little tricky, since the repo needs to have multiple .pack files, and have a delta'fied object in one pack use an object in another .pack as its base. This can happen in larger repo's that have been in use for a while, but the code as it stands now might struggle a bit with such repo's, since it's been written to be simple and easy to understand, not efficient. We'll address this later, but if you're interested, you can come back then and check the impact this change has.
Download source
The pack.py script is now able to load objects of any type.