diff --git a/src/installer/git/mod.rs b/src/installer/git/mod.rs index fb24230..1c31ce3 100644 --- a/src/installer/git/mod.rs +++ b/src/installer/git/mod.rs @@ -20,7 +20,7 @@ pub struct GitConfig { pub install_type: file_utils::InstallType, } -fn _get_file_url(package: &str, version: &str, git_identifiers: Vec) -> Result { +fn get_file_url(package: &str, version: &str, git_identifiers: Vec) -> Result { let git_response = git::get_git_release_by_version(package, version) .ok_or(format!("Failed to get git release"))?; @@ -39,8 +39,8 @@ fn _get_file_url(package: &str, version: &str, git_identifiers: Vec Result<(), String> { - let url = _get_file_url(config.package.as_str(), config.version.as_str(), config.git_identifiers)?; +fn install(config: GitConfig) -> Result<(), String> { + let url = get_file_url(config.package.as_str(), config.version.as_str(), config.git_identifiers)?; let filename = url.split('/').last() .ok_or(format!("Failed to get name of file"))?; @@ -57,14 +57,14 @@ fn _install(config: GitConfig) -> Result<(), String> { .to_str() .ok_or(format!("Failed to get extracted folder"))?; - file_utils::install(extractor_package_temp_folder_str, config.install_type).ok_or(format!("Failed to install"))?; + file_utils::install(extractor_package_temp_folder_str, config.package.as_str(), config.install_type).ok_or(format!("Failed to install"))?; Ok(()) } pub fn process(config: GitConfig, config_mode: configure::ConfigMode) -> Result<(), String> { match config_mode { - configure::ConfigMode::INSTALL => _install(config), + configure::ConfigMode::INSTALL => install(config), configure::ConfigMode::UNINSTALL => Err(format!("not yet implemented")), } } \ No newline at end of file diff --git a/src/installer/utils/configure/common.rs b/src/installer/utils/configure/common.rs index 8756ae3..db809ae 100644 --- a/src/installer/utils/configure/common.rs +++ b/src/installer/utils/configure/common.rs @@ -9,7 +9,7 @@ fn folder_exist(folder: &str) -> bool { } pub fn configure_folder(mode: &ConfigMode) -> Option<()> { - let binary_folder_path = file_utils::get_install_dir(file_utils::InstallType::Root).ok()?; + let binary_folder_path = file_utils::get_install_dir(&file_utils::InstallType::Root).ok()?; let binary_folder_str = binary_folder_path.to_str()?; match mode { diff --git a/src/installer/utils/configure/windows/env.rs b/src/installer/utils/configure/windows/env.rs index d4c1a8a..2eaaf80 100644 --- a/src/installer/utils/configure/windows/env.rs +++ b/src/installer/utils/configure/windows/env.rs @@ -17,7 +17,7 @@ pub fn configure_env(mode: &ConfigMode) -> Option<()> { let hklm = RegKey::predef(HKEY_CURRENT_USER); let environment = hklm.open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE).ok()?; let mut reg_value : String = environment.get_value("PATH").ok()?; - let binary_folder_path = file_utils::get_install_dir(file_utils::InstallType::Command).ok()?; + let binary_folder_path = file_utils::get_install_dir(&file_utils::InstallType::Command).ok()?; let binary_folder_str = binary_folder_path.to_str()?; match mode { diff --git a/src/installer/utils/file_utils/binary_utils.rs b/src/installer/utils/file_utils/binary_utils.rs new file mode 100644 index 0000000..ca26652 --- /dev/null +++ b/src/installer/utils/file_utils/binary_utils.rs @@ -0,0 +1,56 @@ +use std::env::consts; +use std::path::PathBuf; +use std::fs; + +#[cfg(target_os = "windows")] +use std::os::windows::fs::symlink_file; + +fn file_is_executable(path: &PathBuf) -> bool { + if consts::FAMILY == "windows" { + match path.extension() { + Some(ext) => { + let extension = match ext.to_str() { + Some(r) => r, + None => "" + }; + match extension { + "bat" | "exe" | "ps1" => true, + _ => false, + } + }, + None => false + } + } else { + todo!() + } +} + +fn get_binary_files(install_package_folder: &PathBuf) -> Result, String> { + let mut files: Vec = vec![]; + let paths = fs::read_dir(install_package_folder).map_err(|_| format!("Failed to get binary files"))?; + + for path_result in paths { + let path = path_result.map_err(|_| format!("Failed to get file"))?; + let metadata = path.metadata().map_err(|_| format!("Failed to get metadata"))?; + if metadata.is_file() && file_is_executable(&path.path()) { + files.push(path.path().clone()); + } + } + + Ok(files) +} + +pub fn create_symlink_of_binary_files(install_package_folder: &PathBuf, binary_package_folder: &PathBuf) -> Result<(), String> { + let files = get_binary_files(install_package_folder)?; + + fs::create_dir_all(&binary_package_folder).map_err(|_| format!("Failed to create bin folder"))?; + + for file in files { + let output_path = binary_package_folder.join(file.file_name().ok_or(format!("Failed to get filename"))?); + + #[cfg(target_os = "windows")] + symlink_file(file.as_os_str(), output_path.as_os_str()).map_err(|_| format!("Failed to create symlink"))?; + } + + Ok(()) +} \ No newline at end of file diff --git a/src/installer/utils/file_utils.rs b/src/installer/utils/file_utils/mod.rs similarity index 52% rename from src/installer/utils/file_utils.rs rename to src/installer/utils/file_utils/mod.rs index 3a0c1aa..782d529 100644 --- a/src/installer/utils/file_utils.rs +++ b/src/installer/utils/file_utils/mod.rs @@ -1,3 +1,5 @@ +mod binary_utils; + use std::path::{PathBuf, Path}; use std::{io, fs}; @@ -7,7 +9,7 @@ pub enum InstallType { Root } -pub fn get_install_dir(install_type: InstallType) -> Result { +pub fn get_install_dir(install_type: &InstallType) -> Result { let home_dir = dirs::home_dir() .ok_or(format!("Failed to get home_directory"))?; @@ -20,6 +22,12 @@ pub fn get_install_dir(install_type: InstallType) -> Result { Ok(home_dir.join(super::INSTALL_FOLDER).join(subfolder)) } +pub fn get_packages_dir(package: &str) -> Result { + let home_dir = dirs::home_dir() + .ok_or(format!("Failed to get home_directory"))?; + Ok(home_dir.join(super::INSTALL_FOLDER).join(super::PACKAGE_FOLDER).join(package)) +} + fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> io::Result<()> { fs::create_dir_all(&dst)?; for entry in fs::read_dir(src)? { @@ -34,10 +42,17 @@ fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> io::Result<()> Ok(()) } -pub fn install(source_path: &str, install_type: InstallType) -> Option <()> { +pub fn install(source_path: &str, package: &str, install_type: InstallType) -> Option <()> { let source_folder = std::path::Path::new(super::TEMP_FOLDER).join(source_path); + let package_folder = get_packages_dir(package).ok()?; - let install_folder = get_install_dir(install_type).ok()?; - copy_dir_all(source_folder, install_folder).ok()?; - Some(()) + copy_dir_all(source_folder, package_folder.clone()).ok()?; + + let install_folder = get_install_dir(&install_type).ok()?; + + match install_type { + InstallType::Command => binary_utils::create_symlink_of_binary_files(&package_folder, &install_folder).ok(), + InstallType::Config => todo!(), + InstallType::Root => todo!(), + } } \ No newline at end of file diff --git a/src/installer/utils/mod.rs b/src/installer/utils/mod.rs index 2a1768a..3f50e45 100644 --- a/src/installer/utils/mod.rs +++ b/src/installer/utils/mod.rs @@ -1,5 +1,6 @@ pub(self) static TEMP_FOLDER: &str = "temp"; pub(self) static INSTALL_FOLDER: &str = ".autoconfig"; +pub(self) static PACKAGE_FOLDER : &str = "packages"; pub mod downloader; pub mod extractor;