@@ -2,11 +2,7 @@ use anyhow::{anyhow, Result};
2
2
use git_features:: progress:: { self , Progress } ;
3
3
use git_object:: { owned, HashKind } ;
4
4
use git_odb:: { loose, pack, Write } ;
5
- use std:: {
6
- fs,
7
- io:: { self , Read } ,
8
- path:: { Path , PathBuf } ,
9
- } ;
5
+ use std:: { fs, io:: Read , path:: Path } ;
10
6
11
7
#[ derive( PartialEq , Debug ) ]
12
8
pub enum SafetyCheck {
@@ -79,8 +75,11 @@ quick_error! {
79
75
ObjectEncodeMismatch ( kind: git_object:: Kind , actual: owned:: Id , expected: owned:: Id ) {
80
76
display( "{} object {} wasn't re-encoded without change - new hash is {}" , kind, expected, actual)
81
77
}
82
- RemoveFile ( err: io:: Error , index: PathBuf , data: PathBuf ) {
83
- display( "Failed to delete pack index file at '{} or data file at '{}'" , index. display( ) , data. display( ) )
78
+ WrittenFileMissing ( id: owned:: Id ) {
79
+ display( "The recently written file for loose object {} could not be found" , id)
80
+ }
81
+ WrittenFileCorrupt ( err: loose:: db:: locate:: Error , id: owned:: Id ) {
82
+ display( "The recently written file for loose object {} cold not be read" , id)
84
83
source( err)
85
84
}
86
85
}
@@ -124,10 +123,12 @@ impl OutputWriter {
124
123
}
125
124
}
126
125
126
+ #[ derive( Default ) ]
127
127
pub struct Context {
128
128
pub thread_limit : Option < usize > ,
129
129
pub delete_pack : bool ,
130
130
pub sink_compress : bool ,
131
+ pub verify : bool ,
131
132
}
132
133
133
134
pub fn pack_or_pack_index < P > (
@@ -139,6 +140,7 @@ pub fn pack_or_pack_index<P>(
139
140
thread_limit,
140
141
delete_pack,
141
142
sink_compress,
143
+ verify,
142
144
} : Context ,
143
145
) -> Result < ( ) >
144
146
where
@@ -183,22 +185,34 @@ where
183
185
{
184
186
let object_path = object_path. map ( |p| p. as_ref ( ) . to_owned ( ) ) ;
185
187
move || {
186
- let out = OutputWriter :: new ( object_path. clone ( ) , sink_compress) ;
187
- move |object_kind, buf, index_entry, _entry_stats, progress| {
188
- let written_id = out
189
- . write_buf ( object_kind, buf, HashKind :: Sha1 )
190
- . map_err ( |err| Error :: Write ( Box :: new ( err) as Box < dyn std:: error:: Error + Send + Sync > , object_kind, index_entry. oid ) )
191
- . map_err ( |err| Box :: new ( err) as Box < dyn std:: error:: Error + Send + Sync > ) ?;
192
- if written_id != index_entry. oid {
193
- if let git_object:: Kind :: Tree = object_kind {
194
- progress. info ( format ! ( "The tree in pack named {} was written as {} due to modes 100664 and 100640 rewritten as 100644." , index_entry. oid, written_id) ) ;
195
- } else {
196
- return Err ( Box :: new ( Error :: ObjectEncodeMismatch ( object_kind, index_entry. oid , written_id) ) )
197
- }
188
+ let out = OutputWriter :: new ( object_path. clone ( ) , sink_compress) ;
189
+ let object_verifier = if verify {
190
+ object_path. as_ref ( ) . map ( |p| loose:: Db :: at ( p) )
191
+ } else {
192
+ None
193
+ } ;
194
+ move |object_kind, buf, index_entry, _entry_stats, progress| {
195
+ let written_id = out
196
+ . write_buf ( object_kind, buf, HashKind :: Sha1 )
197
+ . map_err ( |err| Error :: Write ( Box :: new ( err) as Box < dyn std:: error:: Error + Send + Sync > , object_kind, index_entry. oid ) )
198
+ . map_err ( |err| Box :: new ( err) as Box < dyn std:: error:: Error + Send + Sync > ) ?;
199
+ if written_id != index_entry. oid {
200
+ if let git_object:: Kind :: Tree = object_kind {
201
+ progress. info ( format ! ( "The tree in pack named {} was written as {} due to modes 100664 and 100640 rewritten as 100644." , index_entry. oid, written_id) ) ;
202
+ } else {
203
+ return Err ( Box :: new ( Error :: ObjectEncodeMismatch ( object_kind, index_entry. oid , written_id) ) )
204
+ }
205
+ }
206
+ if let Some ( verifier) = object_verifier. as_ref ( ) {
207
+ let obj = verifier. locate ( written_id. to_borrowed ( ) )
208
+ . ok_or_else ( || Error :: WrittenFileMissing ( written_id) ) ?
209
+ . map_err ( |err| Error :: WrittenFileCorrupt ( err, written_id) ) ?;
210
+ // obj.checksum_matches(written_id);
211
+ }
212
+ Ok ( ( ) )
198
213
}
199
- Ok ( ( ) )
200
214
}
201
- } } ,
215
+ } ,
202
216
pack:: cache:: DecodeEntryLRU :: default,
203
217
) . map ( |( _, _, c) |progress:: DoOrDiscard :: from ( c) ) . with_context ( || "Failed to explode the entire pack - some loose objects may have been created nonetheless" ) ?;
204
218
@@ -208,7 +222,13 @@ where
208
222
if delete_pack {
209
223
fs:: remove_file ( & index_path)
210
224
. and_then ( |_| fs:: remove_file ( & data_path) )
211
- . map_err ( |err| Error :: RemoveFile ( err, index_path. clone ( ) , data_path. clone ( ) ) ) ?;
225
+ . with_context ( || {
226
+ format ! (
227
+ "Failed to delete pack index file at '{} or data file at '{}'" ,
228
+ index_path. display( ) ,
229
+ data_path. display( )
230
+ )
231
+ } ) ?;
212
232
progress. info ( format ! (
213
233
"Removed '{}' and '{}'" ,
214
234
index_path. display( ) ,
0 commit comments