generated from pure_sagacity/rust-starter
added color
This commit is contained in:
+75
-53
@@ -18,6 +18,10 @@ use crypto::encrypt;
|
|||||||
|
|
||||||
const GIT_VERSION: &str = env!("GIT_VERSION");
|
const GIT_VERSION: &str = env!("GIT_VERSION");
|
||||||
|
|
||||||
|
fn print_error(message: impl std::fmt::Display) {
|
||||||
|
eprintln!("{}", message.to_string().bright_red().bold());
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
use cli::{Commands, ProjectCommands};
|
use cli::{Commands, ProjectCommands};
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
@@ -37,7 +41,7 @@ fn main() {
|
|||||||
let root = match std::env::current_dir() {
|
let root = match std::env::current_dir() {
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("Error resolving current directory: {}", err);
|
print_error(format!("Error resolving current directory: {}", err));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -48,10 +52,7 @@ fn main() {
|
|||||||
match cli.command {
|
match cli.command {
|
||||||
Some(c) => match c {
|
Some(c) => match c {
|
||||||
_ if requires_config(&c) && !has_config => {
|
_ if requires_config(&c) && !has_config => {
|
||||||
eprintln!(
|
print_error("Missing .harbor.toml. Run `harbor config create` first.");
|
||||||
"{}",
|
|
||||||
"Missing .harbor.toml. Run `harbor config create` first.".yellow()
|
|
||||||
);
|
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
Commands::Set { environment, vars } => {
|
Commands::Set { environment, vars } => {
|
||||||
@@ -60,7 +61,7 @@ fn main() {
|
|||||||
Some(env) => match env.parse::<Environment>() {
|
Some(env) => match env.parse::<Environment>() {
|
||||||
Ok(parsed) => parsed,
|
Ok(parsed) => parsed,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("Invalid environment '{}'.", env);
|
print_error(format!("Invalid environment '{}'.", env));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -70,20 +71,23 @@ fn main() {
|
|||||||
let pairs = match cli::parse_secret_pairs(&vars) {
|
let pairs = match cli::parse_secret_pairs(&vars) {
|
||||||
Ok(pairs) => pairs,
|
Ok(pairs) => pairs,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error parsing secrets: {}", e);
|
print_error(format!("Error parsing secrets: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if pairs.is_empty() {
|
if pairs.is_empty() {
|
||||||
eprintln!("No secrets provided. Use KEY=VALUE pairs.");
|
print_error("No secrets provided. Use KEY=VALUE pairs.");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let project = match get_project_id(&config.name) {
|
let project = match get_project_id(&config.name) {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Unable to get project ID for '{}': {}", config.name, e);
|
print_error(format!(
|
||||||
|
"Unable to get project ID for '{}': {}",
|
||||||
|
config.name, e
|
||||||
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -92,21 +96,27 @@ fn main() {
|
|||||||
let key = match gen_or_get_key() {
|
let key = match gen_or_get_key() {
|
||||||
Ok(k) => k,
|
Ok(k) => k,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("Error generating or getting key");
|
print_error("Error generating or getting key");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let (nonce, encrypted) = match encrypt(&key, pair.1.as_bytes().to_vec()) {
|
let (nonce, encrypted) = match encrypt(&key, pair.1.as_bytes().to_vec()) {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error encrypting secret for key '{}': {}", pair.0, e);
|
print_error(format!(
|
||||||
|
"Error encrypting secret for key '{}': {}",
|
||||||
|
pair.0, e
|
||||||
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match set_secret(&project, &pair.0, encrypted, environment, nonce) {
|
match set_secret(&project, &pair.0, encrypted, environment, nonce) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error setting secret for key '{}': {}", pair.0, e);
|
print_error(format!(
|
||||||
|
"Error setting secret for key '{}': {}",
|
||||||
|
pair.0, e
|
||||||
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +136,7 @@ fn main() {
|
|||||||
let cleaned = cleaned;
|
let cleaned = cleaned;
|
||||||
|
|
||||||
if cleaned.is_empty() {
|
if cleaned.is_empty() {
|
||||||
eprintln!("No secret keys provided. Use one or more keys.");
|
print_error("No secret keys provided. Use one or more keys.");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +146,7 @@ fn main() {
|
|||||||
println!("Deleted secret for key '{}'", key);
|
println!("Deleted secret for key '{}'", key);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error deleting secret for key '{}': {}", key, e);
|
print_error(format!("Error deleting secret for key '{}': {}", key, e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -148,7 +158,7 @@ fn main() {
|
|||||||
Some(env) => match env.parse::<Environment>() {
|
Some(env) => match env.parse::<Environment>() {
|
||||||
Ok(parsed) => parsed,
|
Ok(parsed) => parsed,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("Invalid environment '{}'.", env);
|
print_error(format!("Invalid environment '{}'.", env));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -157,7 +167,10 @@ fn main() {
|
|||||||
let proj_id = match get_project_id(&config.name) {
|
let proj_id = match get_project_id(&config.name) {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Unable to get project ID for '{}': {}", config.name, e);
|
print_error(format!(
|
||||||
|
"Unable to get project ID for '{}': {}",
|
||||||
|
config.name, e
|
||||||
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -174,7 +187,7 @@ fn main() {
|
|||||||
let secrets = match get_project_secrets(&proj_id, environment) {
|
let secrets = match get_project_secrets(&proj_id, environment) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error getting secrets: {}", e);
|
print_error(format!("Error getting secrets: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -185,7 +198,7 @@ fn main() {
|
|||||||
let key = match gen_or_get_key() {
|
let key = match gen_or_get_key() {
|
||||||
Ok(k) => k,
|
Ok(k) => k,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("Error generating or getting key");
|
print_error("Error generating or getting key");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -193,7 +206,10 @@ fn main() {
|
|||||||
let decrypted = match crypto::decrypt(&key, ciphertext, nonce) {
|
let decrypted = match crypto::decrypt(&key, ciphertext, nonce) {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error decrypting secret for key '{}': {}", name, e);
|
print_error(format!(
|
||||||
|
"Error decrypting secret for key '{}': {}",
|
||||||
|
name, e
|
||||||
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -201,10 +217,10 @@ fn main() {
|
|||||||
let decrypted_str = match String::from_utf8(decrypted) {
|
let decrypted_str = match String::from_utf8(decrypted) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!(
|
print_error(format!(
|
||||||
"Error converting decrypted secret to string for key '{}': {}",
|
"Error converting decrypted secret to string for key '{}': {}",
|
||||||
name, e
|
name, e
|
||||||
);
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -217,7 +233,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cmd.status().is_err() {
|
if cmd.status().is_err() {
|
||||||
eprintln!("Error waiting for command to finish: {:?}", after);
|
print_error(format!("Error waiting for command to finish: {:?}", after));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
} else {
|
} else {
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
@@ -229,7 +245,10 @@ fn main() {
|
|||||||
let proj_id = match get_project_id(&config.name) {
|
let proj_id = match get_project_id(&config.name) {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Unable to get project ID for '{}': {}", config.name, e);
|
print_error(format!(
|
||||||
|
"Unable to get project ID for '{}': {}",
|
||||||
|
config.name, e
|
||||||
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -237,7 +256,7 @@ fn main() {
|
|||||||
let secrets = match get_project_secrets(&proj_id, Environment::Dev) {
|
let secrets = match get_project_secrets(&proj_id, Environment::Dev) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error getting secrets: {}", e);
|
print_error(format!("Error getting secrets: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -263,7 +282,7 @@ fn main() {
|
|||||||
let projects = match get_projects() {
|
let projects = match get_projects() {
|
||||||
Ok(projects) => projects,
|
Ok(projects) => projects,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error getting projects: {}", e);
|
print_error(format!("Error getting projects: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -275,7 +294,7 @@ fn main() {
|
|||||||
let project_name = match get_input("Project name", ':', false) {
|
let project_name = match get_input("Project name", ':', false) {
|
||||||
Ok(name) => name,
|
Ok(name) => name,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error getting project name: {}", e);
|
print_error(format!("Error getting project name: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -283,7 +302,7 @@ fn main() {
|
|||||||
match cli::interactions::create_project(&project_name) {
|
match cli::interactions::create_project(&project_name) {
|
||||||
Ok(()) => println!("{}", "Project created successfully.".cyan()),
|
Ok(()) => println!("{}", "Project created successfully.".cyan()),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error creating project: {}", e);
|
print_error(format!("Error creating project: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,13 +312,13 @@ fn main() {
|
|||||||
let exists = match cli::interactions::project_exists(&name) {
|
let exists = match cli::interactions::project_exists(&name) {
|
||||||
Ok(exists) => exists,
|
Ok(exists) => exists,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error checking if project exists: {}", e);
|
print_error(format!("Error checking if project exists: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
eprintln!("Project '{}' does not exist.", name);
|
print_error(format!("Project '{}' does not exist.", name));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +334,7 @@ fn main() {
|
|||||||
) {
|
) {
|
||||||
Ok(input) => input,
|
Ok(input) => input,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error getting confirmation: {}", e);
|
print_error(format!("Error getting confirmation: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -326,7 +345,7 @@ fn main() {
|
|||||||
println!("{}", "Project deleted successfully.".cyan())
|
println!("{}", "Project deleted successfully.".cyan())
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error deleting project: {}", e);
|
print_error(format!("Error deleting project: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,7 +364,7 @@ fn main() {
|
|||||||
Some(env) => match env.parse::<Environment>() {
|
Some(env) => match env.parse::<Environment>() {
|
||||||
Ok(parsed) => parsed,
|
Ok(parsed) => parsed,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("Invalid environment '{}'.", env);
|
print_error(format!("Invalid environment '{}'.", env));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -354,7 +373,10 @@ fn main() {
|
|||||||
let proj_id = match get_project_id(&config.name) {
|
let proj_id = match get_project_id(&config.name) {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Unable to get project ID for '{}': {}", config.name, e);
|
print_error(format!(
|
||||||
|
"Unable to get project ID for '{}': {}",
|
||||||
|
config.name, e
|
||||||
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -377,7 +399,7 @@ fn main() {
|
|||||||
let secrets = match get_project_secrets(&proj_id, environment) {
|
let secrets = match get_project_secrets(&proj_id, environment) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error getting secrets: {}", e);
|
print_error(format!("Error getting secrets: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -388,7 +410,7 @@ fn main() {
|
|||||||
let key = match gen_or_get_key() {
|
let key = match gen_or_get_key() {
|
||||||
Ok(k) => k,
|
Ok(k) => k,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("Error generating or getting key");
|
print_error("Error generating or getting key");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -396,7 +418,10 @@ fn main() {
|
|||||||
let decrypted = match crypto::decrypt(&key, ciphertext, nonce) {
|
let decrypted = match crypto::decrypt(&key, ciphertext, nonce) {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error decrypting secret for key '{}': {}", name, e);
|
print_error(format!(
|
||||||
|
"Error decrypting secret for key '{}': {}",
|
||||||
|
name, e
|
||||||
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -404,10 +429,10 @@ fn main() {
|
|||||||
let decrypted_str = match String::from_utf8(decrypted) {
|
let decrypted_str = match String::from_utf8(decrypted) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!(
|
print_error(format!(
|
||||||
"Error converting decrypted secret to string for key '{}': {}",
|
"Error converting decrypted secret to string for key '{}': {}",
|
||||||
name, e
|
name, e
|
||||||
);
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -422,13 +447,13 @@ fn main() {
|
|||||||
let mut child = match cmd.spawn() {
|
let mut child = match cmd.spawn() {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!("Error executing command: {:?}", &shell);
|
print_error(format!("Error executing command: {:?}", &shell));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if child.wait().is_err() {
|
if child.wait().is_err() {
|
||||||
eprintln!("Error waiting for command to finish: {:?}", &shell);
|
print_error(format!("Error waiting for command to finish: {:?}", &shell));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
} else {
|
} else {
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
@@ -441,13 +466,13 @@ fn main() {
|
|||||||
let projects = match get_projects() {
|
let projects = match get_projects() {
|
||||||
Ok(projects) => projects,
|
Ok(projects) => projects,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error getting projects: {}", e);
|
print_error(format!("Error getting projects: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if projects.is_empty() {
|
if projects.is_empty() {
|
||||||
eprintln!("No projects found. Please create a project first.");
|
print_error("No projects found. Please create a project first.");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,7 +486,7 @@ fn main() {
|
|||||||
{
|
{
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error spawning fzf: {}", e);
|
print_error(format!("Error spawning fzf: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -478,20 +503,20 @@ fn main() {
|
|||||||
let output = match fzf.wait_with_output() {
|
let output = match fzf.wait_with_output() {
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error waiting for fzf: {}", e);
|
print_error(format!("Error waiting for fzf: {}", e));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
eprintln!("fzf exited with non-zero status");
|
print_error("fzf exited with non-zero status");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let project = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
let project = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||||
|
|
||||||
if project.is_empty() {
|
if project.is_empty() {
|
||||||
eprintln!("No project selected.");
|
print_error("No project selected.");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,10 +533,10 @@ config = "dev""#,
|
|||||||
println!("Created .harbor.toml for project '{}'.", project);
|
println!("Created .harbor.toml for project '{}'.", project);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!(
|
print_error(format!(
|
||||||
"Error creating .harbor.toml for project '{}': {}",
|
"Error creating .harbor.toml for project '{}': {}",
|
||||||
project, e
|
project, e
|
||||||
);
|
));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -532,14 +557,11 @@ fn require_config(root: &std::path::Path) -> Config {
|
|||||||
match Config::from_repo_root(root) {
|
match Config::from_repo_root(root) {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(ConfigError::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
|
Err(ConfigError::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
|
||||||
eprintln!(
|
print_error("Missing .harbor.toml. Run `harbor config create` first.");
|
||||||
"{}",
|
|
||||||
"Missing .harbor.toml. Run `harbor config create` first.".yellow()
|
|
||||||
);
|
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("Error reading config: {}", err);
|
print_error(format!("Error reading config: {}", err));
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user