aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar BanceDev 2026-02-26 12:40:51 -0500
committerGravatar BanceDev 2026-02-26 12:40:51 -0500
commit8c411011aadfd96e7189366f20dda87b26a50cbf (patch)
tree766b0d2e6d75c63c3fca1ffc0d3359064e83c0fe /src
parentupdates to add, remove and list (diff)
add build support
Diffstat (limited to 'src')
-rw-r--r--src/action.rs67
-rw-r--r--src/config.rs25
-rw-r--r--src/main.rs1
-rw-r--r--src/util.rs22
4 files changed, 83 insertions, 32 deletions
diff --git a/src/action.rs b/src/action.rs
index cd3b32b..b94c8b3 100644
--- a/src/action.rs
+++ b/src/action.rs
@@ -1,7 +1,11 @@
-use crate::util::{TEMP_CONFIG_PATH, create_config, dir_size, get_editor, is_root, open_in_editor, yn_prompt};
+use crate::config::Config;
+use crate::util::{
+ TEMP_CONFIG_PATH, create_config, 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";
@@ -74,6 +78,32 @@ 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());
@@ -85,10 +115,7 @@ fn add(url: &str) -> Result<(), String> {
};
let config_name = format!("{repo_name}.toml");
- println!(
- "Creating config: {}",
- config_name
- );
+ println!("Creating config: {}", config_name);
create_config(repo_name)?;
let editor = get_editor();
@@ -96,26 +123,29 @@ fn add(url: &str) -> Result<(), String> {
open_in_editor(&editor, &config_temp)?;
let clone_path = PathBuf::from(BASE_REPO_PATH).join(repo_name);
- let repo = Repository::clone(url, &clone_path).map_err(|e| {
- format!("failed to clone {}: {}", repo_name, e)
- })?;
+ let repo = Repository::clone(url, &clone_path)
+ .map_err(|e| format!("failed to clone {}: {}", repo_name, e))?;
let mut config_path = PathBuf::from(BASE_CONFIG_PATH);
if !config_path.exists() {
- fs::create_dir_all(&config_path).map_err(|e| {
- format!("failed to create config directory: {}", e)
- })?;
+ fs::create_dir_all(&config_path)
+ .map_err(|e| format!("failed to create config directory: {}", e))?;
}
config_path.push(config_name);
- fs::rename(config_temp, config_path).map_err(|e| format!("failed to place config in system directory: {}", e))?;
+ fs::rename(config_temp, &config_path)
+ .map_err(|e| format!("failed to place config in system directory: {}", e))?;
println!(
- "New package initialized at: {}",
+ "New package initialized at: {}\n",
repo.path().to_str().unwrap()
);
+ if yn_prompt("Run build and install commands?") {
+ build(config_path, clone_path)?;
+ }
+
Ok(())
}
@@ -174,12 +204,8 @@ fn remove(packages: Vec<String>) -> Result<(), String> {
if yn_prompt("Proceed with removal?") {
for (name, path, cfg_path) in package_paths {
- 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)
- })?;
+ 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);
}
}
@@ -190,7 +216,8 @@ fn remove(packages: Vec<String>) -> Result<(), String> {
fn list() -> Result<(), String> {
let config_path = Path::new(BASE_CONFIG_PATH);
for entry in fs::read_dir(config_path)
- .map_err(|e| format!("failed to iterate package directory: {}", e))? {
+ .map_err(|e| format!("failed to iterate package directory: {}", e))?
+ {
let entry = entry.map_err(|e| e.to_string())?;
let path = entry.path();
if path.is_file() {
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..f168b27
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,25 @@
+use serde::Deserialize;
+use std::fs;
+use std::path::Path;
+
+#[derive(Deserialize)]
+pub struct Config {
+ pub update: Option<String>,
+ pub build: Option<String>,
+ pub install: Option<String>,
+ pub dependencies: Option<Vec<String>>,
+}
+
+impl Config {
+ pub fn new<P: AsRef<Path>>(filepath: P) -> Option<Self> {
+ let contents = match fs::read_to_string(filepath) {
+ Ok(c) => c,
+ Err(_) => {
+ eprintln!("no package config found");
+ return None;
+ }
+ };
+ let config: Config = toml::from_str(&contents).expect("failed to parse config");
+ Some(config)
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index ff71155..fa0ee11 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,6 +4,7 @@ use std::{env, fs};
use crate::util::TEMP_CONFIG_PATH;
mod action;
+mod config;
mod util;
fn main() {
diff --git a/src/util.rs b/src/util.rs
index ae114d0..caa2c73 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,3 +1,4 @@
+use libc;
use std::env;
use std::fs;
use std::io;
@@ -5,7 +6,6 @@ use std::io::Write;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
-use libc;
pub const TEMP_CONFIG_PATH: &str = "/var/lib/forge/.tmp";
@@ -14,9 +14,8 @@ pub fn create_config(package: &str) -> Result<(), String> {
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)
- })?;
+ fs::create_dir_all(&path)
+ .map_err(|e| format!("failed to create temp config directory: {}", e))?;
}
path.push(filename);
@@ -25,14 +24,12 @@ pub fn create_config(package: &str) -> Result<(), String> {
r#"# {package} configuration
update = "tagged" # no | live | tagged
build = "make"
-dependencies = []
install = "make install"
+dependencies = []
"#
);
- fs::write(path, template).map_err(|e| {
- format!("failed to create config: {}", e)
- })?;
+ fs::write(path, template).map_err(|e| format!("failed to create config: {}", e))?;
Ok(())
}
@@ -60,13 +57,14 @@ pub fn get_editor() -> String {
}
pub fn is_root() -> bool {
- unsafe { libc::geteuid() == 0}
+ unsafe { libc::geteuid() == 0 }
}
pub fn open_in_editor(editor: &str, file: &str) -> Result<(), String> {
- let status = Command::new(editor).arg(file).status().map_err(|e| {
- format!("failed to execute editor: {}", e)
- })?;
+ let status = Command::new(editor)
+ .arg(file)
+ .status()
+ .map_err(|e| format!("failed to execute editor: {}", e))?;
if !status.success() {
return Err(format!("editor exited with non-zero status: {}", status));