aboutsummaryrefslogtreecommitdiffstats
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
parentupdates to add, remove and list (diff)
add build support
-rw-r--r--Cargo.lock79
-rw-r--r--Cargo.toml2
-rw-r--r--src/action.rs67
-rw-r--r--src/config.rs25
-rw-r--r--src/main.rs1
-rw-r--r--src/util.rs22
6 files changed, 164 insertions, 32 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 44163e9..a7a747b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -38,6 +38,12 @@ dependencies = [
]
[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
name = "find-msvc-tools"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -49,6 +55,8 @@ version = "0.1.0"
dependencies = [
"git2",
"libc",
+ "serde",
+ "toml",
]
[[package]]
@@ -88,6 +96,12 @@ dependencies = [
]
[[package]]
+name = "hashbrown"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
+
+[[package]]
name = "icu_collections"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -190,6 +204,16 @@ dependencies = [
]
[[package]]
+name = "indexmap"
+version = "2.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
name = "jobserver"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -327,6 +351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
+ "serde_derive",
]
[[package]]
@@ -350,6 +375,15 @@ dependencies = [
]
[[package]]
+name = "serde_spanned"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -400,6 +434,45 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "1.0.3+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7614eaf19ad818347db24addfa201729cf2a9b6fdfd9eb0ab870fcacc606c0c"
+dependencies = [
+ "indexmap",
+ "serde_core",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_parser",
+ "toml_writer",
+ "winnow",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "1.0.0+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "toml_parser"
+version = "1.0.9+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
+dependencies = [
+ "winnow",
+]
+
+[[package]]
+name = "toml_writer"
+version = "1.0.6+spec-1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
+
+[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -439,6 +512,12 @@ dependencies = [
]
[[package]]
+name = "winnow"
+version = "0.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
+
+[[package]]
name = "wit-bindgen"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 677689f..88af1b2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,3 +6,5 @@ edition = "2024"
[dependencies]
git2 = "0.20.4"
libc = "0.2.182"
+serde = { version = "1.0.228", features = ["derive"] }
+toml = "1.0.3"
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));