diff --git a/src/main.rs b/src/main.rs index 96d8169..08cab2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,6 +47,7 @@ use std::io::{BufReader, BufRead}; mod ui; mod event; mod check; +mod utils; mod bridge; mod engine; mod config; diff --git a/src/package/default.rs b/src/package/default.rs index a7df18a..e80f09c 100644 --- a/src/package/default.rs +++ b/src/package/default.rs @@ -25,7 +25,7 @@ use std::io::BufReader; use chrono::{NaiveDateTime, Timelike}; use std::time::{SystemTime, UNIX_EPOCH}; use crate::package::UpdateResult::{NotOutdated, Updated}; -use crate::package::InstallResult::{NotFound, AlreadyInstalled}; +use crate::package::InstallResult::{NotFoundInIndex, AlreadyInstalled}; use std::fs; use tempfile::TempDir; use git2::Repository; @@ -165,7 +165,7 @@ impl super::PackageManager for DefaultPackageManager { self.install_package_from_repo(name, &package.repo) }, None => { - Ok(NotFound) + Ok(NotFoundInIndex) }, } } @@ -177,8 +177,16 @@ impl super::PackageManager for DefaultPackageManager { return Ok(AlreadyInstalled); } - // TODO: clone the repo, and copy the folder to the packages dir - unimplemented!() + let temp_dir = Self::clone_repo_to_temp(repo_url)?; + + let temp_package_dir = temp_dir.path().join(name); + if !temp_package_dir.exists() { + return Ok(InstallResult::NotFoundInRepo); + } + + crate::utils::copy_dir_into(&temp_package_dir, &self.package_dir)?; + + Ok(InstallResult::Installed) } } @@ -189,6 +197,7 @@ mod tests { use std::path::Path; use crate::package::PackageManager; use std::fs::create_dir; + use crate::package::InstallResult::{Installed, NotFoundInRepo}; const OUTDATED_INDEX_CONTENT : &str = include_str!("../res/test/outdated_index.json"); const INDEX_CONTENT_WITHOUT_UPDATE: &str = include_str!("../res/test/index_without_update.json"); @@ -315,7 +324,7 @@ mod tests { std::fs::write(index_file, INSTALL_PACKAGE_INDEX); }); - assert_eq!(temp.package_manager.install_package("not-existing").unwrap(), NotFound); + assert_eq!(temp.package_manager.install_package("doesnotexist").unwrap(), NotFoundInIndex); } #[test] @@ -334,4 +343,27 @@ mod tests { let cloned_dir = DefaultPackageManager::clone_repo_to_temp("https://github.com/federico-terzi/espanso-hub-core").unwrap(); assert!(cloned_dir.path().join("LICENSE").exists()); } + + #[test] + fn test_install_package() { + let mut temp = create_temp_package_manager(|_, data_dir| { + let index_file = data_dir.join(DEFAULT_PACKAGE_INDEX_FILE); + std::fs::write(index_file, INSTALL_PACKAGE_INDEX); + }); + + assert_eq!(temp.package_manager.install_package("dummy-package").unwrap(), Installed); + assert!(temp.package_dir.path().join("dummy-package").exists()); + assert!(temp.package_dir.path().join("dummy-package/README.md").exists()); + assert!(temp.package_dir.path().join("dummy-package/package.yml").exists()); + } + + #[test] + fn test_install_package_does_not_exist_in_repo() { + let mut temp = create_temp_package_manager(|_, data_dir| { + let index_file = data_dir.join(DEFAULT_PACKAGE_INDEX_FILE); + std::fs::write(index_file, INSTALL_PACKAGE_INDEX); + }); + + assert_eq!(temp.package_manager.install_package("not-existing").unwrap(), NotFoundInRepo); + } } \ No newline at end of file diff --git a/src/package/mod.rs b/src/package/mod.rs index b7f6e6d..95ca33e 100644 --- a/src/package/mod.rs +++ b/src/package/mod.rs @@ -58,7 +58,8 @@ pub enum UpdateResult { #[derive(Clone, Debug, PartialEq)] pub enum InstallResult { - NotFound, + NotFoundInIndex, + NotFoundInRepo, AlreadyInstalled, Installed } \ No newline at end of file diff --git a/src/res/test/install_package_index.json b/src/res/test/install_package_index.json index 7512f40..df67503 100644 --- a/src/res/test/install_package_index.json +++ b/src/res/test/install_package_index.json @@ -3,11 +3,11 @@ "packages": [ { - "name": "basic-emojis", - "title": "Basic Emojis", + "name": "dummy-package", + "title": "Dummy Package", "version": "0.1.0", "repo": "https://github.com/federico-terzi/espanso-hub-core", - "desc": "A package to include some basic emojis in espanso.", + "desc": "Dummy package", "author": "Federico Terzi" }, @@ -21,7 +21,15 @@ "desc": "Include Italian accents substitutions to espanso.", "author": "Federico Terzi" + }, + + { + "name": "not-existing", + "title": "Not Existing", + "version": "0.1.0", + "repo": "https://github.com/federico-terzi/espanso-hub-core", + "desc": "Package that does not exist in the repo", + "author": "Federico Terzi" + } - - -]} \ No newline at end of file + ]} \ No newline at end of file diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..791ccdc --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,73 @@ +use std::path::Path; +use std::error::Error; +use walkdir::WalkDir; +use std::fs::create_dir; + +pub fn copy_dir_into(source_dir: &Path, dest_dir: &Path) -> Result<(), Box> { + // Create source directory in dest dir + let name = source_dir.file_name().expect("Error obtaining the filename"); + let target_dir = dest_dir.join(name); + create_dir(&target_dir)?; + + for entry in WalkDir::new(source_dir) { + let entry = entry?; + let entry = entry.path(); + if entry.is_dir() { + copy_dir_into(entry, &target_dir); + }else if entry.is_file() { + let target_entry = target_dir.join(entry.file_name().expect("Error obtaining the filename")); + std::fs::copy(entry, target_entry); + } + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use tempfile::TempDir; + use std::path::Path; + use std::fs::create_dir; + + #[test] + fn test_copy_dir_into() { + let source_tmp_dir = TempDir::new().expect("Error creating temp directory"); + let dest_tmp_dir = TempDir::new().expect("Error creating temp directory"); + + let source_dir = source_tmp_dir.path().join("source"); + create_dir(&source_dir); + std::fs::write(source_dir.join("file1.txt"), "file1"); + std::fs::write(source_dir.join("file2.txt"), "file2"); + + copy_dir_into(&source_dir, dest_tmp_dir.path()); + + assert!(dest_tmp_dir.path().join("source").exists()); + assert!(dest_tmp_dir.path().join("source/file1.txt").exists()); + assert!(dest_tmp_dir.path().join("source/file2.txt").exists()); + } + + #[test] + fn test_copy_dir_into_recursive() { + let source_tmp_dir = TempDir::new().expect("Error creating temp directory"); + let dest_tmp_dir = TempDir::new().expect("Error creating temp directory"); + + let source_dir = source_tmp_dir.path().join("source"); + create_dir(&source_dir); + std::fs::write(source_dir.join("file1.txt"), "file1"); + std::fs::write(source_dir.join("file2.txt"), "file2"); + let nested_dir = source_dir.join("nested"); + create_dir(&nested_dir); + std::fs::write(nested_dir.join("nestedfile.txt"), "nestedfile1"); + + copy_dir_into(&source_dir, dest_tmp_dir.path()); + + assert!(dest_tmp_dir.path().join("source").exists()); + assert!(dest_tmp_dir.path().join("source/file1.txt").exists()); + assert!(dest_tmp_dir.path().join("source/file2.txt").exists()); + + assert!(dest_tmp_dir.path().join("source/nested").exists()); + assert!(dest_tmp_dir.path().join("source/nested/nestedfile.txt").exists()); + } + +} \ No newline at end of file