diff --git a/sn_cli/src/bin/subcommands/files.rs b/sn_cli/src/bin/subcommands/files.rs index c9bac6d498..f1742fc959 100644 --- a/sn_cli/src/bin/subcommands/files.rs +++ b/sn_cli/src/bin/subcommands/files.rs @@ -6,11 +6,9 @@ // KIND, either express or implied. Please review the Licences for the specific language governing // permissions and limitations relating to use of the SAFE Network Software. -use autonomi::{ - download_file, download_files, ChunkManager, Estimator, UploadedFile, UPLOADED_FILES, -}; +use autonomi::{download_file, ChunkManager, Estimator, UploadedFile, UPLOADED_FILES}; use clap::Parser; -use color_eyre::{eyre::eyre, Help, Result}; +use color_eyre::{eyre::eyre, Result}; use sn_client::protocol::storage::{Chunk, ChunkAddress, RetryStrategy}; use sn_client::{Client, FilesApi, BATCH_SIZE}; use std::{ @@ -37,14 +35,14 @@ pub enum FilesCmds { /// /// If neither are, all the files uploaded by the current user will be downloaded again. #[clap(name = "name")] - file_name: Option, + file_name: OsString, /// The hex address of a file. /// /// If the address argument is used, the name argument must also be supplied. /// /// If neither are, all the files uploaded by the current user will be downloaded again. #[clap(name = "address")] - file_addr: Option, + file_addr: String, /// Flagging whether to show the holders of the uploaded chunks. /// Default to be not showing. #[clap(long, name = "show_holders", default_value = "false")] @@ -81,107 +79,79 @@ pub(crate) async fn files_cmds(cmds: FilesCmds, client: &Client, root_dir: &Path batch_size, retry_strategy, } => { - if (file_name.is_some() && file_addr.is_none()) - || (file_addr.is_some() && file_name.is_none()) - { - return Err( - eyre!("Both the name and address must be supplied if either are used") - .suggestion( - "Please run the command again in the form 'files upload
'", - ), - ); - } - let mut download_dir = root_dir.to_path_buf(); let mut download_file_name = file_name.clone(); - if let Some(file_name) = file_name { - // file_name may direct the downloaded data to: - // - // the current directory (just a filename) - // eg safe files download myfile.txt ADDRESS - // - // a directory relative to the current directory (relative filename) - // eg safe files download my/relative/path/myfile.txt ADDRESS - // - // a directory relative to root of the filesystem (absolute filename) - // eg safe files download /home/me/mydir/myfile.txt ADDRESS - let file_name_path = Path::new(&file_name); - if file_name_path.is_dir() { - return Err(eyre!("Cannot download file to path: {:?}", file_name)); - } - let file_name_dir = file_name_path.parent(); - if file_name_dir.is_none() { - // just a filename, use the current_dir - download_dir = std::env::current_dir().unwrap_or(root_dir.to_path_buf()); - } else if file_name_path.is_relative() { - // relative to the current directory. Make the relative path - // into an absolute path by joining it to current_dir - if let Some(relative_dir) = file_name_dir { - let current_dir = std::env::current_dir().unwrap_or(root_dir.to_path_buf()); - download_dir = current_dir.join(relative_dir); - if !download_dir.exists() { - return Err(eyre!("Directory does not exist: {:?}", download_dir)); - } - if let Some(path_file_name) = file_name_path.file_name() { - download_file_name = Some(OsString::from(path_file_name)); - } + // file_name may direct the downloaded data to: + // + // the current directory (just a filename) + // eg safe files download myfile.txt ADDRESS + // + // a directory relative to the current directory (relative filename) + // eg safe files download my/relative/path/myfile.txt ADDRESS + // + // a directory relative to root of the filesystem (absolute filename) + // eg safe files download /home/me/mydir/myfile.txt ADDRESS + let file_name_path = Path::new(&file_name); + if file_name_path.is_dir() { + return Err(eyre!("Cannot download file to path: {:?}", file_name)); + } + let file_name_dir = file_name_path.parent(); + if file_name_dir.is_none() { + // just a filename, use the current_dir + download_dir = std::env::current_dir().unwrap_or(root_dir.to_path_buf()); + } else if file_name_path.is_relative() { + // relative to the current directory. Make the relative path + // into an absolute path by joining it to current_dir + if let Some(relative_dir) = file_name_dir { + let current_dir = std::env::current_dir().unwrap_or(root_dir.to_path_buf()); + download_dir = current_dir.join(relative_dir); + if !download_dir.exists() { + return Err(eyre!("Directory does not exist: {:?}", download_dir)); + } + if let Some(path_file_name) = file_name_path.file_name() { + download_file_name = OsString::from(path_file_name); } - } else { - // absolute dir - download_dir = file_name_dir.unwrap_or(root_dir).to_path_buf(); } + } else { + // absolute dir + download_dir = file_name_dir.unwrap_or(root_dir).to_path_buf(); } - let files_api: FilesApi = FilesApi::new(client.clone(), download_dir.clone()); - match (download_file_name, file_addr) { - (Some(download_file_name), Some(address_provided)) => { - let bytes = - hex::decode(&address_provided).expect("Input address is not a hex string"); - let xor_name_provided = XorName( - bytes - .try_into() - .expect("Failed to parse XorName from hex string"), - ); - // try to read the data_map if it exists locally. - let uploaded_files_path = root_dir.join(UPLOADED_FILES); - let expected_data_map_location = uploaded_files_path.join(address_provided); - let local_data_map = { - if expected_data_map_location.exists() { - let uploaded_file_metadata = - UploadedFile::read(&expected_data_map_location)?; + let files_api: FilesApi = FilesApi::new(client.clone(), download_dir.clone()); - uploaded_file_metadata.data_map.map(|bytes| Chunk { - address: ChunkAddress::new(xor_name_provided), - value: bytes, - }) - } else { - None - } - }; + let address_provided = file_addr; + let bytes = hex::decode(&address_provided).expect("Input address is not a hex string"); + let xor_name_provided = XorName( + bytes + .try_into() + .expect("Failed to parse XorName from hex string"), + ); + // try to read the data_map if it exists locally. + let uploaded_files_path = root_dir.join(UPLOADED_FILES); + let expected_data_map_location = uploaded_files_path.join(address_provided); + let local_data_map = { + if expected_data_map_location.exists() { + let uploaded_file_metadata = UploadedFile::read(&expected_data_map_location)?; - download_file( - files_api, - xor_name_provided, - (download_file_name, local_data_map), - &download_dir, - show_holders, - batch_size, - retry_strategy, - ) - .await - } - _ => { - println!("Attempting to download all files uploaded by the current user..."); - download_files( - &files_api, - root_dir, - show_holders, - batch_size, - retry_strategy, - ) - .await? + uploaded_file_metadata.data_map.map(|bytes| Chunk { + address: ChunkAddress::new(xor_name_provided), + value: bytes, + }) + } else { + None } - } + }; + + download_file( + files_api, + xor_name_provided, + (download_file_name, local_data_map), + &download_dir, + show_holders, + batch_size, + retry_strategy, + ) + .await } } Ok(()) diff --git a/sn_cli/src/files.rs b/sn_cli/src/files.rs index e9b3a1346b..c98943c5c3 100644 --- a/sn_cli/src/files.rs +++ b/sn_cli/src/files.rs @@ -13,7 +13,7 @@ mod files_uploader; mod upload; pub use chunk_manager::ChunkManager; -pub use download::{download_file, download_files}; +pub use download::download_file; pub use estimate::Estimator; pub use files_uploader::FilesUploader; pub use upload::{UploadedFile, UPLOADED_FILES}; diff --git a/sn_cli/src/files/download.rs b/sn_cli/src/files/download.rs index 2d200d8dd4..e455566f49 100644 --- a/sn_cli/src/files/download.rs +++ b/sn_cli/src/files/download.rs @@ -6,86 +6,19 @@ // KIND, either express or implied. Please review the Licences for the specific language governing // permissions and limitations relating to use of the SAFE Network Software. -use super::{ - get_progress_bar, - upload::{UploadedFile, UPLOADED_FILES}, -}; +use super::get_progress_bar; -use std::collections::BTreeSet; use std::ffi::OsString; use std::path::Path; -use color_eyre::Result; use indicatif::ProgressBar; -use walkdir::WalkDir; use xor_name::XorName; use sn_client::{ protocol::storage::{Chunk, ChunkAddress, RetryStrategy}, FilesApi, FilesDownload, FilesDownloadEvent, }; -use tracing::{debug, error, info}; - -/// The default folder to download files to. -const DOWNLOAD_FOLDER: &str = "safe_files"; - -pub async fn download_files( - files_api: &FilesApi, - root_dir: &Path, - show_holders: bool, - batch_size: usize, - retry_strategy: RetryStrategy, -) -> Result<()> { - info!("Downloading with batch size of {}", batch_size); - let uploaded_files_path = root_dir.join(UPLOADED_FILES); - let download_path = dirs_next::download_dir() - .unwrap_or(root_dir.to_path_buf()) - .join(DOWNLOAD_FOLDER); - std::fs::create_dir_all(download_path.as_path())?; - - #[allow(clippy::mutable_key_type)] - let mut uploaded_files = BTreeSet::new(); - - for entry in WalkDir::new(uploaded_files_path.clone()) { - let entry = entry?; - let path = entry.path(); - if path.is_file() { - let hex_xorname = path - .file_name() - .expect("Uploaded file to have name") - .to_str() - .expect("Failed to convert path to string"); - let bytes = hex::decode(hex_xorname)?; - let xor_name_bytes: [u8; 32] = bytes - .try_into() - .expect("Failed to parse XorName from hex string"); - let xor_name = XorName(xor_name_bytes); - let address = ChunkAddress::new(xor_name); - - let uploaded_file_metadata = UploadedFile::read(path)?; - let datamap_chunk = uploaded_file_metadata.data_map.map(|bytes| Chunk { - address, - value: bytes, - }); - uploaded_files.insert((xor_name, (uploaded_file_metadata.filename, datamap_chunk))); - } - } - - for (xorname, file_data) in uploaded_files.into_iter() { - download_file( - files_api.clone(), - xorname, - file_data, - &download_path, - show_holders, - batch_size, - retry_strategy, - ) - .await; - } - - Ok(()) -} +use tracing::{debug, error}; pub async fn download_file( files_api: FilesApi, diff --git a/sn_cli/src/lib.rs b/sn_cli/src/lib.rs index 637f8a1581..76278d7816 100644 --- a/sn_cli/src/lib.rs +++ b/sn_cli/src/lib.rs @@ -11,6 +11,5 @@ mod files; pub use acc_packet::AccountPacket; pub use files::{ - download_file, download_files, ChunkManager, Estimator, FilesUploader, UploadedFile, - UPLOADED_FILES, + download_file, ChunkManager, Estimator, FilesUploader, UploadedFile, UPLOADED_FILES, };