@@ -17,6 +17,15 @@ pub mod verify {
17
17
quick_error ! {
18
18
#[ derive( Debug ) ]
19
19
pub enum Error {
20
+ MissingTreeDirectory { parent_id: git_hash:: ObjectId , entry_id: git_hash:: ObjectId , name: BString } {
21
+ display( "The entry {} at path '{}' in parent tree {} wasn't found in the nodes children, making it incomplete" , entry_id, name, parent_id)
22
+ }
23
+ TreeNodeNotFound { oid: git_hash:: ObjectId } {
24
+ display( "The tree with id {} wasn't found in the object database" , oid)
25
+ }
26
+ TreeNodeChildcountMismatch { oid: git_hash:: ObjectId , expected_childcount: usize , actual_childcount: usize } {
27
+ display( "The tree with id {} should have {} children, but its cached representation had {} of them" , oid, expected_childcount, actual_childcount)
28
+ }
20
29
RootWithName { name: BString } {
21
30
display( "The root tree was named '{}', even though it should be empty" , name)
22
31
}
@@ -31,23 +40,25 @@ pub mod verify {
31
40
}
32
41
33
42
impl Tree {
34
- pub fn verify ( & self ) -> Result < ( ) , verify:: Error > {
35
- fn verify_recursive ( parent_id : git_hash:: ObjectId , children : & [ Tree ] ) -> Result < Option < u32 > , verify:: Error > {
43
+ pub fn verify < F > ( & self , use_find : bool , mut find : F ) -> Result < ( ) , verify:: Error >
44
+ where
45
+ F : for < ' a > FnMut ( & git_hash:: oid , & ' a mut Vec < u8 > ) -> Option < git_object:: TreeRefIter < ' a > > ,
46
+ {
47
+ fn verify_recursive < F > (
48
+ parent_id : git_hash:: ObjectId ,
49
+ children : & [ Tree ] ,
50
+ mut find_buf : Option < & mut Vec < u8 > > ,
51
+ find : & mut F ,
52
+ ) -> Result < Option < u32 > , verify:: Error >
53
+ where
54
+ F : for < ' a > FnMut ( & git_hash:: oid , & ' a mut Vec < u8 > ) -> Option < git_object:: TreeRefIter < ' a > > ,
55
+ {
36
56
if children. is_empty ( ) {
37
57
return Ok ( None ) ;
38
58
}
39
59
let mut entries = 0 ;
40
60
let mut prev = None :: < & Tree > ;
41
61
for child in children {
42
- let actual_num_entries = verify_recursive ( child. id , & child. children ) ?;
43
- if let Some ( actual) = actual_num_entries {
44
- if actual > child. num_entries {
45
- return Err ( verify:: Error :: EntriesCount {
46
- actual,
47
- expected : child. num_entries ,
48
- } ) ;
49
- }
50
- }
51
62
entries += child. num_entries ;
52
63
if let Some ( prev) = prev {
53
64
if prev. name . cmp ( & child. name ) != Ordering :: Less {
@@ -60,6 +71,43 @@ impl Tree {
60
71
}
61
72
prev = Some ( child) ;
62
73
}
74
+ if let Some ( buf) = find_buf. as_mut ( ) {
75
+ let tree_entries =
76
+ find ( & parent_id, * buf) . ok_or_else ( || verify:: Error :: TreeNodeNotFound { oid : parent_id } ) ?;
77
+ let mut num_entries = 0 ;
78
+ for entry in tree_entries
79
+ . filter_map ( Result :: ok)
80
+ . filter ( |e| e. mode == git_object:: tree:: EntryMode :: Tree )
81
+ {
82
+ children
83
+ . binary_search_by ( |e| e. name . as_bstr ( ) . cmp ( & entry. filename ) )
84
+ . map_err ( |_| verify:: Error :: MissingTreeDirectory {
85
+ parent_id,
86
+ entry_id : entry. oid . to_owned ( ) ,
87
+ name : entry. filename . to_owned ( ) ,
88
+ } ) ?;
89
+ num_entries += 1 ;
90
+ }
91
+
92
+ if num_entries != children. len ( ) {
93
+ return Err ( verify:: Error :: TreeNodeChildcountMismatch {
94
+ oid : parent_id,
95
+ expected_childcount : num_entries,
96
+ actual_childcount : children. len ( ) ,
97
+ } ) ;
98
+ }
99
+ }
100
+ for child in children {
101
+ let actual_num_entries = verify_recursive ( child. id , & child. children , find_buf. as_deref_mut ( ) , find) ?;
102
+ if let Some ( actual) = actual_num_entries {
103
+ if actual > child. num_entries {
104
+ return Err ( verify:: Error :: EntriesCount {
105
+ actual,
106
+ expected : child. num_entries ,
107
+ } ) ;
108
+ }
109
+ }
110
+ }
63
111
Ok ( entries. into ( ) )
64
112
}
65
113
@@ -69,7 +117,8 @@ impl Tree {
69
117
} ) ;
70
118
}
71
119
72
- let declared_entries = verify_recursive ( self . id , & self . children ) ?;
120
+ let mut buf = Vec :: new ( ) ;
121
+ let declared_entries = verify_recursive ( self . id , & self . children , use_find. then ( || & mut buf) , & mut find) ?;
73
122
if let Some ( actual) = declared_entries {
74
123
if actual > self . num_entries {
75
124
return Err ( verify:: Error :: EntriesCount {
0 commit comments