1
1
use crate :: pack;
2
+ use crate :: types:: IndexAndPacks ;
2
3
use git_features:: progress:: Progress ;
3
- use std:: sync:: atomic:: AtomicBool ;
4
+ use std:: ops:: Deref ;
5
+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
4
6
5
7
#[ allow( missing_docs, unused) ]
6
8
@@ -13,9 +15,19 @@ pub mod integrity {
13
15
#[ allow( missing_docs) ]
14
16
pub enum Error {
15
17
#[ error( transparent) ]
16
- MultiIndex ( #[ from] pack:: index:: traverse:: Error < pack:: multi_index:: verify:: integrity:: Error > ) ,
18
+ MultiIndexIntegrity ( #[ from] pack:: index:: traverse:: Error < pack:: multi_index:: verify:: integrity:: Error > ) ,
17
19
#[ error( transparent) ]
18
- Index ( #[ from] pack:: index:: traverse:: Error < pack:: index:: verify:: integrity:: Error > ) ,
20
+ IndexIntegrity ( #[ from] pack:: index:: traverse:: Error < pack:: index:: verify:: integrity:: Error > ) ,
21
+ #[ error( transparent) ]
22
+ IndexOpen ( #[ from] pack:: index:: init:: Error ) ,
23
+ #[ error( transparent) ]
24
+ MultiIndexOpen ( #[ from] pack:: multi_index:: init:: Error ) ,
25
+ #[ error( transparent) ]
26
+ PackOpen ( #[ from] pack:: data:: init:: Error ) ,
27
+ #[ error( transparent) ]
28
+ InitializeODB ( #[ from] crate :: store:: load_index:: Error ) ,
29
+ #[ error( "The disk on state changed while performing the operation, and we observed the change." ) ]
30
+ NeedsRetryDueToChangeOnDisk ,
19
31
}
20
32
21
33
/// Returned by [`Store::verify_integrity()`][crate::Store::verify_integrity()].
@@ -34,15 +46,97 @@ impl super::Store {
34
46
/// This does, however, include all alternates.
35
47
pub fn verify_integrity < C , P , F > (
36
48
& self ,
37
- _progress : P ,
38
- _should_interrupt : & AtomicBool ,
39
- _options : pack:: index:: verify:: integrity:: Options < F > ,
40
- ) -> Result < integrity:: Outcome < P > , pack :: index :: traverse :: Error < integrity:: Error > >
49
+ mut progress : P ,
50
+ should_interrupt : & AtomicBool ,
51
+ options : pack:: index:: verify:: integrity:: Options < F > ,
52
+ ) -> Result < integrity:: Outcome < P > , integrity:: Error >
41
53
where
42
54
P : Progress ,
43
55
C : pack:: cache:: DecodeEntry ,
44
56
F : Fn ( ) -> C + Send + Clone ,
45
57
{
46
- todo ! ( )
58
+ let mut index = self . index . load ( ) ;
59
+ if !index. is_initialized ( ) {
60
+ self . consolidate_with_disk_state ( false ) ?;
61
+ index = self . index . load ( ) ;
62
+ assert ! (
63
+ index. is_initialized( ) ,
64
+ "BUG: after consolidating successfully, we have an initialized index"
65
+ )
66
+ }
67
+
68
+ progress. init (
69
+ Some ( index. slot_indices . len ( ) ) ,
70
+ git_features:: progress:: count ( "pack indices" ) ,
71
+ ) ;
72
+ let mut statistics = Vec :: new ( ) ;
73
+ for slot_index in & index. slot_indices {
74
+ let slot = & self . files [ * slot_index] ;
75
+ if slot. generation . load ( Ordering :: SeqCst ) != index. generation {
76
+ return Err ( integrity:: Error :: NeedsRetryDueToChangeOnDisk ) ;
77
+ }
78
+ let files = slot. files . load ( ) ;
79
+ let files = Option :: as_ref ( & files) . ok_or ( integrity:: Error :: NeedsRetryDueToChangeOnDisk ) ?;
80
+
81
+ match files {
82
+ IndexAndPacks :: Index ( bundle) => {
83
+ let index;
84
+ let index = match bundle. index . loaded ( ) {
85
+ Some ( index) => index. deref ( ) ,
86
+ None => {
87
+ index = pack:: index:: File :: at ( bundle. index . path ( ) , self . object_hash ) ?;
88
+ & index
89
+ }
90
+ } ;
91
+ let pack;
92
+ let data = match bundle. data . loaded ( ) {
93
+ Some ( pack) => pack. deref ( ) ,
94
+ None => {
95
+ pack = pack:: data:: File :: at ( bundle. data . path ( ) , self . object_hash ) ?;
96
+ & pack
97
+ }
98
+ } ;
99
+ let outcome = index. verify_integrity (
100
+ Some ( pack:: index:: verify:: PackContext {
101
+ data,
102
+ options : options. clone ( ) ,
103
+ } ) ,
104
+ progress. add_child ( "Checking integrity" ) ,
105
+ should_interrupt,
106
+ ) ?;
107
+ statistics. push (
108
+ outcome
109
+ . pack_traverse_statistics
110
+ . expect ( "pack provided so there are stats" ) ,
111
+ ) ;
112
+ }
113
+ IndexAndPacks :: MultiIndex ( bundle) => {
114
+ let index;
115
+ let index = match bundle. multi_index . loaded ( ) {
116
+ Some ( index) => index. deref ( ) ,
117
+ None => {
118
+ index = pack:: multi_index:: File :: at ( bundle. multi_index . path ( ) ) ?;
119
+ & index
120
+ }
121
+ } ;
122
+ let outcome = index. verify_integrity (
123
+ progress. add_child ( "Checking integrity" ) ,
124
+ should_interrupt,
125
+ options. clone ( ) ,
126
+ ) ?;
127
+ statistics. extend ( outcome. pack_traverse_statistics ) ;
128
+ }
129
+ }
130
+ progress. inc ( ) ;
131
+ }
132
+
133
+ for _loose_db in & * index. loose_dbs {
134
+ // TODO: impl verify integrity for loose object databases
135
+ }
136
+
137
+ Ok ( integrity:: Outcome {
138
+ pack_traverse_statistics : statistics,
139
+ progress,
140
+ } )
47
141
}
48
142
}
0 commit comments