mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Don't eagerly populate copied subdirectory
This can race anyway with snapshot updates, so we just eagerly refresh the root entry and wait for updates to come in to populate it.
This commit is contained in:
parent
604b737d7c
commit
354488ebdf
@ -824,7 +824,7 @@ async fn test_fs_operations(
|
||||
project_b
|
||||
.update(cx_b, |project, cx| {
|
||||
project
|
||||
.copy_entry(dir_entry.id, Path::new("DIR2"), cx)
|
||||
.copy_entry(entry.id, Path::new("f.txt"), cx)
|
||||
.unwrap()
|
||||
})
|
||||
.await
|
||||
@ -840,13 +840,10 @@ async fn test_fs_operations(
|
||||
"DIR/SUBDIR",
|
||||
"DIR/SUBDIR/f.txt",
|
||||
"DIR/e.txt",
|
||||
"DIR2",
|
||||
"DIR2/SUBDIR",
|
||||
"DIR2/SUBDIR/f.txt",
|
||||
"DIR2/e.txt",
|
||||
"a.txt",
|
||||
"b.txt",
|
||||
"d.txt"
|
||||
"d.txt",
|
||||
"f.txt"
|
||||
]
|
||||
);
|
||||
});
|
||||
@ -861,13 +858,10 @@ async fn test_fs_operations(
|
||||
"DIR/SUBDIR",
|
||||
"DIR/SUBDIR/f.txt",
|
||||
"DIR/e.txt",
|
||||
"DIR2",
|
||||
"DIR2/SUBDIR",
|
||||
"DIR2/SUBDIR/f.txt",
|
||||
"DIR2/e.txt",
|
||||
"a.txt",
|
||||
"b.txt",
|
||||
"d.txt"
|
||||
"d.txt",
|
||||
"f.txt"
|
||||
]
|
||||
);
|
||||
});
|
||||
@ -884,15 +878,7 @@ async fn test_fs_operations(
|
||||
.paths()
|
||||
.map(|p| p.to_string_lossy())
|
||||
.collect::<Vec<_>>(),
|
||||
[
|
||||
"DIR2",
|
||||
"DIR2/SUBDIR",
|
||||
"DIR2/SUBDIR/f.txt",
|
||||
"DIR2/e.txt",
|
||||
"a.txt",
|
||||
"b.txt",
|
||||
"d.txt"
|
||||
]
|
||||
["a.txt", "b.txt", "d.txt", "f.txt"]
|
||||
);
|
||||
});
|
||||
worktree_b.read_with(cx_b, |worktree, _| {
|
||||
@ -901,15 +887,7 @@ async fn test_fs_operations(
|
||||
.paths()
|
||||
.map(|p| p.to_string_lossy())
|
||||
.collect::<Vec<_>>(),
|
||||
[
|
||||
"DIR2",
|
||||
"DIR2/SUBDIR",
|
||||
"DIR2/SUBDIR/f.txt",
|
||||
"DIR2/e.txt",
|
||||
"a.txt",
|
||||
"b.txt",
|
||||
"d.txt"
|
||||
]
|
||||
["a.txt", "b.txt", "d.txt", "f.txt"]
|
||||
);
|
||||
});
|
||||
|
||||
@ -925,14 +903,7 @@ async fn test_fs_operations(
|
||||
.paths()
|
||||
.map(|p| p.to_string_lossy())
|
||||
.collect::<Vec<_>>(),
|
||||
[
|
||||
"DIR2",
|
||||
"DIR2/SUBDIR",
|
||||
"DIR2/SUBDIR/f.txt",
|
||||
"DIR2/e.txt",
|
||||
"a.txt",
|
||||
"b.txt"
|
||||
]
|
||||
["a.txt", "b.txt", "f.txt"]
|
||||
);
|
||||
});
|
||||
worktree_b.read_with(cx_b, |worktree, _| {
|
||||
@ -941,14 +912,7 @@ async fn test_fs_operations(
|
||||
.paths()
|
||||
.map(|p| p.to_string_lossy())
|
||||
.collect::<Vec<_>>(),
|
||||
[
|
||||
"DIR2",
|
||||
"DIR2/SUBDIR",
|
||||
"DIR2/SUBDIR/f.txt",
|
||||
"DIR2/e.txt",
|
||||
"a.txt",
|
||||
"b.txt"
|
||||
]
|
||||
["a.txt", "b.txt", "f.txt"]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -15,12 +15,7 @@ use text::Rope;
|
||||
pub trait Fs: Send + Sync {
|
||||
async fn create_dir(&self, path: &Path) -> Result<()>;
|
||||
async fn create_file(&self, path: &Path, options: CreateOptions) -> Result<()>;
|
||||
async fn copy(
|
||||
&self,
|
||||
source: &Path,
|
||||
target: &Path,
|
||||
options: CopyOptions,
|
||||
) -> Result<Vec<PathBuf>>;
|
||||
async fn copy(&self, source: &Path, target: &Path, options: CopyOptions) -> Result<()>;
|
||||
async fn rename(&self, source: &Path, target: &Path, options: RenameOptions) -> Result<()>;
|
||||
async fn remove_dir(&self, path: &Path, options: RemoveOptions) -> Result<()>;
|
||||
async fn remove_file(&self, path: &Path, options: RemoveOptions) -> Result<()>;
|
||||
@ -96,21 +91,15 @@ impl Fs for RealFs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn copy(
|
||||
&self,
|
||||
source: &Path,
|
||||
target: &Path,
|
||||
options: CopyOptions,
|
||||
) -> Result<Vec<PathBuf>> {
|
||||
async fn copy(&self, source: &Path, target: &Path, options: CopyOptions) -> Result<()> {
|
||||
if !options.overwrite && smol::fs::metadata(target).await.is_ok() {
|
||||
if options.ignore_if_exists {
|
||||
return Ok(Default::default());
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err(anyhow!("{target:?} already exists"));
|
||||
}
|
||||
}
|
||||
|
||||
let mut paths = vec![target.to_path_buf()];
|
||||
let metadata = smol::fs::metadata(source).await?;
|
||||
let _ = smol::fs::remove_dir_all(target).await;
|
||||
if metadata.is_dir() {
|
||||
@ -120,17 +109,15 @@ impl Fs for RealFs {
|
||||
if let Ok(child) = child {
|
||||
let child_source_path = child.path();
|
||||
let child_target_path = target.join(child.file_name());
|
||||
paths.extend(
|
||||
self.copy(&child_source_path, &child_target_path, options)
|
||||
.await?,
|
||||
);
|
||||
self.copy(&child_source_path, &child_target_path, options)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
smol::fs::copy(source, target).await?;
|
||||
}
|
||||
|
||||
Ok(paths)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn rename(&self, source: &Path, target: &Path, options: RenameOptions) -> Result<()> {
|
||||
@ -560,12 +547,7 @@ impl Fs for FakeFs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn copy(
|
||||
&self,
|
||||
source: &Path,
|
||||
target: &Path,
|
||||
options: CopyOptions,
|
||||
) -> Result<Vec<PathBuf>> {
|
||||
async fn copy(&self, source: &Path, target: &Path, options: CopyOptions) -> Result<()> {
|
||||
let source = normalize_path(source);
|
||||
let target = normalize_path(target);
|
||||
|
||||
@ -575,7 +557,7 @@ impl Fs for FakeFs {
|
||||
|
||||
if !options.overwrite && state.entries.contains_key(&target) {
|
||||
if options.ignore_if_exists {
|
||||
return Ok(Default::default());
|
||||
return Ok(());
|
||||
} else {
|
||||
return Err(anyhow!("{target:?} already exists"));
|
||||
}
|
||||
@ -588,15 +570,15 @@ impl Fs for FakeFs {
|
||||
}
|
||||
}
|
||||
|
||||
let mut paths = Vec::new();
|
||||
let mut events = Vec::new();
|
||||
for (relative_path, entry) in new_entries {
|
||||
let new_path = normalize_path(&target.join(relative_path));
|
||||
paths.push(new_path.clone());
|
||||
events.push(new_path.clone());
|
||||
state.entries.insert(new_path, entry);
|
||||
}
|
||||
|
||||
state.emit_event(&paths).await;
|
||||
Ok(paths)
|
||||
state.emit_event(&events).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn remove_dir(&self, dir_path: &Path, options: RemoveOptions) -> Result<()> {
|
||||
|
@ -785,7 +785,7 @@ impl Project {
|
||||
entry_id: ProjectEntryId,
|
||||
new_path: impl Into<Arc<Path>>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Option<Task<Result<(Entry, Vec<Entry>)>>> {
|
||||
) -> Option<Task<Result<Entry>>> {
|
||||
let worktree = self.worktree_for_entry(entry_id, cx)?;
|
||||
let new_path = new_path.into();
|
||||
if self.is_local() {
|
||||
@ -810,24 +810,15 @@ impl Project {
|
||||
let entry = response
|
||||
.entry
|
||||
.ok_or_else(|| anyhow!("missing entry in response"))?;
|
||||
let (entry, child_entries) = worktree.update(&mut cx, |worktree, cx| {
|
||||
let worktree = worktree.as_remote().unwrap();
|
||||
let root_entry =
|
||||
worktree.insert_entry(entry, response.worktree_scan_id as usize, cx);
|
||||
let mut child_entries = Vec::new();
|
||||
for entry in response.child_entries {
|
||||
child_entries.push(worktree.insert_entry(
|
||||
worktree
|
||||
.update(&mut cx, |worktree, cx| {
|
||||
worktree.as_remote().unwrap().insert_entry(
|
||||
entry,
|
||||
response.worktree_scan_id as usize,
|
||||
cx,
|
||||
));
|
||||
}
|
||||
(root_entry, child_entries)
|
||||
});
|
||||
Ok((
|
||||
entry.await?,
|
||||
futures::future::try_join_all(child_entries).await?,
|
||||
))
|
||||
)
|
||||
})
|
||||
.await
|
||||
}))
|
||||
}
|
||||
}
|
||||
@ -4058,7 +4049,6 @@ impl Project {
|
||||
.await?;
|
||||
Ok(proto::ProjectEntryResponse {
|
||||
entry: Some((&entry).into()),
|
||||
child_entries: Default::default(),
|
||||
worktree_scan_id: worktree_scan_id as u64,
|
||||
})
|
||||
}
|
||||
@ -4087,7 +4077,6 @@ impl Project {
|
||||
.await?;
|
||||
Ok(proto::ProjectEntryResponse {
|
||||
entry: Some((&entry).into()),
|
||||
child_entries: Default::default(),
|
||||
worktree_scan_id: worktree_scan_id as u64,
|
||||
})
|
||||
}
|
||||
@ -4104,7 +4093,7 @@ impl Project {
|
||||
.ok_or_else(|| anyhow!("worktree not found"))
|
||||
})?;
|
||||
let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id());
|
||||
let (entry, child_entries) = worktree
|
||||
let entry = worktree
|
||||
.update(&mut cx, |worktree, cx| {
|
||||
let new_path = PathBuf::from(OsString::from_vec(envelope.payload.new_path));
|
||||
worktree
|
||||
@ -4116,7 +4105,6 @@ impl Project {
|
||||
.await?;
|
||||
Ok(proto::ProjectEntryResponse {
|
||||
entry: Some((&entry).into()),
|
||||
child_entries: child_entries.iter().map(Into::into).collect(),
|
||||
worktree_scan_id: worktree_scan_id as u64,
|
||||
})
|
||||
}
|
||||
@ -4144,7 +4132,6 @@ impl Project {
|
||||
.await?;
|
||||
Ok(proto::ProjectEntryResponse {
|
||||
entry: None,
|
||||
child_entries: Default::default(),
|
||||
worktree_scan_id: worktree_scan_id as u64,
|
||||
})
|
||||
}
|
||||
|
@ -779,7 +779,7 @@ impl LocalWorktree {
|
||||
entry_id: ProjectEntryId,
|
||||
new_path: impl Into<Arc<Path>>,
|
||||
cx: &mut ModelContext<Worktree>,
|
||||
) -> Option<Task<Result<(Entry, Vec<Entry>)>>> {
|
||||
) -> Option<Task<Result<Entry>>> {
|
||||
let old_path = self.entry_for_id(entry_id)?.path.clone();
|
||||
let new_path = new_path.into();
|
||||
let abs_old_path = self.absolutize(&old_path);
|
||||
@ -794,38 +794,23 @@ impl LocalWorktree {
|
||||
});
|
||||
|
||||
Some(cx.spawn(|this, mut cx| async move {
|
||||
let copied_paths = copy.await?;
|
||||
let (entry, child_entries) = this.update(&mut cx, |this, cx| {
|
||||
let this = this.as_local_mut().unwrap();
|
||||
let root_entry =
|
||||
this.refresh_entry(new_path.clone(), abs_new_path.clone(), None, cx);
|
||||
|
||||
let mut child_entries = Vec::new();
|
||||
for copied_path in copied_paths {
|
||||
if copied_path != abs_new_path {
|
||||
let relative_copied_path = copied_path.strip_prefix(this.abs_path())?;
|
||||
child_entries.push(this.refresh_entry(
|
||||
relative_copied_path.into(),
|
||||
copied_path,
|
||||
None,
|
||||
cx,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
anyhow::Ok((root_entry, child_entries))
|
||||
})?;
|
||||
let (entry, child_entries) = (
|
||||
entry.await?,
|
||||
futures::future::try_join_all(child_entries).await?,
|
||||
);
|
||||
|
||||
copy.await?;
|
||||
let entry = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.as_local_mut().unwrap().refresh_entry(
|
||||
new_path.clone(),
|
||||
abs_new_path,
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.poll_snapshot(cx);
|
||||
this.as_local().unwrap().broadcast_snapshot()
|
||||
})
|
||||
.await;
|
||||
Ok((entry, child_entries))
|
||||
Ok(entry)
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -224,8 +224,7 @@ message DeleteProjectEntry {
|
||||
|
||||
message ProjectEntryResponse {
|
||||
Entry entry = 1;
|
||||
repeated Entry child_entries = 2;
|
||||
uint64 worktree_scan_id = 3;
|
||||
uint64 worktree_scan_id = 2;
|
||||
}
|
||||
|
||||
message AddProjectCollaborator {
|
||||
|
Loading…
Reference in New Issue
Block a user