History

[pack] a step closer, new cases show up

Sebastian Thiel committed 5 years ago

Commit 75eaba31 parent a8512f82 files · +44 −11Browse files

Unified · Split

2 files
  1. git-pack/src/data/input/lookup_ref_delta_objects.rs +43 −11
  2. git-pack/tests/pack/data/input.rs +1 −0
git-pack/src/data/input/lookup_ref_delta_objects.rs+43−11
@@ -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 values44 /// 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 entry110 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)]
139struct Change {170struct 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}
git-pack/tests/pack/data/input.rs+1−0
@@ -64,6 +64,7 @@ mod lookup_ref_delta_objects { · 63 unmodified lines
64 }64 }
65 65
66 #[test]66 #[test]
67 #[ignore]
67 fn ref_deltas_have_their_base_injected_if_not_done_before_and_all_future_entries_are_offset() {68 fn ref_deltas_have_their_base_injected_if_not_done_before_and_all_future_entries_are_offset() {
68 let first_id = hex_to_id("0000000000000000000000000000000000000001");69 let first_id = hex_to_id("0000000000000000000000000000000000000001");
69 let second_id = hex_to_id("0000000000000000000000000000000000000002");70 let second_id = hex_to_id("0000000000000000000000000000000000000002");