Skip to content

Commit 6169325

Browse files
committed
fix: gix-index prefix matching should now work correctly with conflicting files.
It was done in a rush and lacks a lot of tests. At least now it has a greater chance of working, as tests that would truly validate this are still missing for a lack of test date. It can be produced with `git update-index`, but it wasn't yet worth it.
1 parent 71b7422 commit 6169325

File tree

1 file changed

+27
-3
lines changed

1 file changed

+27
-3
lines changed

gix-index/src/access/mod.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,30 @@ impl State {
8484
self.entry_index_by_idx_and_stage(path, idx, stage, stage_cmp)
8585
}
8686

87+
/// Walk as far in `direction` as possible, with [`Ordering::Greater`] towards higher stages, and [`Ordering::Less`]
88+
/// towards lower stages, and return the lowest or highest seen stage.
89+
/// Return `None` if there is no greater or smaller stage.
90+
fn walk_entry_stages(&self, path: &BStr, base: usize, direction: Ordering) -> Option<usize> {
91+
match direction {
92+
Ordering::Greater => self
93+
.entries
94+
.get(base + 1..)?
95+
.iter()
96+
.enumerate()
97+
.take_while(|(_, e)| e.path(self) == path)
98+
.last()
99+
.map(|(idx, _)| base + 1 + idx),
100+
Ordering::Equal => Some(base),
101+
Ordering::Less => self.entries[..base]
102+
.iter()
103+
.enumerate()
104+
.rev()
105+
.take_while(|(_, e)| e.path(self) == path)
106+
.last()
107+
.map(|(idx, _)| idx),
108+
}
109+
}
110+
87111
fn entry_index_by_idx_and_stage(
88112
&self,
89113
path: &BStr,
@@ -173,13 +197,13 @@ impl State {
173197
let low_entry = &self.entries[low];
174198
if low_entry.stage() != 0 {
175199
low = self
176-
.entry_index_by_idx_and_stage(low_entry.path(self), low, 0, low_entry.stage().cmp(&0))
200+
.walk_entry_stages(low_entry.path(self), low, Ordering::Less)
177201
.unwrap_or(low);
178202
}
179203
if let Some(high_entry) = self.entries.get(high) {
180-
if low_entry.stage() != 2 {
204+
if high_entry.stage() != 3 {
181205
high = self
182-
.entry_index_by_idx_and_stage(high_entry.path(self), high, 2, high_entry.stage().cmp(&2))
206+
.walk_entry_stages(high_entry.path(self), high, Ordering::Greater)
183207
.unwrap_or(high);
184208
}
185209
}

0 commit comments

Comments
 (0)