| @@ -6,6 +6,7 @@ use std::{ · 5 unmodified lines |
| 6 | 6 | }; |
| 7 | 7 | |
| 8 | 8 | use git_features::threading::OwnShared; |
| 9 | +use git_hash::oid; |
| 9 | 10 | |
| 10 | 11 | use crate::store::{handle, types, RefreshMode}; |
| 11 | 12 | |
| @@ -25,7 +26,33 @@ pub enum SingleOrMultiIndex { · 13 unmodified lines |
| 25 | 26 | }, |
| 26 | 27 | } |
| 27 | 28 | |
| 28 | | −// pub enum SingleOrMultiIndexRef<'a> {} |
| 29 | +/// A utility to allow looking up pack offsets for a particular pack |
| 30 | +pub enum IntraPackLookup<'a> { |
| 31 | + Single(&'a git_pack::index::File), |
| 32 | + /// the internal pack-id inside of a multi-index for which the lookup is supposed to be. |
| 33 | + /// Used to prevent ref-delta OIDs to, for some reason, point to a different pack. |
| 34 | + Multi { |
| 35 | + index: &'a git_pack::multi_index::File, |
| 36 | + required_pack_index: git_pack::multi_index::PackIndex, |
| 37 | + }, |
| 38 | +} |
| 39 | + |
| 40 | +impl<'a> IntraPackLookup<'a> { |
| 41 | + pub(crate) fn pack_offset_by_id(&self, id: &oid) -> Option<git_pack::data::Offset> { |
| 42 | + match self { |
| 43 | + IntraPackLookup::Single(index) => index |
| 44 | + .lookup(id) |
| 45 | + .map(|entry_index| index.pack_offset_at_index(entry_index)), |
| 46 | + IntraPackLookup::Multi { |
| 47 | + index, |
| 48 | + required_pack_index, |
| 49 | + } => index.lookup(id).and_then(|entry_index| { |
| 50 | + let (pack_index, pack_offset) = index.pack_id_and_pack_offset_at_index(entry_index); |
| 51 | + (pack_index == *required_pack_index).then(|| pack_offset) |
| 52 | + }), |
| 53 | + } |
| 54 | + } |
| 55 | +} |
| 29 | 56 | |
| 30 | 57 | pub struct IndexLookup { |
| 31 | 58 | pub(crate) file: SingleOrMultiIndex, |
| @@ -45,11 +72,12 @@ pub(crate) mod index_lookup { · 13 unmodified lines |
| 45 | 72 | |
| 46 | 73 | use git_hash::oid; |
| 47 | 74 | |
| 75 | + use crate::store::handle::IntraPackLookup; |
| 48 | 76 | use crate::store::{handle, types}; |
| 49 | 77 | |
| 50 | 78 | pub(crate) struct Outcome<'a> { |
| 51 | 79 | pub object_index: handle::IndexForObjectInPack, |
| 52 | | − pub index_file: &'a git_pack::index::File, |
| 80 | + pub index_file: IntraPackLookup<'a>, |
| 53 | 81 | pub pack: &'a mut Option<Arc<git_pack::data::File>>, |
| 54 | 82 | } |
| 55 | 83 | |
| @@ -62,10 +90,9 @@ pub(crate) mod index_lookup { · 6 unmodified lines |
| 62 | 90 | (self.id == pack_id.index).then(|| match &self.file { |
| 63 | 91 | handle::SingleOrMultiIndex::Single { index, .. } => index.iter(), |
| 64 | 92 | handle::SingleOrMultiIndex::Multi { index, .. } => { |
| 65 | | − // TODO: figure out if this could actually not be true all the time. |
| 66 | | − let pack_index = pack_id |
| 67 | | − .multipack_index |
| 68 | | − .expect("multi-pack index must be set if this is a multi-pack"); |
| 93 | + let pack_index = pack_id.multipack_index.expect( |
| 94 | + "BUG: multi-pack index must be set if this is a multi-pack, pack-indices seem unstable", |
| 95 | + ); |
| 69 | 96 | Box::new(index.iter().filter_map(move |e| { |
| 70 | 97 | (e.pack_index == pack_index as u32).then(|| git_pack::index::Entry { |
| 71 | 98 | oid: e.oid, |
| @@ -81,11 +108,10 @@ pub(crate) mod index_lookup { · 9 unmodified lines |
| 81 | 108 | (self.id == pack_id.index).then(move || match &mut self.file { |
| 82 | 109 | handle::SingleOrMultiIndex::Single { data, .. } => data, |
| 83 | 110 | handle::SingleOrMultiIndex::Multi { data, .. } => { |
| 84 | | − // TODO: figure out if this could actually not be true all the time. |
| 85 | | − let pack_index = pack_id |
| 86 | | − .multipack_index |
| 87 | | − .expect("multi-pack index must be set if this is a multi-pack"); |
| 88 | | − &mut data[pack_index] |
| 111 | + let pack_index = pack_id.multipack_index.expect( |
| 112 | + "BUG: multi-pack index must be set if this is a multi-pack, pack-indices seem unstable", |
| 113 | + ); |
| 114 | + &mut data[pack_index as usize] |
| 89 | 115 | } |
| 90 | 116 | }) |
| 91 | 117 | } |
| @@ -130,12 +156,11 @@ pub(crate) mod index_lookup { · 38 unmodified lines |
| 130 | 156 | }, |
| 131 | 157 | pack_offset: index.pack_offset_at_index(idx), |
| 132 | 158 | }, |
| 133 | | − index_file: &**index, |
| 159 | + index_file: IntraPackLookup::Single(&**index), |
| 134 | 160 | pack: data, |
| 135 | 161 | }), |
| 136 | 162 | handle::SingleOrMultiIndex::Multi { index, data } => index.lookup(object_id).map(move |idx| { |
| 137 | | − let (pack_index, pack_offset) = index.pack_offset_and_pack_id_at_index(idx); |
| 138 | | − let pack_index = pack_index as usize; |
| 163 | + let (pack_index, pack_offset) = index.pack_id_and_pack_offset_at_index(idx); |
| 139 | 164 | Outcome { |
| 140 | 165 | object_index: handle::IndexForObjectInPack { |
| 141 | 166 | pack_id: types::PackId { |
| @@ -144,9 +169,11 @@ pub(crate) mod index_lookup { · 2 unmodified lines |
| 144 | 169 | }, |
| 145 | 170 | pack_offset, |
| 146 | 171 | }, |
| 147 | | − // index_file: &**index, |
| 148 | | − index_file: todo!("figure out how to pass different kinds of indices"), |
| 149 | | − pack: &mut data[pack_index], |
| 172 | + index_file: IntraPackLookup::Multi { |
| 173 | + index: &**index, |
| 174 | + required_pack_index: pack_index, |
| 175 | + }, |
| 176 | + pack: &mut data[pack_index as usize], |
| 150 | 177 | } |
| 151 | 178 | }), |
| 152 | 179 | } |