diff --git a/Cargo.toml b/Cargo.toml index 83f1085..6d46f8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ version = "0.8.7" edition = "2021" exclude = ["logo.png", "tests/test_data/**"] license = "MIT" +authors = ["Vince Buffalo "] keywords = ["science", "reproducibility", "bioinformatics", "data"] categories = ["command-line-utilities", "science"] repository = "https://github.com/vsbuffalo/scidataflow" diff --git a/src/lib/project.rs b/src/lib/project.rs index 177940d..19d9f42 100644 --- a/src/lib/project.rs +++ b/src/lib/project.rs @@ -21,6 +21,8 @@ use crate::lib::utils::{load_file, pluralize, print_status}; #[allow(unused_imports)] use crate::{print_info, print_warn}; +use super::utils::is_directory; + const MANIFEST: &str = "data_manifest.yml"; pub fn find_manifest(start_dir: Option<&PathBuf>, filename: &str) -> Option { @@ -466,10 +468,21 @@ impl Project { // has been successfully moved. So the updating is all done on the DataFile // directly, since lower interfaces cannot access the relative path. pub async fn mv(&mut self, source: &str, destination: &str) -> Result<()> { - let source_path = self.relative_path_string(Path::new(source))?; - if let Some(file) = self.data.files.remove(&source_path) { + let source_path = Path::new(source); + let source_path_str = self.relative_path_string(source_path)?; + if let Some(file) = self.data.files.remove(&source_path_str) { + let mut destination_path = PathBuf::from(destination); + + if is_directory(&destination_path) { + // if destination is a directory, append the file name from + // the source path to mimic unix mv + if let Some(file_name) = source_path.file_name() { + destination_path = destination_path.join(file_name); + } + } + // move the actual file - rename(source, destination).context("Error encountered when moving file.")?; + rename(source, destination_path).context("Error encountered when moving file.")?; // update the relative path let relative_destination = self.relative_path_string(Path::new(destination))?; @@ -484,9 +497,9 @@ impl Project { self.save() } else { Err(anyhow!( - "Cannot move file '{}' with 'sdf mv' since it is not in the manifest.", - source - )) + "Cannot move file '{}' with 'sdf mv' since it is not in the manifest.", + source + )) } } @@ -516,17 +529,17 @@ impl Project { } else { println!( "File '{}' already existed in \ - the manifest, so it was not added.", + the manifest, so it was not added.", &filepath - ); + ); } Ok(()) } else { Err(anyhow!( - "The file at '{}' was not downloaded because it would overwrite a file.\n\ - Use 'sdf get --ovewrite' to overwrite it.", - url - )) + "The file at '{}' was not downloaded because it would overwrite a file.\n\ + Use 'sdf get --ovewrite' to overwrite it.", + url + )) } } @@ -536,7 +549,7 @@ impl Project { column: Option, header: bool, overwrite: bool, - ) -> Result<()> { + ) -> Result<()> { let extension = std::path::Path::new(filename) .extension() .and_then(std::ffi::OsStr::to_str); @@ -596,15 +609,15 @@ impl Project { let num_skipped = skipped.len(); println!( "{} URLs found in '{}.'\n\ - {} files were downloaded, {} added to manifest ({} were already registered).\n\ - {} files were skipped because they existed (and --overwrite was no specified).", + {} files were downloaded, {} added to manifest ({} were already registered).\n\ + {} files were skipped because they existed (and --overwrite was no specified).", num_lines, filename, urls.len(), num_added, num_already_registered, num_skipped - ); + ); self.save()?; Ok(()) } diff --git a/src/lib/utils.rs b/src/lib/utils.rs index 18b07d0..d062ee4 100644 --- a/src/lib/utils.rs +++ b/src/lib/utils.rs @@ -6,6 +6,7 @@ use log::{debug, info, trace}; use md5::Context; use std::collections::BTreeMap; use std::collections::HashMap; +use std::fs; use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; @@ -36,6 +37,12 @@ pub fn ensure_directory(dir: &Path) -> Result<()> { } } +pub fn is_directory(path: &Path) -> bool { + fs::metadata(path) + .map(|metadata| metadata.is_dir()) + .unwrap_or(false) +} + pub fn ensure_exists(path: &Path) -> Result<()> { if path.exists() { Ok(())