project: Fix empty files not downloading from a remote project (#51571)
Amaan
created 3 weeks ago
- check `content_size==0`
- entry is removed from `downloading_files`
- empty file is writte via `smol::fs::write(..., &[])`
this means the receiver handles the empty files completely as soon as
the State message arrives, without ever needing a Chunk that will never
come
Closes #51551
Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [ ] No UI CHANGES
Release Notes:
- Fixed empty files not downloading from a remote project
Change summary
crates/project/src/project.rs | 58 ++++++++++++++++++++++++++----------
1 file changed, 42 insertions(+), 16 deletions(-)
Detailed changes
@@ -5497,25 +5497,51 @@ impl Project {
let key = (worktree_id, path);
log::debug!("handle_create_file_for_peer: looking up key={:?}", key);
- let mut files = downloading_files.lock();
- log::trace!(
- "handle_create_file_for_peer: current downloading_files keys: {:?}",
- files.keys().collect::<Vec<_>>()
- );
+ let empty_file_destination: Option<PathBuf> = {
+ let mut files = downloading_files.lock();
+ log::trace!(
+ "handle_create_file_for_peer: current downloading_files keys: {:?}",
+ files.keys().collect::<Vec<_>>()
+ );
+
+ if let Some(file_entry) = files.get_mut(&key) {
+ file_entry.total_size = state.content_size;
+ file_entry.file_id = Some(state.id);
+ log::debug!(
+ "handle_create_file_for_peer: updated file entry: total_size={}, file_id={}",
+ state.content_size,
+ state.id
+ );
+ } else {
+ log::warn!(
+ "handle_create_file_for_peer: key={:?} not found in downloading_files",
+ key
+ );
+ }
+
+ if state.content_size == 0 {
+ // No chunks will arrive for an empty file; write it now.
+ files.remove(&key).map(|entry| entry.destination_path)
+ } else {
+ None
+ }
+ };
- if let Some(file_entry) = files.get_mut(&key) {
- file_entry.total_size = state.content_size;
- file_entry.file_id = Some(state.id);
+ if let Some(destination) = empty_file_destination {
log::debug!(
- "handle_create_file_for_peer: updated file entry: total_size={}, file_id={}",
- state.content_size,
- state.id
- );
- } else {
- log::warn!(
- "handle_create_file_for_peer: key={:?} not found in downloading_files",
- key
+ "handle_create_file_for_peer: writing empty file to {:?}",
+ destination
);
+ match smol::fs::write(&destination, &[] as &[u8]).await {
+ Ok(_) => log::info!(
+ "handle_create_file_for_peer: successfully wrote file to {:?}",
+ destination
+ ),
+ Err(e) => log::error!(
+ "handle_create_file_for_peer: failed to write empty file: {:?}",
+ e
+ ),
+ }
}
} else {
log::warn!("handle_create_file_for_peer: State has no file field");