use crate::config::{ModToml, Module}; use crate::prompt::multi_select; #[derive(Debug)] struct NamedModule(String, Module); impl ToString for NamedModule { fn to_string(&self) -> String { self.0.clone() } } fn install_mod(m: NamedModule) { let spinner = indicatif::ProgressBar::new_spinner().with_message(format!("Installing module {}...", m.0)); 'content_iter: for entry in m.1.content { let src = std::path::Path::new("repo").join(&entry.0); if src.is_file() { if let Err(err) = std::fs::copy(src, entry.1) { println!("Failed to copy {}:\n{}", entry.0, err); } spinner.tick(); } else { let dst = std::path::Path::new(entry.1.as_str()); if let Err(err) = std::fs::create_dir_all(dst) { println!("Failed to create directory {}:\n{}", entry.1, err); continue 'content_iter; } let to_remove = match crate::utils::get_dir_content_filtered(dst, &m.1.ignore) { Ok(v) => v, Err(err) => { println!("Failed to get destination content:\n{}", err); continue 'content_iter; } }; for file in to_remove.files { let _ = std::fs::remove_file(file); spinner.tick(); } for dir in to_remove.directories.into_iter().rev() { let _ = std::fs::remove_dir(dir); spinner.tick(); } if let Err(err) = crate::utils::copy_dir(&src, dst, &spinner) { println!("Failed to copy directory:\n{}", err); } } } } fn collect_mod(m: NamedModule) { let spinner = indicatif::ProgressBar::new_spinner().with_message(format!("Collecting module {}...", m.0)); 'content_iter: for entry in m.1.content { let dst = std::path::Path::new("repo").join(entry.0.as_str()); let src = std::path::Path::new(entry.1.as_str()); if src.is_file() { if let Err(err) = std::fs::copy(src, dst) { println!("Failed to copy {}:\n{}", entry.1, err); } spinner.tick(); } else { let _ = std::fs::remove_dir_all(&dst); if let Err(err) = std::fs::create_dir_all(&dst) { println!("Failed to create directory {}:\n{}", entry.0, err); continue 'content_iter; } let to_copy = match crate::utils::get_dir_content_filtered(src, &m.1.ignore) { Ok(v) => crate::utils::trim_dir_content(v, src), Err(err) => { println!("Failed to get source content:\n{}", err); continue 'content_iter; } }; for dir in to_copy.directories { std::fs::create_dir_all(dst.join(dir)).unwrap(); spinner.tick(); } for file in to_copy.files { std::fs::copy(src.join(&file), dst.join(&file)).unwrap(); spinner.tick(); } } } } pub fn install(config: &ModToml) { let to_install = multi_select( Some("Which modules do you want to install?"), config.modules.iter().map(|v| NamedModule(v.0.clone(), v.1.clone())).collect() ); for m in to_install { install_mod(m); } } pub fn collect(config: &ModToml) { let to_collect = multi_select( Some("Which modules do you want to collect?"), config.modules.iter().map(|v| NamedModule(v.0.clone(), v.1.clone())).collect() ); for m in to_collect { collect_mod(m); } } pub fn upload() { if !crate::repository::is_clean() { let msg = crate::prompt::input("Commit message"); if !crate::repository::commit_changes(&msg) { println!("Failed to commit"); return; } } if !crate::repository::push_repo() { println!("Failed to push to origin"); } }