fix: use PathBuf::join for path construction in download command
On Windows, std::fs::canonicalize returns an extended-length path
with the \?\ prefix, which does not support forward slashes.
Using format!("{}/{}", ...) to join paths then caused os error 123
(ERROR_INVALID_NAME).
Replace all string-based path concatenation with PathBuf::join so
that the OS-appropriate separator is used on every platform.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
+18
-19
@@ -4,7 +4,7 @@ use crate::commands::shared::{
|
||||
};
|
||||
use crate::connection::MDRSConnection;
|
||||
use futures::stream::{FuturesUnordered, StreamExt};
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub async fn download(
|
||||
@@ -26,7 +26,6 @@ pub async fn download(
|
||||
if !local_real.is_dir() {
|
||||
return Err(format!("Local directory `{}` not found.", local_path).into());
|
||||
}
|
||||
let local_dir_base = local_real.to_string_lossy().to_string();
|
||||
|
||||
// Split r_path into the parent directory path and the target basename.
|
||||
// Trailing slashes are already stripped by parse_remote_path, so this is safe.
|
||||
@@ -49,20 +48,20 @@ pub async fn download(
|
||||
return Ok(());
|
||||
}
|
||||
// Python always places the downloaded file inside the local directory.
|
||||
let dest = format!("{}/{}", local_dir_base, file.name);
|
||||
let dest = local_real.join(&file.name);
|
||||
if skip_if_exists {
|
||||
if Path::new(&dest).exists() {
|
||||
if dest.exists() {
|
||||
if let Ok(meta) = std::fs::metadata(&dest) {
|
||||
if meta.len() == file.size {
|
||||
println!("{}", dest);
|
||||
println!("{}", dest.display());
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let url = make_absolute_url(&conn, &file.download_url);
|
||||
conn.download_file(&url, &dest).await?;
|
||||
println!("{}", dest);
|
||||
conn.download_file(&url, &dest.to_string_lossy()).await?;
|
||||
println!("{}", dest.display());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -77,10 +76,10 @@ pub async fn download(
|
||||
}
|
||||
// Python downloads into local_path/<remote_folder_name>/ (not directly into local_path).
|
||||
// We create that subdirectory first, then recurse into it.
|
||||
let top_local = format!("{}/{}", local_dir_base, sub.name);
|
||||
let top_local = local_real.join(&sub.name);
|
||||
|
||||
// Iterative DFS: each entry is (remote_folder_id, local_dir)
|
||||
let mut stack: Vec<(String, String)> = vec![(sub.id.clone(), top_local)];
|
||||
let mut stack: Vec<(String, PathBuf)> = vec![(sub.id.clone(), top_local)];
|
||||
|
||||
while let Some((folder_id, local_dir)) = stack.pop() {
|
||||
let folder = conn.retrieve_folder(&folder_id).await?;
|
||||
@@ -90,7 +89,7 @@ pub async fn download(
|
||||
}
|
||||
|
||||
tokio::fs::create_dir_all(&local_dir).await?;
|
||||
println!("{}", local_dir);
|
||||
println!("{}", local_dir.display());
|
||||
|
||||
let dir_files = conn.list_all_files(&folder_id).await?;
|
||||
|
||||
@@ -101,12 +100,12 @@ pub async fn download(
|
||||
if is_excluded(&excludes, &lab.name, &folder.path, Some(&f.name)) {
|
||||
continue;
|
||||
}
|
||||
let dest_path = format!("{}/{}", local_dir, f.name);
|
||||
let dest_path = local_dir.join(&f.name);
|
||||
if skip_if_exists {
|
||||
if Path::new(&dest_path).exists() {
|
||||
if dest_path.exists() {
|
||||
if let Ok(meta) = std::fs::metadata(&dest_path) {
|
||||
if meta.len() == f.size {
|
||||
println!("{}", dest_path);
|
||||
println!("{}", dest_path.display());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -114,13 +113,13 @@ pub async fn download(
|
||||
}
|
||||
let url = make_absolute_url(&conn, &f.download_url);
|
||||
let conn = conn.clone();
|
||||
let _fname = f.name.clone();
|
||||
futs.push(tokio::spawn(async move {
|
||||
match conn.download_file(&url, &dest_path).await {
|
||||
Ok(_) => println!("{}", dest_path),
|
||||
let dest_str = dest_path.to_string_lossy().to_string();
|
||||
match conn.download_file(&url, &dest_str).await {
|
||||
Ok(_) => println!("{}", dest_path.display()),
|
||||
Err(_) => {
|
||||
eprintln!("Failed: {}", dest_path);
|
||||
if Path::new(&dest_path).is_file() {
|
||||
eprintln!("Failed: {}", dest_path.display());
|
||||
if dest_path.is_file() {
|
||||
let _ = std::fs::remove_file(&dest_path);
|
||||
}
|
||||
}
|
||||
@@ -144,7 +143,7 @@ pub async fn download(
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
let sub_local = format!("{}/{}", local_dir, sf.name);
|
||||
let sub_local = local_dir.join(&sf.name);
|
||||
stack.push((sf.id.clone(), sub_local));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user