@@ -135,7 +135,7 @@ where
135135 } ;
136136
137137 // For possibly existing, overwritten files, we must change the file mode explicitly.
138- finalize_entry ( entry, file, set_executable_after_creation) ?;
138+ finalize_entry ( entry, file, num_bytes as u64 , set_executable_after_creation) ?;
139139 num_bytes
140140 }
141141 gix_index:: entry:: Mode :: SYMLINK => {
@@ -276,19 +276,31 @@ pub(crate) fn open_file(
276276}
277277
278278/// Close `file` and store its stats in `entry`, possibly setting `file` executable.
279+ ///
280+ /// `desired_bytes` is the amount of bytes Git thinks the file should have after writing.
279281pub ( crate ) fn finalize_entry (
280282 entry : & mut gix_index:: Entry ,
281283 file : std:: fs:: File ,
284+ desired_bytes : u64 ,
282285 #[ cfg_attr( windows, allow( unused_variables) ) ] set_executable_after_creation : bool ,
283286) -> Result < ( ) , crate :: checkout:: Error > {
284287 // For possibly existing, overwritten files, we must change the file mode explicitly.
285288 #[ cfg( unix) ]
286289 if set_executable_after_creation {
287290 set_executable ( & file) ?;
288291 }
292+
293+ let md = & gix_index:: fs:: Metadata :: from_file ( & file) ?;
294+ // A last sanity check: if the file wasn't truncated upon opening, which is good in case something
295+ // goes wrong during writing, not everything is lost, then after writing the file is smaller than it was
296+ // before, it needs truncation. We do that here.
297+ let needs_truncation = md. len ( ) > desired_bytes;
298+ if needs_truncation {
299+ file. set_len ( desired_bytes) ?;
300+ }
289301 // NOTE: we don't call `file.sync_all()` here knowing that some filesystems don't handle this well.
290302 // revisit this once there is a bug to fix.
291- entry. stat = Stat :: from_fs ( & gix_index :: fs :: Metadata :: from_file ( & file ) ? ) ?;
303+ entry. stat = Stat :: from_fs ( md ) ?;
292304 file. close ( ) ?;
293305 Ok ( ( ) )
294306}
0 commit comments