From aab1d94388356089f198e1bc2cdb0608c6013bcb Mon Sep 17 00:00:00 2001 From: Maaz Khokhar Date: Tue, 14 Jul 2026 14:48:39 -0500 Subject: [PATCH] bug fixes, but every cmd works! --- crates/cli/src/db/mod.rs | 12 +++--- crates/cli/src/lib.rs | 89 +++++++++++++++++++++++++--------------- crates/cli/src/main.rs | 38 ++++++++--------- devenv.nix | 2 + 4 files changed, 84 insertions(+), 57 deletions(-) diff --git a/crates/cli/src/db/mod.rs b/crates/cli/src/db/mod.rs index 07465e5..ece0ca7 100644 --- a/crates/cli/src/db/mod.rs +++ b/crates/cli/src/db/mod.rs @@ -1,14 +1,16 @@ use diesel::prelude::*; use dotenvy::dotenv; -use std::env; pub mod models; pub mod schema; -pub fn establish_connection() -> SqliteConnection { +pub fn establish_connection(url: String) -> SqliteConnection { dotenv().ok(); - let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); - SqliteConnection::establish(&database_url) - .unwrap_or_else(|_| panic!("Error connecting to {}", database_url)) + let resolved_path = std::fs::canonicalize(&url) + .map(|p| p.to_string_lossy().into_owned()) + .unwrap_or(url); + + SqliteConnection::establish(&resolved_path) + .unwrap_or_else(|_| panic!("Error connecting to {}", &resolved_path)) } diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index d2e8969..bc464a0 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -112,6 +112,9 @@ pub enum Commands { #[arg(short = 's', long = "shell", default_value = "sh")] shell: Option, + + #[arg(short = 'c', long = "command")] + command: Option, }, #[command(alias = "add")] Set { @@ -194,11 +197,13 @@ pub enum ProjectCommands { Delete { name: String }, } +const DB_URL: &str = "/Users/Maaz/Documents/Git/harbor/crates/cli/harbor.db"; + pub mod interactions { - use super::db::establish_connection; - use super::db::models::Project; + use super::DB_URL; + use super::db::{establish_connection, models::Project}; use crate::Environment; - use crate::db::schema::secrets::config; + use crate::db::schema::projects::id; use diesel::dsl::{insert_into, update}; use diesel::result::{DatabaseErrorKind, Error as DieselError}; use diesel::{ExpressionMethods, OptionalExtension, QueryDsl, RunQueryDsl, SelectableHelper}; @@ -216,7 +221,7 @@ pub mod interactions { pub fn project_exists(proj_name: &str) -> Result { use super::db::schema::projects::dsl::{name, projects}; - let mut conn = establish_connection(); + let mut conn = establish_connection(DB_URL.to_string()); let existing_project = projects .filter(name.eq(proj_name)) @@ -229,7 +234,7 @@ pub mod interactions { pub fn create_project(proj_name: &str) -> Result<()> { use super::db::schema::projects::dsl::{created_at, id, name, projects}; - let mut conn = establish_connection(); + let mut conn = establish_connection(DB_URL.to_string()); if project_exists(proj_name)? { return construct_error("Project already exists"); @@ -255,7 +260,7 @@ pub mod interactions { pub fn delete_project(proj_name: &str) -> Result<()> { use super::db::schema::projects::dsl::{name, projects}; - let mut conn = establish_connection(); + let mut conn = establish_connection(DB_URL.to_string()); if !project_exists(proj_name)? { return construct_error("Project does not exist"); @@ -268,7 +273,7 @@ pub mod interactions { pub fn get_projects() -> Result> { use super::db::schema::projects::dsl::projects; - let mut conn = establish_connection(); + let mut conn = establish_connection(DB_URL.to_string()); let results = projects .select(Project::as_select()) @@ -277,18 +282,28 @@ pub mod interactions { Ok(results) } - pub fn secret_exists() -> Result { - use super::db::schema::secrets::dsl::{id, secrets}; - let mut conn = establish_connection(); + pub fn secret_exists( + proj_id: &str, + secret_name: &str, + environment: Environment, + ) -> Result { + use super::db::schema::secrets::dsl::{config, id, name, project_id, secrets}; + let mut conn = establish_connection(DB_URL.to_string()); - let existing_secret = secrets.select(id).first::(&mut conn).optional()?; + let existing_secret = secrets + .filter(project_id.eq(proj_id)) + .filter(name.eq(secret_name)) + .filter(config.eq(environment)) + .select(id) + .first::(&mut conn) + .optional()?; Ok(existing_secret.is_some()) } pub fn get_project_id(proj_name: &str) -> Result { use super::db::schema::projects::dsl::{id, name, projects}; - let mut conn = establish_connection(); + let mut conn = establish_connection(DB_URL.to_string()); let project_id = projects .filter(name.eq(proj_name)) @@ -313,27 +328,29 @@ pub mod interactions { non: crypto::Nonce, ) -> Result<()> { use super::db::schema::secrets::dsl::{ - config, created_at, name, nonce, project_id, secret, secrets, + config, created_at, id, name, nonce, project_id, secret, secrets, }; - let mut conn = establish_connection(); + let mut conn = establish_connection(DB_URL.to_string()); - if secret_exists()? { - update(secrets.filter(name.eq(secret_name))) - .set(secret.eq(secret_value)) - .execute(&mut conn)?; - } else { - insert_into(secrets) - .values(( - name.eq(secret_name), - secret.eq(secret_value), - project_id.eq(proj_id), - config.eq(conf), - nonce.eq(non.to_vec()), - created_at.eq(chrono::Utc::now().naive_utc()), - )) - .execute(&mut conn)?; + if secret_exists(proj_id, secret_name, conf)? { + return Err(Box::new(std::io::Error::new( + std::io::ErrorKind::AlreadyExists, + "Secret already exists", + ))); } + insert_into(secrets) + .values(( + id.eq(Uuid::new_v4().to_string()), + name.eq(secret_name), + secret.eq(secret_value), + project_id.eq(proj_id), + config.eq(conf), + nonce.eq(non.to_vec()), + created_at.eq(chrono::Utc::now().naive_utc()), + )) + .execute(&mut conn)?; + Ok(()) } @@ -342,7 +359,7 @@ pub mod interactions { environment: Environment, ) -> Result, Vec)>> { use super::db::schema::secrets::dsl::{config, name, nonce, project_id, secret, secrets}; - let mut conn = establish_connection(); + let mut conn = establish_connection(DB_URL.to_string()); let results = secrets .filter(project_id.eq(proj_id)) @@ -354,10 +371,16 @@ pub mod interactions { } pub fn delete_secret(secret_name: &str) -> Result<()> { - use super::db::schema::secrets::dsl::{name, secrets}; - let mut conn = establish_connection(); + use super::db::schema::secrets::dsl::{id, name, secrets}; + let mut conn = establish_connection(DB_URL.to_string()); - if !secret_exists()? { + let existing_secret = secrets + .filter(name.eq(secret_name)) + .select(id) + .first::(&mut conn) + .optional()?; + + if existing_secret.is_none() { return Err(Box::new(std::io::Error::new( std::io::ErrorKind::NotFound, "Secret does not exist", diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index d177ed7..3f2e6d0 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -45,13 +45,6 @@ fn main() { let config_path = root.join(".harbor.toml"); let has_config = config_path.exists(); - if !has_config { - eprintln!( - "{}", - "Warning: .harbor.toml not found. Some commands are disabled.".yellow() - ); - } - match cli.command { Some(c) => match c { _ if requires_config(&c) && !has_config => { @@ -223,11 +216,6 @@ fn main() { cmd.env(key, value); } - if cmd.spawn().is_err() { - eprintln!("Error executing command: {:?}", after); - process::exit(1); - } - if cmd.status().is_err() { eprintln!("Error waiting for command to finish: {:?}", after); process::exit(1); @@ -347,7 +335,11 @@ fn main() { } } }, - Commands::Shell { environment, shell } => { + Commands::Shell { + environment, + shell, + command, + } => { let config = require_config(&root); let environment: Environment = match environment { Some(env) => match env.parse::() { @@ -372,11 +364,16 @@ fn main() { let shell = shell .or_else(|| std::env::var("SHELL").ok()) - .or_else(|| Some("sh".into())) + .or_else(|| Some("/bin/sh".into())) .unwrap(); let mut cmd = process::Command::new(&shell); + if let Some(command) = command { + cmd.arg("-c"); + cmd.arg(command); + } + let secrets = match get_project_secrets(&proj_id, environment) { Ok(s) => s, Err(e) => { @@ -422,12 +419,15 @@ fn main() { cmd.env(key, value); } - if cmd.spawn().is_err() { - eprintln!("Error executing command: {:?}", &shell); - process::exit(1); - } + let mut child = match cmd.spawn() { + Ok(c) => c, + Err(_) => { + eprintln!("Error executing command: {:?}", &shell); + process::exit(1); + } + }; - if cmd.status().is_err() { + if child.wait().is_err() { eprintln!("Error waiting for command to finish: {:?}", &shell); process::exit(1); } else { diff --git a/devenv.nix b/devenv.nix index 3a8a605..b83e7da 100644 --- a/devenv.nix +++ b/devenv.nix @@ -12,6 +12,8 @@ sqlite ]; + env.RUST_BACKTRACE = "1"; + languages.rust = { enable = true; lsp.enable = true;