| @@ -1,10 +1,12 @@ |
| 1 | 1 | mod lookup_ref_delta_objects { |
| 2 | + use crate::pack::hex_to_id; |
| 2 | 3 | use git_hash::ObjectId; |
| 3 | 4 | use git_pack::data::{self, entry::Header, input, LookupRefDeltaObjectsIter}; |
| 4 | 5 | |
| 5 | 6 | const D_A: &[u8] = b"a"; |
| 6 | 7 | const D_B: &[u8] = b"bb"; |
| 7 | 8 | const D_C: &[u8] = b"ccc"; |
| 9 | + const D_D: &[u8] = b"dddd"; |
| 8 | 10 | |
| 9 | 11 | fn base() -> Header { |
| 10 | 12 | Header::Blob |
| @@ -63,21 +65,25 @@ mod lookup_ref_delta_objects { · 52 unmodified lines |
| 63 | 65 | |
| 64 | 66 | #[test] |
| 65 | 67 | fn ref_deltas_have_their_base_injected_if_not_done_before_and_all_future_entries_are_offset() { |
| 66 | | − let first = entry(base(), D_C); |
| 67 | | − let mut inserted = entry(base(), D_B); |
| 68 | + let first_id = hex_to_id("0000000000000000000000000000000000000001"); |
| 69 | + let second_id = hex_to_id("0000000000000000000000000000000000000002"); |
| 70 | + let first = entry(delta_ref(first_id), D_A); |
| 71 | + |
| 72 | + let inserted_data = D_D; |
| 73 | + let mut inserted = entry(base(), inserted_data); |
| 68 | 74 | let mut last_entry = entry(base(), D_C); |
| 69 | 75 | // todo: let's have an ofs delta point at the altered entry, maybe even last_entry |
| 70 | 76 | let input = compute_offsets(vec![ |
| 71 | 77 | first.clone(), |
| 72 | | − entry(delta_ref(ObjectId::null_sha1()), D_A), |
| 78 | + entry(delta_ref(second_id), D_B), |
| 73 | 79 | last_entry.clone(), |
| 74 | 80 | ]); |
| 75 | 81 | |
| 76 | 82 | let mut calls = 0; |
| 77 | 83 | let actual = LookupRefDeltaObjectsIter::new(into_results_iter(input), |_oid, buf| { |
| 78 | 84 | calls += 1; |
| 79 | | − buf.resize(D_B.len(), 0); |
| 80 | | − buf.copy_from_slice(&D_B); |
| 85 | + buf.resize(inserted_data.len(), 0); |
| 86 | + buf.copy_from_slice(inserted_data); |
| 81 | 87 | Some(data::Object { |
| 82 | 88 | kind: git_object::Kind::Blob, |
| 83 | 89 | data: buf.as_slice(), |
| @@ -87,28 +93,43 @@ mod lookup_ref_delta_objects { · 3 unmodified lines |
| 87 | 93 | .collect::<Result<Vec<_>, _>>() |
| 88 | 94 | .unwrap(); |
| 89 | 95 | |
| 90 | | − assert_eq!(calls, 1, "there is only one object to replace"); |
| 91 | | − assert_eq!(actual.len(), 4, "one object was inserted"); |
| 92 | | − assert_eq!(&actual[0], &first, "first object is unchanged"); |
| 96 | + assert_eq!(calls, 2, "there is only two objects to replace"); |
| 97 | + assert_eq!(actual.len(), 5, "two object was inserted"); |
| 98 | + |
| 99 | + assert_eq!(&actual[0], &inserted, "first object is inserted one"); |
| 100 | + |
| 101 | + let altered = &actual[1]; |
| 102 | + assert_eq!( |
| 103 | + extract_delta_offset(&altered.header), |
| 104 | + inserted.bytes_in_pack(), |
| 105 | + "former first entry is now an offset delta pointing at the item before" |
| 106 | + ); |
| 107 | + assert_eq!( |
| 108 | + altered.pack_offset, |
| 109 | + inserted.bytes_in_pack(), |
| 110 | + "the pack offset was adjusted to accommodate for the inserted object" |
| 111 | + ); |
| 93 | 112 | |
| 94 | | − inserted.pack_offset += first.bytes_in_pack(); |
| 95 | | − assert_eq!(&actual[1], &inserted, "second object is the inserted one"); |
| 113 | + inserted.pack_offset = inserted.bytes_in_pack() + altered.bytes_in_pack(); |
| 114 | + assert_eq!(&actual[2], &inserted, "third object is a newly inserted one, too"); |
| 96 | 115 | |
| 97 | | − let altered = &actual[2]; |
| 116 | + let first_altered_len = altered.bytes_in_pack(); |
| 117 | + let altered = &actual[3]; |
| 98 | 118 | assert_eq!( |
| 99 | 119 | extract_delta_offset(&altered.header), |
| 100 | 120 | inserted.bytes_in_pack(), |
| 101 | | − "former second entry is now an offset delta pointing at the item before" |
| 121 | + "former second entry is now an offset delta pointing at the inserted item before" |
| 102 | 122 | ); |
| 103 | 123 | assert_eq!( |
| 104 | 124 | altered.pack_offset, |
| 105 | | − first.bytes_in_pack() + inserted.bytes_in_pack(), |
| 106 | | − "the pack offset was adjusted to accommodate for the first and inserted object" |
| 125 | + inserted.bytes_in_pack() + first_altered_len + inserted.bytes_in_pack(), |
| 126 | + "the pack offset was adjusted to accommodate for preceding objects" |
| 107 | 127 | ); |
| 108 | 128 | |
| 109 | | − last_entry.pack_offset = first.bytes_in_pack() + inserted.bytes_in_pack() + altered.bytes_in_pack(); |
| 129 | + last_entry.pack_offset = |
| 130 | + inserted.bytes_in_pack() + first_altered_len + inserted.bytes_in_pack() + altered.bytes_in_pack(); |
| 110 | 131 | assert_eq!( |
| 111 | | − &actual[3], &last_entry, |
| 132 | + &actual[4], &last_entry, |
| 112 | 133 | "the last entry was offset and is otherwise unchanged" |
| 113 | 134 | ); |
| 114 | 135 | } |