aboutsummaryrefslogtreecommitdiffstats
path: root/src/action.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/action.rs105
1 files changed, 76 insertions, 29 deletions
diff --git a/src/action.rs b/src/action.rs
index 55e5685..63e8676 100644
--- a/src/action.rs
+++ b/src/action.rs
@@ -1,5 +1,10 @@
+use crate::util::{self, yn_prompt};
+use git2::Repository;
+use std::fs;
+use std::path::PathBuf;
+
pub enum Action {
- Add { repo: String },
+ Add { url: String },
Update,
Upgrade { packages: Vec<String> },
Autoremove,
@@ -12,16 +17,12 @@ pub enum Action {
impl Action {
pub fn parse(args: &[String]) -> Result<Self, String> {
- let cmd = args.get(1)
- .ok_or("no command provided")?
- .as_str();
+ let cmd = args.get(1).ok_or("no command provided")?.as_str();
match cmd {
"add" => {
- let repo = args.get(2)
- .ok_or("add requires <repo>")?
- .clone();
- Ok(Action::Add { repo })
+ let url = args.get(2).ok_or("add requires <repo>")?.clone();
+ Ok(Action::Add { url })
}
"update" => Ok(Action::Update),
"upgrade" => {
@@ -40,9 +41,7 @@ impl Action {
}
"list" => Ok(Action::List),
"search" => {
- let term = args.get(2)
- .ok_or("search requires <term>")?
- .clone();
+ let term = args.get(2).ok_or("search requires <term>")?.clone();
Ok(Action::Search { term })
}
"clean" => {
@@ -50,32 +49,42 @@ impl Action {
Ok(Action::Clean { packages })
}
"show" => {
- let package = args.get(2)
- .ok_or("show requires <package>")?
- .clone();
+ let package = args.get(2).ok_or("show requires <package>")?.clone();
Ok(Action::Show { package })
}
_ => Err(format!("unknown command {}", cmd)),
}
}
- pub fn execute(self) {
+ pub fn execute(self) -> Result<(), String> {
match self {
- Action::Add { repo } => add(repo),
- Action::Update => update(),
- Action::Upgrade { packages } => upgrade(packages),
- Action::Autoremove => autoremove(),
+ Action::Add { url } => add(url.as_str()),
+ Action::Update => Ok(update()),
+ Action::Upgrade { packages } => Ok(upgrade(packages)),
+ Action::Autoremove => Ok(autoremove()),
Action::Remove { packages } => remove(packages),
- Action::List => list(),
- Action::Search { term } => search(term),
- Action::Clean { packages } => clean(packages),
- Action::Show { package } => show(package),
+ Action::List => Ok(list()),
+ Action::Search { term } => Ok(search(term)),
+ Action::Clean { packages } => Ok(clean(packages)),
+ Action::Show { package } => Ok(show(package)),
}
}
}
-fn add(repo: String) {
- println!("adding {}", repo);
+fn add(url: &str) -> Result<(), String> {
+ let base_path = "/var/lib/forge";
+ let repo_name = {
+ let last_segment = url.rsplit('/').next().unwrap_or(url);
+ last_segment.strip_suffix(".git").unwrap_or(last_segment)
+ };
+ let clone_path = PathBuf::from(base_path).join(repo_name);
+ let repo = Repository::clone(url, &clone_path)
+ .map_err(|e| format!("failed to clone {}: {}", repo_name, e))?;
+ println!(
+ "new package initialized at: {}",
+ repo.path().to_str().unwrap()
+ );
+ Ok(())
}
fn update() {
@@ -92,10 +101,49 @@ fn autoremove() {
println!("autoremoving");
}
-fn remove(packages: Vec<String>) {
- for (_, p) in packages.iter().enumerate() {
- println!("removing: {}", p);
+fn remove(packages: Vec<String>) -> Result<(), String> {
+ let base_path = "/var/lib/forge";
+ println!("checking dependencies...\n");
+ let package_paths: Vec<(String, PathBuf)> = packages
+ .into_iter()
+ .map(|p| {
+ let path = PathBuf::from(base_path).join(&p);
+ if !path.exists() {
+ Err(format!("no installed package: {}", p))
+ } else {
+ Ok((p, path))
+ }
+ })
+ .collect::<Result<_, _>>()?; // propagates the first error
+
+ println!(
+ "Packages to remove ({}): {}\n",
+ package_paths.len(),
+ package_paths
+ .iter()
+ .map(|(p, _)| p.as_str())
+ .collect::<Vec<_>>()
+ .join(", ")
+ );
+
+ let total_size: u64 = package_paths
+ .iter()
+ .map(|(_, path)| util::dir_size(path).unwrap_or(0))
+ .sum();
+
+ println!(
+ "Total remove size: {:.2} MB\n",
+ total_size as f64 / (1024.0 * 1024.0)
+ );
+
+ if yn_prompt("Proceed with removal?") {
+ for (name, path) in package_paths {
+ fs::remove_dir_all(&path).map_err(|e| format!("failed to remove {}: {}", name, e))?;
+ println!("Removed {}", name);
+ }
}
+
+ Ok(())
}
fn list() {
@@ -115,4 +163,3 @@ fn clean(packages: Vec<String>) {
fn show(package: String) {
println!("showing {}", package);
}
-