aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar BanceDev 2026-02-26 16:23:29 -0500
committerGravatar BanceDev 2026-02-26 16:23:29 -0500
commitaa1b4b75d0070c417f8c02bf35588c195b2d8254 (patch)
treed2725b9a668d0587161e516160033432101b0d14
parentadd build support (diff)
proper config command handling
-rw-r--r--src/action.rs39
-rw-r--r--src/config.rs69
-rw-r--r--src/main.rs2
-rw-r--r--src/util.rs28
4 files changed, 76 insertions, 62 deletions
diff --git a/src/action.rs b/src/action.rs
index b94c8b3..1aeefb6 100644
--- a/src/action.rs
+++ b/src/action.rs
@@ -1,11 +1,8 @@
-use crate::config::Config;
-use crate::util::{
- TEMP_CONFIG_PATH, create_config, dir_size, get_editor, is_root, open_in_editor, yn_prompt,
-};
+use crate::config::{self, ConfigCommand, TEMP_CONFIG_PATH, create_config};
+use crate::util::{dir_size, get_editor, is_root, open_in_editor, yn_prompt};
use git2::Repository;
use std::fs;
use std::path::{Path, PathBuf};
-use std::process::Command;
const BASE_REPO_PATH: &str = "/var/db/forge";
const BASE_CONFIG_PATH: &str = "/etc/forge/packages";
@@ -78,32 +75,6 @@ impl Action {
}
}
-//=========================================
-// command helpers
-//=========================================
-
-fn build(config_path: PathBuf, repo_path: PathBuf) -> Result<(), String> {
- let config = Config::new(config_path);
- if let Some(bld) = config.unwrap().build {
- let status = Command::new(bld)
- .current_dir(repo_path)
- .status()
- .map_err(|e| format!("failed to execute editor: {}", e))?;
-
- if !status.success() {
- return Err(format!("editor exited with non-zero status: {}", status));
- }
- } else {
- return Err("no build command found".to_string());
- }
-
- Ok(())
-}
-
-//=========================================
-// commands
-//=========================================
-
fn add(url: &str) -> Result<(), String> {
if !is_root() {
return Err("add must be run as root".to_string());
@@ -143,7 +114,10 @@ fn add(url: &str) -> Result<(), String> {
);
if yn_prompt("Run build and install commands?") {
- build(config_path, clone_path)?;
+ println!("Building...");
+ config::run_config_command(&config_path, &clone_path, ConfigCommand::Build)?;
+ println!("Installing...");
+ config::run_config_command(&config_path, &clone_path, ConfigCommand::Install)?;
}
Ok(())
@@ -204,6 +178,7 @@ fn remove(packages: Vec<String>) -> Result<(), String> {
if 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))?;
fs::remove_file(&cfg_path).map_err(|e| format!("failed to remove {}: {}", name, e))?;
println!("Removed {}", name);
diff --git a/src/config.rs b/src/config.rs
index f168b27..7c6cf2b 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,12 +1,22 @@
use serde::Deserialize;
use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+pub const TEMP_CONFIG_PATH: &str = "/var/lib/forge/.tmp";
+
+pub enum ConfigCommand {
+ Build,
+ Install,
+ Uninstall,
+}
#[derive(Deserialize)]
pub struct Config {
pub update: Option<String>,
pub build: Option<String>,
pub install: Option<String>,
+ pub uninstall: Option<String>,
pub dependencies: Option<Vec<String>>,
}
@@ -23,3 +33,60 @@ impl Config {
Some(config)
}
}
+
+pub fn create_config(package: &str) -> Result<(), String> {
+ let filename = format!("{package}.toml");
+ let mut path = PathBuf::from(TEMP_CONFIG_PATH);
+
+ if !path.exists() {
+ fs::create_dir_all(&path)
+ .map_err(|e| format!("failed to create temp config directory: {}", e))?;
+ }
+
+ path.push(filename);
+
+ let template = format!(
+ r#"# {package} configuration
+update = "tagged" # no | live | tagged
+build = "make"
+install = "make install"
+uninstall = "make uninstall"
+dependencies = []
+ "#
+ );
+
+ fs::write(path, template).map_err(|e| format!("failed to create config: {}", e))?;
+
+ Ok(())
+}
+
+pub fn run_config_command(
+ config_path: &Path,
+ repo_path: &Path,
+ command: ConfigCommand,
+) -> Result<(), String> {
+ let config = Config::new(config_path).ok_or("config not found".to_string())?;
+ let cmd = match command {
+ ConfigCommand::Build => config.build,
+ ConfigCommand::Install => config.install,
+ ConfigCommand::Uninstall => config.uninstall,
+ };
+
+ if let Some(c) = cmd {
+ let mut parts = c.split_whitespace();
+ let cmd_base = parts.next().ok_or("empty command".to_string())?;
+ let args: Vec<&str> = parts.collect();
+
+ let status = Command::new(cmd_base)
+ .args(&args)
+ .current_dir(repo_path)
+ .status()
+ .map_err(|e| format!("failed to execute command: {}", e))?;
+
+ if !status.success() {
+ return Err(format!("command exited with non-zero status: {}", status));
+ }
+ }
+
+ Ok(())
+}
diff --git a/src/main.rs b/src/main.rs
index fa0ee11..529b875 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,7 @@
use action::Action;
use std::{env, fs};
-use crate::util::TEMP_CONFIG_PATH;
+use crate::config::TEMP_CONFIG_PATH;
mod action;
mod config;
diff --git a/src/util.rs b/src/util.rs
index caa2c73..90aacb6 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -4,36 +4,8 @@ use std::fs;
use std::io;
use std::io::Write;
use std::path::Path;
-use std::path::PathBuf;
use std::process::Command;
-pub const TEMP_CONFIG_PATH: &str = "/var/lib/forge/.tmp";
-
-pub fn create_config(package: &str) -> Result<(), String> {
- let filename = format!("{package}.toml");
- let mut path = PathBuf::from(TEMP_CONFIG_PATH);
-
- if !path.exists() {
- fs::create_dir_all(&path)
- .map_err(|e| format!("failed to create temp config directory: {}", e))?;
- }
-
- path.push(filename);
-
- let template = format!(
- r#"# {package} configuration
-update = "tagged" # no | live | tagged
-build = "make"
-install = "make install"
-dependencies = []
- "#
- );
-
- fs::write(path, template).map_err(|e| format!("failed to create config: {}", e))?;
-
- Ok(())
-}
-
pub fn dir_size(path: &Path) -> std::io::Result<u64> {
let mut size = 0;
if path.is_dir() {