Skip to content

Commit e2e8c09

Browse files
use and remove commands: restore .env from vault, delete projects
1 parent d08ada3 commit e2e8c09

4 files changed

Lines changed: 112 additions & 2 deletions

File tree

src/cli/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ pub mod init;
22
pub mod add;
33
pub mod add_auto;
44
pub mod list;
5+
pub mod use_project;
6+
pub mod remove;
57
use clap::{Parser, Subcommand};
68

79
#[derive(Parser)]

src/cli/remove.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use anyhow::{Context, Result};
2+
use colored::Colorize;
3+
use std::io::{self, Write};
4+
5+
use crate::crypto;
6+
use crate::vault;
7+
8+
pub fn handle_remove(name: &str) -> Result<()> {
9+
let password = crypto::prompt_existing_password()?;
10+
let conn = vault::open_vault(&password)
11+
.context("Failed to open vault")?;
12+
13+
// Check project exists
14+
let project = vault::project::get_project(&conn, name)?;
15+
let var_count = vault::project::count_variables(&conn, &project.id)?;
16+
17+
// Confirm deletion
18+
print!(
19+
"Delete project {} ({} variables)? [y/N]: ",
20+
name.cyan().bold(),
21+
var_count
22+
);
23+
io::stdout().flush()?;
24+
25+
let mut input = String::new();
26+
io::stdin().read_line(&mut input)?;
27+
28+
if input.trim().to_lowercase() != "y" {
29+
println!("Cancelled.");
30+
return Ok(());
31+
}
32+
33+
vault::project::delete_project(&conn, name)?;
34+
35+
println!(
36+
"{} Removed project {} and {} variables",
37+
"Done.".green().bold(),
38+
name.cyan(),
39+
var_count
40+
);
41+
42+
Ok(())
43+
}

src/cli/use_project.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use anyhow::{Context, Result};
2+
use colored::Colorize;
3+
use std::collections::BTreeMap;
4+
use std::env;
5+
6+
use crate::crypto;
7+
use crate::env_parser;
8+
use crate::vault;
9+
10+
pub fn handle_use(project_name: &str) -> Result<()> {
11+
let password = crypto::prompt_existing_password()?;
12+
let conn = vault::open_vault(&password)
13+
.context("Failed to open vault")?;
14+
let enc_key = vault::get_encryption_key(&conn, &password)?;
15+
16+
// Get the project
17+
let project = vault::project::get_project(&conn, project_name)?;
18+
19+
// Get all variables
20+
let variables = vault::variable::get_variables(&conn, &project.id)?;
21+
22+
if variables.is_empty() {
23+
println!(
24+
"{} Project {} has no variables.",
25+
"Warning:".yellow(),
26+
project_name.cyan()
27+
);
28+
return Ok(());
29+
}
30+
31+
// Decrypt all values
32+
let mut vars = BTreeMap::new();
33+
for var in &variables {
34+
let decrypted = crypto::decrypt_value(&enc_key, &var.encrypted_value)
35+
.context(format!("Failed to decrypt variable: {}", var.key))?;
36+
vars.insert(var.key.clone(), decrypted);
37+
}
38+
39+
// Write .env to current directory
40+
let cwd = env::current_dir().context("Could not determine current directory")?;
41+
let env_path = cwd.join(".env");
42+
43+
// Warn if .env already exists
44+
if env_path.exists() {
45+
println!(
46+
"{} Existing .env file will be overwritten.",
47+
"Warning:".yellow()
48+
);
49+
}
50+
51+
env_parser::write_env_file(&env_path, &vars)?;
52+
53+
// Update last_used_at
54+
vault::project::touch_project(&conn, project_name)?;
55+
56+
println!(
57+
"{} Wrote {} variables to .env",
58+
"Done.".green().bold(),
59+
variables.len()
60+
);
61+
62+
Ok(())
63+
}

src/main.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ fn main() -> Result<()> {
1818
Commands::Add { name } => cli::add::handle_add(&name)?,
1919
Commands::AddAuto => cli::add_auto::handle_add_auto()?,
2020
Commands::List => cli::list::handle_list()?,
21+
Commands::Use { project } => cli::use_project::handle_use(&project)?,
22+
Commands::Remove { name } => cli::remove::handle_remove(&name)?,
2123

2224
// placeholder commands for now - will implement later
2325
Commands::Migrate => println!("dotkeep migrate: upgrading schema..."),
@@ -26,12 +28,12 @@ fn main() -> Result<()> {
2628
// Commands::Add { name } => println!("dotkeep add: scanning .env for {}...", name),
2729
// Commands::AddAuto => println!("dotkeep add-auto: detecting project..."),
2830
// Commands::List => println!("dotkeep list: showing all projects..."),
29-
Commands::Remove { name } => println!("dotkeep remove: deleting {}...", name),
31+
// Commands::Remove { name } => println!("dotkeep remove: deleting {}...", name),
3032
Commands::Inspect { name } => println!("dotkeep inspect: showing {}...", name),
3133
Commands::Diff { project1, project2 } => {
3234
println!("dotkeep diff: comparing {} vs {}...", project1, project2);
3335
}
34-
Commands::Use { project } => println!("dotkeep use: writing .env for {}...", project),
36+
// Commands::Use { project } => println!("dotkeep use: writing .env for {}...", project),
3537
Commands::Status => println!("dotkeep status: showing active project..."),
3638
Commands::Recent => println!("dotkeep recent: showing recent projects..."),
3739
Commands::Search { key } => println!("dotkeep search: finding {}...", key),

0 commit comments

Comments
 (0)