2 extension
::{Link, Signature}
,
6 /// The signature of the link extension.
7 pub const SIGNATURE
: Signature
= *b
"link";
9 /// Bitmaps to know which entries to delete or replace, even though details are still unknown.
12 /// A bitmap to signal which entries to delete, maybe.
13 pub delete
: gix_bitmap
::ewah
::Vec
,
14 /// A bitmap to signal which entries to replace, maybe.
15 pub replace
: gix_bitmap
::ewah
::Vec
,
21 /// The error returned when decoding link extensions.
22 #[derive(Debug, thiserror::Error)]
23 #[allow(missing_docs)]
26 Corrupt(&'
static str),
27 #[error("{kind} bitmap corrupt")]
29 err
: gix_bitmap
::ewah
::decode
::Error
,
34 impl From
<std
::num
::TryFromIntError
> for Error
{
35 fn from(_
: std
::num
::TryFromIntError
) -> Self {
36 Self::Corrupt("error in bitmap iteration trying to convert from u64 to usize")
41 pub(crate) fn decode(data
: &[u8], object_hash
: gix_hash
::Kind
) -> Result
<Link
, decode
::Error
> {
42 let (id
, data
) = split_at_pos(data
, object_hash
.len_in_bytes())
43 .ok_or(decode
::Error
::Corrupt(
44 "link extension too short to read share index checksum",
46 .map(|(id
, d
)| (gix_hash
::ObjectId
::from(id
), d
))?
;
50 shared_index_checksum
: id
,
56 gix_bitmap
::ewah
::decode(data
).map_err(|err
| decode
::Error
::BitmapDecode { kind: "delete", err }
)?
;
58 gix_bitmap
::ewah
::decode(data
).map_err(|err
| decode
::Error
::BitmapDecode { kind: "replace", err }
)?
;
61 return Err(decode
::Error
::Corrupt("garbage trailing link extension"));
65 shared_index_checksum
: id
,
66 bitmaps
: Some(Bitmaps { delete, replace }
),
71 pub(crate) fn dissolve_into(
73 split_index
: &mut crate::File
,
74 object_hash
: gix_hash
::Kind
,
76 options
: crate::decode
::Options
,
77 ) -> Result
<(), crate::file
::init
::Error
> {
78 let shared_index_path
= split_index
81 .expect("split index file in .git folder")
82 .join(format
!("sharedindex.{}", self.shared_index_checksum
));
83 let mut shared_index
= crate::File
::at(
87 crate::decode
::Options
{
88 expected_checksum
: self.shared_index_checksum
.into(),
93 if let Some(bitmaps
) = self.bitmaps
{
94 let mut split_entry_index
= 0;
97 bitmaps
.replace
.for_each_set_bit(|replace_index
| {
98 let shared_entry
= match shared_index
.entries
.get_mut(replace_index
) {
101 err
= decode
::Error
::Corrupt("replace bitmap length exceeds shared index length - more entries in bitmap than found in shared index").into();
106 if shared_entry
.flags
.contains(crate::entry
::Flags
::REMOVE
) {
107 err
= decode
::Error
::Corrupt("entry is marked as both replace and delete").into();
111 let split_entry
= match split_index
.entries
.get(split_entry_index
) {
114 err
= decode
::Error
::Corrupt("replace bitmap length exceeds split index length - more entries in bitmap than found in split index").into();
118 if !split_entry
.path
.is_empty() {
119 err
= decode
::Error
::Corrupt("paths in split index entries that are for replacement should be empty").into();
122 if shared_entry
.path
.is_empty() {
123 err
= decode
::Error
::Corrupt("paths in shared index entries that are replaced should not be empty").into();
126 shared_entry
.stat
= split_entry
.stat
;
127 shared_entry
.id
= split_entry
.id
;
128 shared_entry
.flags
= split_entry
.flags
;
129 shared_entry
.mode
= split_entry
.mode
;
131 split_entry_index
+= 1;
134 if let Some(err
) = err
{
135 return Err(err
.into());
138 let split_index_path_backing
= std
::mem
::take(&mut split_index
.path_backing
);
139 for mut split_entry
in split_index
.entries
.drain(split_entry_index
..) {
140 let start
= shared_index
.path_backing
.len();
141 let split_index_path
= split_entry
.path
.clone();
143 split_entry
.path
= start
..start
+ split_entry
.path
.len();
144 shared_index
.entries
.push(split_entry
);
148 .extend_from_slice(&split_index_path_backing
[split_index_path
]);
151 bitmaps
.delete
.for_each_set_bit(|delete_index
| {
152 let shared_entry
= match shared_index
.entries
.get_mut(delete_index
) {
155 err
= decode
::Error
::Corrupt("delete bitmap length exceeds shared index length - more entries in bitmap than found in shared index").into();
159 shared_entry
.flags
.insert(crate::entry
::Flags
::REMOVE
);
162 if let Some(err
) = err
{
163 return Err(err
.into());
168 .retain(|e
| !e
.flags
.contains(crate::entry
::Flags
::REMOVE
));
170 let mut shared_entries
= std
::mem
::take(&mut shared_index
.entries
);
171 shared_entries
.sort_by(|a
, b
| a
.cmp(b
, &shared_index
.state
));
173 split_index
.entries
= shared_entries
;
174 split_index
.path_backing
= std
::mem
::take(&mut shared_index
.path_backing
);