aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar BanceDev 2026-02-25 20:44:04 -0500
committerGravatar BanceDev 2026-02-25 20:44:04 -0500
commit2b702a8b91588873a663ecd9af249e1dc1a47160 (patch)
tree6e7d693a066dbe762f6a9a5d53b9315333824a09
parentinitial commit (diff)
begin work on add and remove
-rw-r--r--Cargo.lock520
-rw-r--r--Cargo.toml1
-rw-r--r--justfile28
-rw-r--r--src/action.rs105
-rw-r--r--src/main.rs12
-rw-r--r--src/util.rs37
6 files changed, 671 insertions, 32 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bc3b2c3..9d05e26 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,5 +3,525 @@
version = 4
[[package]]
+name = "bitflags"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
+
+[[package]]
+name = "cc"
+version = "1.2.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
+dependencies = [
+ "find-msvc-tools",
+ "jobserver",
+ "libc",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+
+[[package]]
name = "forge"
version = "0.1.0"
+dependencies = [
+ "git2",
+]
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasip2",
+]
+
+[[package]]
+name = "git2"
+version = "0.20.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b"
+dependencies = [
+ "bitflags",
+ "libc",
+ "libgit2-sys",
+ "log",
+ "openssl-probe",
+ "openssl-sys",
+ "url",
+]
+
+[[package]]
+name = "icu_collections"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
+dependencies = [
+ "displaydoc",
+ "potential_utf",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locale_core"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
+dependencies = [
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
+
+[[package]]
+name = "icu_properties"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
+dependencies = [
+ "icu_collections",
+ "icu_locale_core",
+ "icu_properties_data",
+ "icu_provider",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
+
+[[package]]
+name = "icu_provider"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
+dependencies = [
+ "displaydoc",
+ "icu_locale_core",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerotrie",
+ "zerovec",
+]
+
+[[package]]
+name = "idna"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
+]
+
+[[package]]
+name = "jobserver"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
+dependencies = [
+ "getrandom",
+ "libc",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.182"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
+
+[[package]]
+name = "libgit2-sys"
+version = "0.18.3+1.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487"
+dependencies = [
+ "cc",
+ "libc",
+ "libssh2-sys",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+]
+
+[[package]]
+name = "libssh2-sys"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9"
+dependencies = [
+ "cc",
+ "libc",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "libz-sys"
+version = "1.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4735e9cbde5aac84a5ce588f6b23a90b9b0b528f6c5a8db8a4aff300463a0839"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "litemap"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
+
+[[package]]
+name = "log"
+version = "0.4.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.111"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+
+[[package]]
+name = "potential_utf"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
+dependencies = [
+ "zerovec",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "serde"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.228"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tinystr"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "url"
+version = "2.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+ "serde",
+]
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "wasip2"
+version = "1.0.2+wasi-0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
+
+[[package]]
+name = "writeable"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
+
+[[package]]
+name = "yoke"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
+dependencies = [
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerotrie"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+]
+
+[[package]]
+name = "zerovec"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/Cargo.toml b/Cargo.toml
index fe3d98d..ffc8c30 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+git2 = "0.20.4"
diff --git a/justfile b/justfile
new file mode 100644
index 0000000..d944b13
--- /dev/null
+++ b/justfile
@@ -0,0 +1,28 @@
+name := 'forge'
+
+rootdir := ''
+prefix := '/usr'
+
+base-dir := absolute_path(clean(rootdir / prefix))
+
+bin-src := 'target' / 'release' / name
+bin-dst := base-dir / 'bin' / name
+
+default: build-release
+
+clean:
+ cargo clean
+
+build-debug *args:
+ cargo build {{args}}
+
+build-release *args: (build-debug '--release' args)
+
+run *args:
+ env RUST_BACKTRACE=full cargo run --release {{args}}
+
+install:
+ install -Dm0755 {{bin-src}} {{bin-dst}}
+
+uninstall:
+ rm {{bin-dst}}
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);
}
-
diff --git a/src/main.rs b/src/main.rs
index e9bb749..ab6f558 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,13 +1,19 @@
-use std::env;
use action::Action;
+use std::env;
mod action;
+mod util;
-fn main() {
+fn main() -> std::io::Result<()> {
let args: Vec<String> = env::args().collect();
match Action::parse(&args) {
- Ok(action) => action.execute(),
+ Ok(action) => {
+ if let Err(e) = action.execute() {
+ eprintln!("forge: {}", e);
+ }
+ }
Err(e) => eprintln!("forge: {}", e),
}
+ Ok(())
}
diff --git a/src/util.rs b/src/util.rs
new file mode 100644
index 0000000..c3d573c
--- /dev/null
+++ b/src/util.rs
@@ -0,0 +1,37 @@
+use std::fs;
+use std::io;
+use std::io::Write;
+use std::path::Path;
+
+pub fn dir_size(path: &Path) -> std::io::Result<u64> {
+ let mut size = 0;
+ if path.is_dir() {
+ for entry in fs::read_dir(path)? {
+ let entry = entry?;
+ let metadata = entry.metadata()?;
+ if metadata.is_file() {
+ size += metadata.len();
+ } else if metadata.is_dir() {
+ size += dir_size(&entry.path())?;
+ }
+ }
+ }
+ Ok(size)
+}
+
+pub fn yn_prompt(prompt: &str) -> bool {
+ print!("{} [y/n]: ", prompt);
+ io::stdout().flush().unwrap();
+
+ // Read input from user
+ let mut input = String::new();
+ io::stdin().read_line(&mut input).unwrap();
+
+ // Normalize input
+ let input = input.trim().to_lowercase();
+
+ match input.as_str() {
+ "y" | "yes" | "" => true,
+ _ => false,
+ }
+}