Skip to content

Commit 2d101eb

Browse files
committed
Verify entry order (#293)
1 parent 017e915 commit 2d101eb

File tree

5 files changed

+70
-7
lines changed

5 files changed

+70
-7
lines changed

git-index/src/entry.rs

+21
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,26 @@ mod access {
140140
pub fn path<'a>(&self, state: &'a State) -> &'a BStr {
141141
(&state.path_backing[self.path.clone()]).as_bstr()
142142
}
143+
144+
pub fn stage(&self) -> u32 {
145+
self.flags.stage()
146+
}
147+
}
148+
}
149+
150+
mod _impls {
151+
use crate::{Entry, State};
152+
use std::cmp::Ordering;
153+
154+
impl Entry {
155+
pub fn cmp(&self, other: &Self, state: &State) -> Ordering {
156+
let lhs = self.path(state);
157+
let rhs = other.path(state);
158+
let common_len = lhs.len().min(rhs.len());
159+
lhs[..common_len]
160+
.cmp(&rhs[..common_len])
161+
.then_with(|| lhs.len().cmp(&rhs.len()))
162+
.then_with(|| self.stage().cmp(&other.stage()))
163+
}
143164
}
144165
}

git-index/src/file/verify.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::File;
22
use std::sync::atomic::AtomicBool;
33

4-
pub mod error {
4+
mod error {
55
use quick_error::quick_error;
66

77
quick_error! {

git-index/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ mod access;
1515

1616
pub mod decode;
1717

18+
pub mod verify;
19+
1820
/// All known versions of a git index file.
1921
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
2022
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]

git-index/src/verify.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use crate::State;
2+
use std::cmp::Ordering;
3+
4+
pub mod entries {
5+
use bstr::BString;
6+
use quick_error::quick_error;
7+
8+
quick_error! {
9+
#[derive(Debug)]
10+
pub enum Error {
11+
OutOfOrder { current_index: usize, current_path: BString, current_stage: u8, previous_path: BString, previous_stage: u8 } {
12+
display("todo")
13+
}
14+
}
15+
}
16+
}
17+
18+
impl State {
19+
pub fn verify_entries(&self) -> Result<(), entries::Error> {
20+
let mut previous = None::<&crate::Entry>;
21+
for (idx, entry) in self.entries.iter().enumerate() {
22+
if let Some(prev) = previous {
23+
if prev.cmp(entry, self) != Ordering::Less {
24+
return Err(entries::Error::OutOfOrder {
25+
current_index: idx,
26+
current_path: entry.path(self).into(),
27+
current_stage: entry.flags.stage() as u8,
28+
previous_path: prev.path(self).into(),
29+
previous_stage: prev.flags.stage() as u8,
30+
});
31+
}
32+
}
33+
previous = Some(entry);
34+
}
35+
Ok(())
36+
}
37+
}

git-index/tests/index/file/mod.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,24 @@ mod init {
55
use git_index::{entry, Version};
66
use git_testtools::hex_to_id;
77

8+
fn verify(index: git_index::File) -> git_index::File {
9+
index.verify_integrity().unwrap();
10+
index.verify_entries().unwrap();
11+
index
12+
}
13+
814
fn loose_file(name: &str) -> git_index::File {
915
let path = git_testtools::fixture_path(Path::new("loose_index").join(name).with_extension("git-index"));
1016
let file = git_index::File::at(path, git_index::decode::Options::default()).unwrap();
11-
file.verify_integrity().unwrap();
12-
file
17+
verify(file)
1318
}
1419
fn file(name: &str) -> git_index::File {
1520
let file = git_index::File::at(crate::fixture_path(name), git_index::decode::Options::default()).unwrap();
16-
file.verify_integrity().unwrap();
17-
file
21+
verify(file)
1822
}
1923
fn file_opt(name: &str, opts: git_index::decode::Options) -> git_index::File {
2024
let file = git_index::File::at(crate::fixture_path(name), opts).unwrap();
21-
file.verify_integrity().unwrap();
22-
file
25+
verify(file)
2326
}
2427

2528
#[test]

0 commit comments

Comments
 (0)