diff options
| author | 2026-02-28 00:25:26 -0500 | |
|---|---|---|
| committer | 2026-02-28 00:25:26 -0500 | |
| commit | 6e5bcf444ddc8b62bbb973b5e2f3cada738a322f (patch) | |
| tree | de28e36217b9221fa582be93f2b07edca1faee69 | |
| parent | remove autoremove and update todo (diff) | |
add package collect helpers to reduce duplicity
| -rw-r--r-- | src/action.rs | 183 | ||||
| -rw-r--r-- | src/util.rs | 61 |
2 files changed, 87 insertions, 157 deletions
diff --git a/src/action.rs b/src/action.rs index fd5fe32..5ebf34a 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,12 +1,9 @@ -use crate::config::{self, Config, ConfigCommand, TEMP_CONFIG_PATH, create_config}; -use crate::util::{dir_size, get_editor, open_in_editor, pull_repo, yn_prompt}; +use crate::config::{self, Config, ConfigCommand, TEMP_CONFIG_PATH}; +use crate::util::{self, BASE_CONFIG_PATH, BASE_REPO_PATH, PackageList}; use git2::Repository; use std::fs; use std::path::PathBuf; -const BASE_REPO_PATH: &str = "/var/db/forge"; -const BASE_CONFIG_PATH: &str = "/etc/forge/packages"; - pub enum Action { Add { url: String }, Update, @@ -87,11 +84,11 @@ fn add(url: &str) -> Result<(), String> { let config_name = format!("{repo_name}.toml"); println!("Creating config: {}", config_name); - create_config(repo_name)?; + config::create_config(repo_name)?; - let editor = get_editor(); + let editor = util::get_editor(); let config_temp = format!("{}/{}", TEMP_CONFIG_PATH, config_name); - open_in_editor(&editor, &config_temp)?; + util::open_in_editor(&editor, &config_temp)?; let clone_path = PathBuf::from(BASE_REPO_PATH).join(repo_name); let repo = Repository::clone(url, &clone_path) @@ -113,7 +110,7 @@ fn add(url: &str) -> Result<(), String> { repo.path().to_str().unwrap() ); - if yn_prompt("Run build and install commands?") { + if util::yn_prompt("Run build and install commands?") { println!("Building..."); config::run_config_command(&config_path, &clone_path, ConfigCommand::Build)?; println!("Installing..."); @@ -128,41 +125,12 @@ fn update() -> Result<(), String> { return Err("update must be run as root".to_string()); } - let package_paths: Vec<(String, PathBuf)> = fs::read_dir(BASE_CONFIG_PATH) - .map_err(|e| format!("failed to iterate package directory: {}", e))? - .map(|p| { - let entry = p.map_err(|e| e.to_string())?; - let path = entry.path(); - - let pkgname = path - .file_stem() - .ok_or_else(|| format!("invalid filename: {:?}", path))? - .to_string_lossy() - .into_owned(); - - let path = PathBuf::from(BASE_REPO_PATH).join(&pkgname); - - if !path.exists() { - Err(format!("no installed package: {}", pkgname)) - } else { - Ok((pkgname, path)) - } - }) - .collect::<Result<_, _>>()?; + let package_paths = util::collect_packages()?; + util::print_collected_packages(&package_paths, "Packages to update"); - println!( - "Packages to update ({}): {}\n", - package_paths.len(), - package_paths - .iter() - .map(|(p, _)| p.as_str()) - .collect::<Vec<_>>() - .join(", ") - ); - - if yn_prompt("Proceed with update?") { - for (name, path) in package_paths { - pull_repo(&path).map_err(|e| format!("failed to update repo: {e}"))?; + if util::yn_prompt("Proceed with update?") { + for (name, path, _) in package_paths { + util::pull_repo(&path).map_err(|e| format!("failed to update repo: {e}"))?; println!("{} up to date.", name); } } @@ -172,58 +140,18 @@ fn update() -> Result<(), String> { fn upgrade(packages: Vec<String>) -> Result<(), String> { if !nix::unistd::geteuid().is_root() { - return Err("clean must be run as root".to_string()); + return Err("upgrade must be run as root".to_string()); } - let package_paths: Vec<(String, PathBuf, PathBuf)> = if packages.is_empty() { - fs::read_dir(BASE_CONFIG_PATH) - .map_err(|e| format!("failed to iterate package directory: {}", e))? - .map(|p| { - let entry = p.map_err(|e| e.to_string())?; - let path = entry.path(); - - let pkgname = path - .file_stem() - .ok_or_else(|| format!("invalid filename: {:?}", path))? - .to_string_lossy() - .into_owned(); - - let path = PathBuf::from(BASE_REPO_PATH).join(&pkgname); - let cfg_path = PathBuf::from(BASE_CONFIG_PATH).join(format!("{}.toml", &pkgname)); - - if !path.exists() || !cfg_path.exists() { - Err(format!("no installed package: {}", pkgname)) - } else { - Ok((pkgname, path, cfg_path)) - } - }) - .collect::<Result<_, _>>()? + let package_paths: PackageList = if packages.is_empty() { + util::collect_packages()? } else { - packages - .into_iter() - .map(|p| { - let path = PathBuf::from(BASE_REPO_PATH).join(&p); - let cfg_path = PathBuf::from(BASE_CONFIG_PATH).join(format!("{}.toml", p)); - if !path.exists() || !cfg_path.exists() { - Err(format!("no installed package: {}", p)) - } else { - Ok((p, path, cfg_path)) - } - }) - .collect::<Result<_, _>>()? + util::collect_named_packages(packages)? }; - println!( - "Packages to upgrade ({}): {}\n", - package_paths.len(), - package_paths - .iter() - .map(|(p, _, _)| p.as_str()) - .collect::<Vec<_>>() - .join(", ") - ); + util::print_collected_packages(&package_paths, "Packages to upgrade"); - if yn_prompt("Proceed with upgrade?") { + if util::yn_prompt("Proceed with upgrade?") { for (name, path, cfg_path) in package_paths { config::run_config_command(&cfg_path, &path, ConfigCommand::Build)?; config::run_config_command(&cfg_path, &path, ConfigCommand::Install)?; @@ -240,32 +168,13 @@ fn remove(packages: Vec<String>) -> Result<(), String> { } println!("Checking dependencies...\n"); - let package_paths: Vec<(String, PathBuf, PathBuf)> = packages - .into_iter() - .map(|p| { - let path = PathBuf::from(BASE_REPO_PATH).join(&p); - let cfg_path = PathBuf::from(BASE_CONFIG_PATH).join(format!("{}.toml", p)); - if !path.exists() || !cfg_path.exists() { - Err(format!("no installed package: {}", p)) - } else { - Ok((p, path, cfg_path)) - } - }) - .collect::<Result<_, _>>()?; + let package_paths: PackageList = util::collect_named_packages(packages)?; - println!( - "Packages to remove ({}): {}\n", - package_paths.len(), - package_paths - .iter() - .map(|(p, _, _)| p.as_str()) - .collect::<Vec<_>>() - .join(", ") - ); + util::print_collected_packages(&package_paths, "Packages to remove"); let total_size: u64 = package_paths .iter() - .map(|(_, path, _)| dir_size(path).unwrap_or(0)) + .map(|(_, path, _)| util::dir_size(path).unwrap_or(0)) .sum(); println!( @@ -273,7 +182,7 @@ fn remove(packages: Vec<String>) -> Result<(), String> { total_size as f64 / (1024.0 * 1024.0) ); - if yn_prompt("Proceed with removal?") { + if util::yn_prompt("Proceed with removal?") { for (name, path, cfg_path) in package_paths { config::run_config_command(&cfg_path, &path, ConfigCommand::Uninstall)?; fs::remove_dir_all(&path).map_err(|e| format!("failed to remove {}: {}", name, e))?; @@ -309,55 +218,15 @@ fn clean(packages: Vec<String>) -> Result<(), String> { return Err("clean must be run as root".to_string()); } - let package_paths: Vec<(String, PathBuf, PathBuf)> = if packages.is_empty() { - fs::read_dir(BASE_CONFIG_PATH) - .map_err(|e| format!("failed to iterate package directory: {}", e))? - .map(|p| { - let entry = p.map_err(|e| e.to_string())?; - let path = entry.path(); - - let pkgname = path - .file_stem() - .ok_or_else(|| format!("invalid filename: {:?}", path))? - .to_string_lossy() - .into_owned(); - - let path = PathBuf::from(BASE_REPO_PATH).join(&pkgname); - let cfg_path = PathBuf::from(BASE_CONFIG_PATH).join(format!("{}.toml", &pkgname)); - - if !path.exists() || !cfg_path.exists() { - Err(format!("no installed package: {}", pkgname)) - } else { - Ok((pkgname, path, cfg_path)) - } - }) - .collect::<Result<_, _>>()? + let package_paths: PackageList = if packages.is_empty() { + util::collect_packages()? } else { - packages - .into_iter() - .map(|p| { - let path = PathBuf::from(BASE_REPO_PATH).join(&p); - let cfg_path = PathBuf::from(BASE_CONFIG_PATH).join(format!("{}.toml", p)); - if !path.exists() || !cfg_path.exists() { - Err(format!("no installed package: {}", p)) - } else { - Ok((p, path, cfg_path)) - } - }) - .collect::<Result<_, _>>()? + util::collect_named_packages(packages)? }; - println!( - "Packages to clean ({}): {}\n", - package_paths.len(), - package_paths - .iter() - .map(|(p, _, _)| p.as_str()) - .collect::<Vec<_>>() - .join(", ") - ); + util::print_collected_packages(&package_paths, "Packages to clean"); - if yn_prompt("Proceed with cleanup?") { + if util::yn_prompt("Proceed with cleanup?") { for (name, path, cfg_path) in package_paths { config::run_config_command(&cfg_path, &path, ConfigCommand::Clean)?; println!("Cleaned {}", name); diff --git a/src/util.rs b/src/util.rs index 0958764..8508377 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,8 +4,57 @@ use std::fs; use std::io; use std::io::Write; use std::path::Path; +use std::path::PathBuf; use std::process::Command; +pub const BASE_REPO_PATH: &str = "/var/db/forge"; +pub const BASE_CONFIG_PATH: &str = "/etc/forge/packages"; +pub type PackageList = Vec<(String, PathBuf, PathBuf)>; + +pub fn collect_packages() -> Result<PackageList, String> { + let pkgs: PackageList = fs::read_dir(BASE_CONFIG_PATH) + .map_err(|e| format!("failed to iterate package directory: {}", e))? + .map(|p| { + let entry = p.map_err(|e| e.to_string())?; + let path = entry.path(); + + let pkgname = path + .file_stem() + .ok_or_else(|| format!("invalid filename: {:?}", path))? + .to_string_lossy() + .into_owned(); + + let path = PathBuf::from(BASE_REPO_PATH).join(&pkgname); + let cfg_path = PathBuf::from(BASE_CONFIG_PATH).join(format!("{}.toml", &pkgname)); + + if !path.exists() || !cfg_path.exists() { + Err(format!("no installed package: {}", pkgname)) + } else { + Ok((pkgname, path, cfg_path)) + } + }) + .collect::<Result<_, _>>()?; + + Ok(pkgs) +} + +pub fn collect_named_packages(packages: Vec<String>) -> Result<PackageList, String> { + let pkgs: PackageList = packages + .into_iter() + .map(|p| { + let path = PathBuf::from(BASE_REPO_PATH).join(&p); + let cfg_path = PathBuf::from(BASE_CONFIG_PATH).join(format!("{}.toml", p)); + if !path.exists() || !cfg_path.exists() { + Err(format!("no installed package: {}", p)) + } else { + Ok((p, path, cfg_path)) + } + }) + .collect::<Result<_, _>>()?; + + Ok(pkgs) +} + pub fn dir_size(path: &Path) -> std::io::Result<u64> { let mut size = 0; if path.is_dir() { @@ -41,6 +90,18 @@ pub fn open_in_editor(editor: &str, file: &str) -> Result<(), String> { Ok(()) } +pub fn print_collected_packages(packages: &PackageList, message: &str) { + println!( + "{message} ({}): {}\n", + packages.len(), + packages + .iter() + .map(|(p, _, _)| p.as_str()) + .collect::<Vec<_>>() + .join(", ") + ); +} + pub fn pull_repo(path: &Path) -> Result<(), git2::Error> { let repo = Repository::open(path)?; |
