aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar BanceDev 2026-02-25 00:25:07 -0500
committerGravatar BanceDev 2026-02-25 00:25:07 -0500
commit337647e9dfd21a5d319530e600b015c70ac64294 (patch)
treebb7746c7fccf643778c90f862555ac37539cbee9
initial commit
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml6
-rw-r--r--LICENSE19
-rw-r--r--README.md46
-rw-r--r--src/action.rs118
-rw-r--r--src/main.rs13
7 files changed, 210 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..bc3b2c3
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "forge"
+version = "0.1.0"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..fe3d98d
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "forge"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ac4bbee
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2026 Lance Borden
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d61d002
--- /dev/null
+++ b/README.md
@@ -0,0 +1,46 @@
+# Package Manager
+
+## Usage
+
+forge add <repo>
+
+creates a config for the package based on the repo name.
+
+#TODO: handle namespace conflict
+
+config options:
+
+update = <no, live, tagged>
+build = "build command"
+install = "install command"
+uninstall = "uninstall command"
+clean = "clean command"
+deps = ["named list of deps"]
+
+forge update
+
+pulls latest for all tracked packages per update rules
+
+forge upgrade [pkgnames]
+
+If no names are provided assume all otherwise do build and install on named packages
+
+forge remove [pkgnames]
+
+Removes named packages and orphaned deps
+
+forge list
+
+lists all packages currently tracked
+
+forge search [term]
+
+lists packages with the given substring not case sensitive
+
+forge clean [pkgnames]
+
+runs the clean command on every tracked package or named
+
+forge show [pkgname]
+
+shows the configured info about the package
diff --git a/src/action.rs b/src/action.rs
new file mode 100644
index 0000000..55e5685
--- /dev/null
+++ b/src/action.rs
@@ -0,0 +1,118 @@
+pub enum Action {
+ Add { repo: String },
+ Update,
+ Upgrade { packages: Vec<String> },
+ Autoremove,
+ Remove { packages: Vec<String> },
+ List,
+ Search { term: String },
+ Clean { packages: Vec<String> },
+ Show { package: String },
+}
+
+impl Action {
+ pub fn parse(args: &[String]) -> Result<Self, String> {
+ 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 })
+ }
+ "update" => Ok(Action::Update),
+ "upgrade" => {
+ let packages = args[2..].to_vec();
+ Ok(Action::Upgrade { packages })
+ }
+ "autoremove" => Ok(Action::Autoremove),
+ "remove" => {
+ let packages = args[2..].to_vec();
+
+ if packages.is_empty() {
+ Err("remove requires a package".into())
+ } else {
+ Ok(Action::Remove { packages })
+ }
+ }
+ "list" => Ok(Action::List),
+ "search" => {
+ let term = args.get(2)
+ .ok_or("search requires <term>")?
+ .clone();
+ Ok(Action::Search { term })
+ }
+ "clean" => {
+ let packages = args[2..].to_vec();
+ Ok(Action::Clean { packages })
+ }
+ "show" => {
+ let package = args.get(2)
+ .ok_or("show requires <package>")?
+ .clone();
+ Ok(Action::Show { package })
+ }
+ _ => Err(format!("unknown command {}", cmd)),
+ }
+ }
+
+ pub fn execute(self) {
+ match self {
+ Action::Add { repo } => add(repo),
+ Action::Update => update(),
+ Action::Upgrade { packages } => upgrade(packages),
+ Action::Autoremove => autoremove(),
+ Action::Remove { packages } => remove(packages),
+ Action::List => list(),
+ Action::Search { term } => search(term),
+ Action::Clean { packages } => clean(packages),
+ Action::Show { package } => show(package),
+ }
+ }
+}
+
+fn add(repo: String) {
+ println!("adding {}", repo);
+}
+
+fn update() {
+ println!("updating");
+}
+
+fn upgrade(packages: Vec<String>) {
+ for (_, p) in packages.iter().enumerate() {
+ println!("upgrading: {}", p);
+ }
+}
+
+fn autoremove() {
+ println!("autoremoving");
+}
+
+fn remove(packages: Vec<String>) {
+ for (_, p) in packages.iter().enumerate() {
+ println!("removing: {}", p);
+ }
+}
+
+fn list() {
+ println!("listing");
+}
+
+fn search(term: String) {
+ println!("searching: {}", term);
+}
+
+fn clean(packages: Vec<String>) {
+ for (_, p) in packages.iter().enumerate() {
+ println!("cleaning: {}", p);
+ }
+}
+
+fn show(package: String) {
+ println!("showing {}", package);
+}
+
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..e9bb749
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,13 @@
+use std::env;
+use action::Action;
+
+mod action;
+
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ match Action::parse(&args) {
+ Ok(action) => action.execute(),
+ Err(e) => eprintln!("forge: {}", e),
+ }
+}