| @@ -43,12 +43,19 @@ where · 42 unmodified lines |
| 43 | | 43 | |
| 44 | /// positive `change` values mean an object grew or was more commonly, was inserted. Negative values | 44 | /// positive `change` values mean an object grew or was more commonly, was inserted. Negative values |
| 45 | /// mean the object shrunk, usually because there header changed from ref-deltas to ofs deltas. | 45 | /// mean the object shrunk, usually because there header changed from ref-deltas to ofs deltas. |
| 46 | fn track_change(&mut self, pack_offset: u64, change: i64, oid: impl Into<Option<ObjectId>>) { | 46 | fn track_change( |
| | 47 | &mut self, |
| | 48 | shifted_pack_offset: u64, |
| | 49 | pack_offset: u64, |
| | 50 | change: i64, |
| | 51 | oid: impl Into<Option<ObjectId>>, |
| | 52 | ) { |
| 47 | if change == 0 { | 53 | if change == 0 { |
| 48 | return; | 54 | return; |
| 49 | } | 55 | } |
| 50 | self.inserted_entry_length_at_offset.push(Change { | 56 | self.inserted_entry_length_at_offset.push(Change { |
| 51 | at_pack_offset: pack_offset, | 57 | shifted_pack_offset, |
| | 58 | pack_offset, |
| 52 | _change_in_bytes: change, | 59 | _change_in_bytes: change, |
| 53 | oid: oid.into().unwrap_or_else(ObjectId::null_sha1), | 60 | oid: oid.into().unwrap_or_else(ObjectId::null_sha1), |
| 54 | }); | 61 | }); |
| @@ -56,13 +63,14 @@ where · 1 unmodified line |
| 56 | } | 63 | } |
| 57 | | 64 | |
| 58 | fn shift_entry_and_point_to_base_by_offset(&mut self, entry: &mut input::Entry, base_distance: u64) { | 65 | fn shift_entry_and_point_to_base_by_offset(&mut self, entry: &mut input::Entry, base_distance: u64) { |
| 59 | entry.pack_offset = self.shift_pack_offset(entry.pack_offset); | 66 | let pack_offset = entry.pack_offset; |
| | 67 | entry.pack_offset = self.shift_pack_offset(pack_offset); |
| 60 | entry.header = Header::OfsDelta { base_distance }; | 68 | entry.header = Header::OfsDelta { base_distance }; |
| 61 | let previous_header_size = entry.header_size; | 69 | let previous_header_size = entry.header_size; |
| 62 | entry.header_size = entry.header.size(entry.decompressed_size) as u16; | 70 | entry.header_size = entry.header.size(entry.decompressed_size) as u16; |
| 63 | | 71 | |
| 64 | let change = entry.header_size as i64 - previous_header_size as i64; | 72 | let change = entry.header_size as i64 - previous_header_size as i64; |
| 65 | self.track_change(entry.pack_offset, change, None); | 73 | self.track_change(entry.pack_offset, pack_offset, change, None); |
| 66 | } | 74 | } |
| 67 | } | 75 | } |
| 68 | | 76 | |
| @@ -93,7 +101,12 @@ where · 24 unmodified lines |
| 93 | Ok(e) => e, | 101 | Ok(e) => e, |
| 94 | }; | 102 | }; |
| 95 | entry.pack_offset = self.shift_pack_offset(current_pack_offset); | 103 | entry.pack_offset = self.shift_pack_offset(current_pack_offset); |
| 96 | self.track_change(entry.pack_offset, entry.bytes_in_pack() as i64, base_id); | 104 | self.track_change( |
| | 105 | entry.pack_offset, |
| | 106 | current_pack_offset, |
| | 107 | entry.bytes_in_pack() as i64, |
| | 108 | base_id, |
| | 109 | ); |
| 97 | entry | 110 | entry |
| 98 | } | 111 | } |
| 99 | None => { | 112 | None => { |
| @@ -109,7 +122,8 @@ where · 9 unmodified lines |
| 109 | Some(Ok(base_entry)) | 122 | Some(Ok(base_entry)) |
| 110 | } | 123 | } |
| 111 | Some(base_entry) => { | 124 | Some(base_entry) => { |
| 112 | let base_distance = self.shift_pack_offset(entry.pack_offset) - base_entry.at_pack_offset; | 125 | let base_distance = |
| | 126 | self.shift_pack_offset(entry.pack_offset) - base_entry.shifted_pack_offset; |
| 113 | self.shift_entry_and_point_to_base_by_offset(&mut entry, base_distance); | 127 | self.shift_entry_and_point_to_base_by_offset(&mut entry, base_distance); |
| 114 | Some(Ok(entry)) | 128 | Some(Ok(entry)) |
| 115 | } | 129 | } |
| @@ -117,10 +131,27 @@ where · 1 unmodified line |
| 117 | } | 131 | } |
| 118 | _ => { | 132 | _ => { |
| 119 | if self.inserted_entries_length_in_bytes != 0 { | 133 | if self.inserted_entries_length_in_bytes != 0 { |
| 120 | entry.pack_offset = self.shift_pack_offset(entry.pack_offset); | 134 | if let Header::OfsDelta { base_distance } = entry.header { |
| 121 | if let Header::OfsDelta { base_distance: _ } = entry.header { | 135 | let base_pack_offset = entry |
| 122 | // self.inserted_entry_length_at_offset.partition_point() | 136 | .pack_offset |
| 123 | // todo!("add all objects that have been added since to the delta offset, compute new size and adjust") | 137 | .checked_sub(base_distance) |
| | 138 | .expect("distance to be in range of pack"); |
| | 139 | entry.pack_offset = self.shift_pack_offset(entry.pack_offset); |
| | 140 | dbg!(base_pack_offset, entry.pack_offset); |
| | 141 | match self |
| | 142 | .inserted_entry_length_at_offset |
| | 143 | .binary_search_by_key(&base_pack_offset, |c| c.pack_offset) |
| | 144 | { |
| | 145 | Ok(index) => { |
| | 146 | dbg!(index, &self.inserted_entry_length_at_offset[index..]); |
| | 147 | todo!("we point exactly at an entry that changed, but this one might be inserted") |
| | 148 | } |
| | 149 | Err(_index) => { |
| | 150 | todo!("close, aggregate the size changes since then to know where we are pointing") |
| | 151 | } |
| | 152 | } |
| | 153 | } else { |
| | 154 | entry.pack_offset = self.shift_pack_offset(entry.pack_offset); |
| 124 | } | 155 | } |
| 125 | } | 156 | } |
| 126 | Some(Ok(entry)) | 157 | Some(Ok(entry)) |
| @@ -137,7 +168,8 @@ where · 10 unmodified lines |
| 137 | | 168 | |
| 138 | #[derive(Debug)] | 169 | #[derive(Debug)] |
| 139 | struct Change { | 170 | struct Change { |
| 140 | at_pack_offset: u64, | 171 | pack_offset: u64, |
| | 172 | shifted_pack_offset: u64, |
| 141 | _change_in_bytes: i64, | 173 | _change_in_bytes: i64, |
| 142 | oid: ObjectId, | 174 | oid: ObjectId, |
| 143 | } | 175 | } |