Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle most of the errors #38

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bwenv"
version = "1.2.4"
version = "1.2.5"
edition = "2021"

[dependencies]
Expand Down
4 changes: 2 additions & 2 deletions lib/src/bitwarden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ impl BitwardenClient {
let result: Result<SecretIdentifiersResponse, Box<dyn std::error::Error>> =
Retry::spawn(retry_strategy, request).await;

result.unwrap()
result
};

let ids: Vec<Uuid> = secret_identifiers
.await
.await?
.data
.into_iter()
.map(|ident| ident.id)
Expand Down
27 changes: 20 additions & 7 deletions lib/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::time::is_date_older_than_n_seconds;
use semver::Version;
use serde::{Deserialize, Serialize};
use std::{fs, future::Future, path::PathBuf, time::SystemTime};
use tracing::info;
use tracing::{error, info};

use crate::config_yaml::Secrets;

Expand Down Expand Up @@ -80,7 +80,9 @@ impl<'a> Cache<'a> {

pub fn set(&self, profile: &str, variables: Secrets) {
let cache_file_path = self.get_cache_file_path(profile);
fs::create_dir_all(self.directory.clone()).unwrap();
fs::create_dir_all(self.directory.clone()).unwrap_or_else(|_| {
error!(message = "Failed to create cache directory");
});
let cache_entry = CacheEntry {
last_revalidation: SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
Expand All @@ -89,8 +91,13 @@ impl<'a> Cache<'a> {
version: self.version.clone(),
variables,
};
let cache_entry = serde_yaml::to_string(&cache_entry).unwrap();
std::fs::write(cache_file_path, cache_entry).unwrap();
if let Ok(cache_entry) = serde_yaml::to_string(&cache_entry) {
std::fs::write(cache_file_path, cache_entry).unwrap_or_else(|_| {
error!(message = "Failed to write cache to file");
});
} else {
error!(message = "Failed to parse cache struct");
};
}

pub fn clear(&self, profile: &str) {
Expand All @@ -103,14 +110,20 @@ impl<'a> Cache<'a> {
info!(message = format!("Invalidating cache for profile {:?}", profile));
if let Some(cache_entry) = self.get(profile) {
let cache_file_path = self.get_cache_file_path(profile);
fs::create_dir_all(self.directory.clone()).unwrap();
fs::create_dir_all(self.directory.clone())
.unwrap_or_else(|_| error!(message = "Failed to create cache directory"));
let cache_entry = CacheEntry {
last_revalidation: 0,
version: self.version.clone(),
variables: cache_entry.variables,
};
let cache_entry = serde_yaml::to_string(&cache_entry).unwrap();
std::fs::write(cache_file_path, cache_entry).unwrap();
if let Ok(cache_entry) = serde_yaml::to_string(&cache_entry) {
std::fs::write(cache_file_path, cache_entry).unwrap_or_else(|_| {
error!(message = "Failed to write cache to file");
});
} else {
error!(message = "Failed to parse cache struct");
};
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/src/config_toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ impl Config<'_> {
crate::config_yaml::Config::<'a> {
version: self.version.clone(),
path: self.path.clone(),
global: Some(config_yaml::Global {
global: config_yaml::Global {
overrides: config_yaml::GlobalOverrides(self.r#override.clone()),
}),
},
profiles: Profiles::new(
<BTreeMap<std::string::String, Profile<'_>> as Clone>::clone(&self.profile)
.into_iter()
Expand Down
23 changes: 12 additions & 11 deletions lib/src/config_yaml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ impl<'a> Secrets<'a> {
}
}

#[derive(Debug, Serialize, Deserialize, JsonSchema)]
#[derive(Debug, Serialize, Deserialize, JsonSchema, Default)]
#[schemars(title = "Global", description = "Global configuration options")]
#[serde(default)]
pub struct Global<'a> {
#[serde(
default,
Expand Down Expand Up @@ -174,7 +175,7 @@ pub struct Config<'a> {
title = "Global",
description = "Overrides for global configuration options, applied to all profiles"
)]
pub global: Option<Global<'a>>,
pub global: Global<'a>,

#[schemars(
title = "Profiles",
Expand All @@ -196,7 +197,7 @@ pub struct ConfigEvaluation<'a> {
}

impl<'a> Config<'a> {
pub fn new<P: AsRef<Path>>(config_file_path: P) -> Result<Self, anyhow::Error> {
pub fn new<P: AsRef<Path>>(config_file_path: P) -> Result<Self, Box<dyn std::error::Error>> {
parse_config_file(config_file_path)
}

Expand All @@ -208,7 +209,7 @@ impl<'a> Config<'a> {

info!(message = format!("Using profile {:?}", profile_name));

let global_overrides = &self.global.as_ref().unwrap().overrides;
let global_overrides = &self.global.overrides;
let profile_overrides = &profile.overrides;

let overrides = Secrets::merge(global_overrides, profile_overrides);
Expand All @@ -223,12 +224,12 @@ impl<'a> Config<'a> {
}
}

fn parse_config_file<'a, P: AsRef<Path>>(file_path: P) -> Result<Config<'a>, anyhow::Error> {
fn parse_config_file<'a, P: AsRef<Path>>(
file_path: P,
) -> Result<Config<'a>, Box<dyn std::error::Error>> {
info!(message = format!("Using configuration file at {:?}", file_path.as_ref()));
let mut raw = String::new();
let mut file = File::open(file_path)
.map_err(|_| ConfigError::Read)
.unwrap();
let mut file = File::open(file_path).map_err(|_| ConfigError::Read)?;
let _ = file.read_to_string(&mut raw);

Ok(serde_yaml::from_str::<Config>(&raw)
Expand Down Expand Up @@ -272,7 +273,7 @@ profiles: {{}}
let config = Config {
version: VersionReq::parse("1.0.0").unwrap(),
cache: Cache::default(),
global: None,
global: Global::default(),
profiles: Profiles::default(),
path: String::new(),
};
Expand Down Expand Up @@ -324,14 +325,14 @@ profiles:
let config = Config {
version: VersionReq::parse("1.0.0").unwrap(),
cache: Cache::default(),
global: Some(Global {
global: Global {
overrides: GlobalOverrides(Secrets(
[("global_key".into(), "global_value".into())]
.iter()
.cloned()
.collect(),
)),
}),
},
profiles: Profiles::default(),
path: String::new(),
};
Expand Down
2 changes: 1 addition & 1 deletion lib/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl Data {
}

fn write(&self, content: &DataContent) -> Result<(), Box<dyn std::error::Error>> {
std::fs::write(&self.path, serde_yaml::to_string(content).unwrap())?;
std::fs::write(&self.path, serde_yaml::to_string(content)?)?;
Ok(())
}

Expand Down
14 changes: 14 additions & 0 deletions lib/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
use std::{error, fmt};

#[derive(Debug, PartialEq)]
pub enum ConfigError {
Read,
NotFound,
NoProfile,
}

impl fmt::Display for ConfigError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ConfigError::Read => write!(f, "Error reading configuration file"),
ConfigError::NotFound => write!(f, "Configuration file not found"),
ConfigError::NoProfile => write!(f, "Profile not found in the configuration"),
}
}
}

impl error::Error for ConfigError {}
6 changes: 2 additions & 4 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"type": "object",
"required": [
"cache",
"global",
"profiles",
"version"
],
Expand All @@ -20,12 +21,9 @@
"global": {
"title": "Global",
"description": "Overrides for global configuration options, applied to all profiles",
"anyOf": [
"allOf": [
{
"$ref": "#/definitions/Global"
},
{
"type": "null"
}
]
},
Expand Down
70 changes: 44 additions & 26 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,35 +44,51 @@ async fn main() {
let root_span = span!(Level::INFO, env!("CARGO_PKG_NAME"));
let _guard = root_span.enter();

let version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
let version =
Version::parse(env!("CARGO_PKG_VERSION")).expect("Failed to parse cargo package version");

let data = data::Data::new();

let data_content = data.get_content();
let latest_version = if is_date_older_than_n_seconds(data_content.last_update_check, &86400_u64)
|| data_content.last_checked_version.is_none()
{
let latest_version = version::fetch_latest_version().await.unwrap();
let _ = data.set_content(
time::SystemTime::now()
.duration_since(time::SystemTime::UNIX_EPOCH)
.expect("SystemTime before UNIX EPOCH!")
.as_millis()
.try_into()
.unwrap(),
Version::to_string(&latest_version),
);
latest_version.to_string()
} else {
data_content.last_checked_version.unwrap()
};
let latest_version = Version::parse(&latest_version).unwrap();
let ordering = version.cmp_precedence(&latest_version);
if ordering == Ordering::Less {
info!(message = format!("New version available: {}", &latest_version));
let latest_version: Option<String> =
if is_date_older_than_n_seconds(data_content.last_update_check, &86400_u64)
|| data_content.last_checked_version.is_none()
{
if let Ok(latest_version) = version::fetch_latest_version().await {
let _ = data.set_content(
time::SystemTime::now()
.duration_since(time::SystemTime::UNIX_EPOCH)
.expect("SystemTime before UNIX EPOCH!")
.as_millis()
.try_into()
.expect("Failed to convert system time"),
Version::to_string(&latest_version),
);
Some(latest_version.to_string())
} else {
error!("Failed to fetch latest version");
None
}
} else {
data_content.last_checked_version
};

if let Some(latest_version) = &latest_version {
if let Ok(latest_version) = Version::parse(latest_version) {
let ordering = version.cmp_precedence(&latest_version);
if ordering == Ordering::Less {
info!(message = format!("New version available: {}", &latest_version));
}
}
}

let local_config = config::find_local_config(Some(&std::env::current_dir().unwrap())).unwrap();
let local_config = config::find_local_config(Some(
&std::env::current_dir().expect("Failed to retrieve CWD"),
))
.unwrap_or_else(|_| {
error!("Failed to find local configuration file");
std::process::exit(1);
});

let config_path = local_config.as_pathbuf();

Expand Down Expand Up @@ -108,7 +124,9 @@ async fn run_with<'a>(
}
}

let root_dir = config_path.parent().unwrap();
let root_dir = config_path
.parent()
.expect("Failed to resolve root directory");
let cache_dir = root_dir.join(config.cache.path.as_path());

let profile_name = cli.profile.clone().unwrap_or_else(|| {
Expand Down Expand Up @@ -203,8 +221,8 @@ async fn run_with<'a>(
.stderr(Stdio::piped());

if let Ok(mut child) = cmd.spawn() {
let mut stdout = child.stdout.take().unwrap();
let mut stderr = child.stderr.take().unwrap();
let mut stdout = child.stdout.take().expect("Failed to take stdout");
let mut stderr = child.stderr.take().expect("Failed to take stderr");
let mut buffer = [0; 1024];

// Create separate threads to handle stdout and stderr
Expand Down