Implement dragging external files to remote projects (#28987)
Release Notes: - Added the ability to copy external files into remote projects by dragging them onto the project panel. --------- Co-authored-by: Peter Tripp <petertripp@gmail.com>
This commit is contained in:
parent
fade49a11a
commit
7e928dd615
8 changed files with 275 additions and 82 deletions
|
@ -111,6 +111,7 @@ pub trait Fs: Send + Sync {
|
|||
async fn load_bytes(&self, path: &Path) -> Result<Vec<u8>>;
|
||||
async fn atomic_write(&self, path: PathBuf, text: String) -> Result<()>;
|
||||
async fn save(&self, path: &Path, text: &Rope, line_ending: LineEnding) -> Result<()>;
|
||||
async fn write(&self, path: &Path, content: &[u8]) -> Result<()>;
|
||||
async fn canonicalize(&self, path: &Path) -> Result<PathBuf>;
|
||||
async fn is_file(&self, path: &Path) -> bool;
|
||||
async fn is_dir(&self, path: &Path) -> bool;
|
||||
|
@ -567,6 +568,14 @@ impl Fs for RealFs {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn write(&self, path: &Path, content: &[u8]) -> Result<()> {
|
||||
if let Some(path) = path.parent() {
|
||||
self.create_dir(path).await?;
|
||||
}
|
||||
smol::fs::write(path, content).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn canonicalize(&self, path: &Path) -> Result<PathBuf> {
|
||||
Ok(smol::fs::canonicalize(path).await?)
|
||||
}
|
||||
|
@ -2105,6 +2114,16 @@ impl Fs for FakeFs {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn write(&self, path: &Path, content: &[u8]) -> Result<()> {
|
||||
self.simulate_random_delay().await;
|
||||
let path = normalize_path(path);
|
||||
if let Some(path) = path.parent() {
|
||||
self.create_dir(path).await?;
|
||||
}
|
||||
self.write_file_internal(path, content.to_vec(), false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn canonicalize(&self, path: &Path) -> Result<PathBuf> {
|
||||
let path = normalize_path(path);
|
||||
self.simulate_random_delay().await;
|
||||
|
@ -2346,7 +2365,7 @@ pub async fn copy_recursive<'a>(
|
|||
target: &'a Path,
|
||||
options: CopyOptions,
|
||||
) -> Result<()> {
|
||||
for (is_dir, item) in read_dir_items(fs, source).await? {
|
||||
for (item, is_dir) in read_dir_items(fs, source).await? {
|
||||
let Ok(item_relative_path) = item.strip_prefix(source) else {
|
||||
continue;
|
||||
};
|
||||
|
@ -2380,7 +2399,10 @@ pub async fn copy_recursive<'a>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn read_dir_items<'a>(fs: &'a dyn Fs, source: &'a Path) -> Result<Vec<(bool, PathBuf)>> {
|
||||
/// Recursively reads all of the paths in the given directory.
|
||||
///
|
||||
/// Returns a vector of tuples of (path, is_dir).
|
||||
pub async fn read_dir_items<'a>(fs: &'a dyn Fs, source: &'a Path) -> Result<Vec<(PathBuf, bool)>> {
|
||||
let mut items = Vec::new();
|
||||
read_recursive(fs, source, &mut items).await?;
|
||||
Ok(items)
|
||||
|
@ -2389,7 +2411,7 @@ async fn read_dir_items<'a>(fs: &'a dyn Fs, source: &'a Path) -> Result<Vec<(boo
|
|||
fn read_recursive<'a>(
|
||||
fs: &'a dyn Fs,
|
||||
source: &'a Path,
|
||||
output: &'a mut Vec<(bool, PathBuf)>,
|
||||
output: &'a mut Vec<(PathBuf, bool)>,
|
||||
) -> BoxFuture<'a, Result<()>> {
|
||||
use futures::future::FutureExt;
|
||||
|
||||
|
@ -2400,7 +2422,7 @@ fn read_recursive<'a>(
|
|||
.ok_or_else(|| anyhow!("path does not exist: {}", source.display()))?;
|
||||
|
||||
if metadata.is_dir {
|
||||
output.push((true, source.to_path_buf()));
|
||||
output.push((source.to_path_buf(), true));
|
||||
let mut children = fs.read_dir(source).await?;
|
||||
while let Some(child_path) = children.next().await {
|
||||
if let Ok(child_path) = child_path {
|
||||
|
@ -2408,7 +2430,7 @@ fn read_recursive<'a>(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
output.push((false, source.to_path_buf()));
|
||||
output.push((source.to_path_buf(), false));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue