stellar_scaffold_cli/commands/
update_env.rs1#![allow(clippy::struct_excessive_bools)]
2use clap::Parser;
3use std::{
4 fs,
5 io::{self, BufRead},
6};
7
8#[derive(Parser, Debug, Clone)]
9pub struct Cmd {
10 #[arg(long)]
12 pub name: String,
13 #[arg(long)]
15 pub value: Option<String>,
16 #[arg(long, default_value = ".env")]
18 pub env_file: std::path::PathBuf,
19}
20
21#[derive(thiserror::Error, Debug)]
22pub enum Error {
23 #[error(transparent)]
24 Io(#[from] io::Error),
25}
26
27impl Cmd {
28 pub fn run(&self) -> Result<(), Error> {
29 let file = &self.env_file;
30 let env_file = if file.exists() {
31 fs::read_to_string(file)?
32 } else {
33 String::new()
34 };
35
36 let value = self.value.clone().unwrap_or_else(|| {
37 std::io::stdin()
39 .lock()
40 .lines()
41 .next()
42 .expect("stdin closed")
43 .expect("stdin error")
44 });
45 let name = &self.name;
46 let new_env_file =
47 replace_lines_starting_with(&env_file, &format!("{name}="), &format!("{name}={value}"));
48 fs::write(&self.env_file, new_env_file)?;
49 Ok(())
50 }
51}
52
53fn replace_lines_starting_with(input: &str, starts_with: &str, replacement: &str) -> String {
54 let mut found = false;
55 let mut v = input
56 .lines()
57 .map(|line| {
58 if line.starts_with(starts_with) {
59 found = true;
60 replacement
61 } else {
62 line
63 }
64 })
65 .collect::<Vec<&str>>();
66 if !found {
67 v.push(replacement);
68 }
69 v.join("\n")
70}