diff --git a/Cargo.lock b/Cargo.lock index 4b0fa97..bd6aada 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,7 +147,7 @@ dependencies = [ "percent-encoding", "serde", "serde_json", - "serde_yaml 0.9.30", + "serde_yaml", ] [[package]] @@ -305,7 +305,7 @@ dependencies = [ "rusty-hook", "serde", "serde_json", - "serde_yaml 0.9.30", + "serde_yaml", "shadow-rs", "sigstore", "tokio", @@ -1144,14 +1144,14 @@ dependencies = [ [[package]] name = "format_serde_error" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5837b8e6a4001f99fe4746767fb7379e8510c508a843caa136cc12ed9c0bad0" +version = "0.4.0" +source = "git+https://github.com/blue-build/format_serde_error#ef37a22531a28a8c99fe5cfdd06604ad5ab0029e" dependencies = [ "colored", "serde", "serde_json", - "serde_yaml 0.8.26", + "serde_yaml", + "toml 0.8.9", "unicode-segmentation", ] @@ -2830,7 +2830,7 @@ dependencies = [ "ci_info", "getopts", "nias", - "toml", + "toml 0.5.11", ] [[package]] @@ -2998,6 +2998,15 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3039,18 +3048,6 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - [[package]] name = "serde_yaml" version = "0.9.30" @@ -3534,6 +3531,40 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.1", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tough" version = "0.14.0" @@ -4176,6 +4207,15 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +[[package]] +name = "winnow" +version = "0.5.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" @@ -4215,15 +4255,6 @@ dependencies = [ "rustix", ] -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "zerocopy" version = "0.7.32" diff --git a/Cargo.toml b/Cargo.toml index 577ed93..6efd87e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ colorized = "1" derive_builder = "0.13" directories = "5" env_logger = "0.11" -format_serde_error = "0.3.0" +format_serde_error = { git = "https://github.com/blue-build/format_serde_error" } futures-util = { version = "0.3", optional = true } fuzzy-matcher = "0.3" indexmap = { version = "2", features = ["serde"] } @@ -44,10 +44,10 @@ which = "6" [features] default = [] -nightly = ["builtin-podman"] -builtin-podman = ["podman-api", "tokio", "futures-util"] -tls = ["podman-api/tls", "builtin-podman"] init = [] +nightly = ["podman-api"] +tls = ["podman-api/tls", "podman-api"] +podman-api = ["dep:podman-api", "tokio", "futures-util"] [dev-dependencies] rusty-hook = "0.11.2" diff --git a/src/commands/bug_report.rs b/src/commands/bug_report.rs index a23b46e..466fb70 100644 --- a/src/commands/bug_report.rs +++ b/src/commands/bug_report.rs @@ -5,6 +5,7 @@ use anyhow::Result; use askama::Template; use clap::Args; use clap_complete::Shell; +use format_serde_error::SerdeError; use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher}; use log::{debug, error, trace}; use requestty::question::{completions, Completions}; @@ -390,10 +391,16 @@ fn get_module_from_file(file_name: &str) -> Result { let file = fs::read_to_string(file_path.clone())?; - serde_yaml::from_str::(file.as_str()).map_or_else( - |_| -> Result { - let module = serde_yaml::from_str::(file.as_str())?; + serde_yaml::from_str::(&file).map_or_else( + |err| -> Result { + error!( + "Failed to parse module from {}: {}", + file_path.display(), + SerdeError::new(file.to_owned(), err).to_string() + ); + let module = + serde_yaml::from_str::(&file).map_err(|err| SerdeError::new(file, err))?; Ok(ModuleExt::builder().modules(vec![module]).build()) }, Ok, diff --git a/src/commands/build.rs b/src/commands/build.rs index 695c87b..78401bf 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -9,6 +9,7 @@ use std::{ use anyhow::{anyhow, bail, Result}; use clap::Args; +use format_serde_error::SerdeError; use log::{debug, info, trace, warn}; use typed_builder::TypedBuilder; @@ -21,9 +22,6 @@ use podman_api::{ #[cfg(feature = "podman-api")] use build_strategy::BuildStrategy; -#[cfg(feature = "futures-util")] -use futures_util::StreamExt; - #[cfg(feature = "tokio")] use tokio::runtime::Runtime; @@ -188,6 +186,8 @@ impl BlueBuildCommand for BuildCommand { impl BuildCommand { #[cfg(feature = "podman-api")] async fn build_image_podman_api(&self, client: Podman, recipe_path: &Path) -> Result<()> { + use futures_util::StreamExt; + trace!("BuildCommand::build_image({client:#?})"); let credentials = self.get_login_creds(); @@ -196,7 +196,9 @@ impl BuildCommand { bail!("Failed to get credentials"); } - let recipe: Recipe = serde_yaml::from_str(fs::read_to_string(recipe_path)?.as_str())?; + let recipe_str = fs::read_to_string(recipe_path)?; + let recipe: Recipe = serde_yaml::from_str(&recipe_str) + .map_err(|err| SerdeError::new(recipe_str.to_owned(), err))?; trace!("recipe: {recipe:#?}"); // Get values for image @@ -280,7 +282,9 @@ impl BuildCommand { fn build_image(&self, recipe_path: &Path) -> Result<()> { trace!("BuildCommand::build_image()"); - let recipe: Recipe = serde_yaml::from_str(fs::read_to_string(recipe_path)?.as_str())?; + let recipe_str = fs::read_to_string(recipe_path)?; + let recipe: Recipe = serde_yaml::from_str(&recipe_str) + .map_err(|err| SerdeError::new(recipe_str.to_owned(), err))?; let tags = recipe.generate_tags(); diff --git a/src/commands/local.rs b/src/commands/local.rs index 9d6c2d0..cd91d89 100644 --- a/src/commands/local.rs +++ b/src/commands/local.rs @@ -6,6 +6,7 @@ use std::{ use anyhow::{bail, Result}; use clap::Args; +use format_serde_error::SerdeError; use log::{debug, info, trace}; use typed_builder::TypedBuilder; use users::{Users, UsersCache}; @@ -43,8 +44,10 @@ impl BlueBuildCommand for UpgradeCommand { check_can_run()?; - let recipe: Recipe = - serde_yaml::from_str(fs::read_to_string(&self.common.recipe)?.as_str())?; + let recipe_str = fs::read_to_string(&self.common.recipe)?; + let recipe: Recipe = serde_yaml::from_str(&recipe_str) + .map_err(|err| SerdeError::new(recipe_str.to_owned(), err))?; + let mut build = BuildCommand::builder() .recipe(self.common.recipe.clone()) .archive(LOCAL_BUILD) @@ -90,8 +93,10 @@ impl BlueBuildCommand for RebaseCommand { check_can_run()?; - let recipe: Recipe = - serde_yaml::from_str(fs::read_to_string(&self.common.recipe)?.as_str())?; + let recipe_str = fs::read_to_string(&self.common.recipe)?; + let recipe: Recipe = serde_yaml::from_str(&recipe_str) + .map_err(|err| SerdeError::new(recipe_str.to_owned(), err))?; + let mut build = BuildCommand::builder() .recipe(self.common.recipe.clone()) .archive(LOCAL_BUILD) diff --git a/src/commands/template.rs b/src/commands/template.rs index 6d12d87..f0767e2 100644 --- a/src/commands/template.rs +++ b/src/commands/template.rs @@ -7,6 +7,7 @@ use std::{ use anyhow::Result; use askama::Template; use clap::Args; +use format_serde_error::SerdeError; use log::{debug, error, info, trace}; use typed_builder::TypedBuilder; @@ -184,8 +185,11 @@ fn template_module_from_file(file_name: &str) -> String { serde_yaml::from_str::(file.as_str()).map_or_else( |_| { - let module = serde_yaml::from_str::(file.as_str()).unwrap_or_else(|e| { - error!("Failed to deserialize module {file_name}: {e}"); + let module = serde_yaml::from_str::(file.as_str()).unwrap_or_else(|err| { + error!( + "Failed to deserialize module {file_name}: {}", + SerdeError::new(file_name.to_owned(), err) + ); process::exit(1); }); diff --git a/src/module_recipe.rs b/src/module_recipe.rs index 4a43b8f..7656ffb 100644 --- a/src/module_recipe.rs +++ b/src/module_recipe.rs @@ -1,15 +1,10 @@ -use std::{ - borrow::Cow, - collections::HashMap, - env, fs, - path::Path, - process::{self, Command}, -}; +use std::{borrow::Cow, collections::HashMap, env, fs, path::Path, process::Command}; use anyhow::Result; use chrono::Local; +use format_serde_error::SerdeError; use indexmap::IndexMap; -use log::{debug, error, info, trace, warn}; +use log::{debug, info, trace, warn}; use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; use serde_yaml::Value; @@ -137,17 +132,11 @@ impl<'a> Recipe<'a> { let recipe_path_string = recipe_path.display().to_string(); debug!("Recipe::parse_recipe({recipe_path_string})"); - let file = fs::read_to_string(recipe_path).unwrap_or_else(|e| { - error!("Failed to read file {recipe_path_string}: {e}"); - process::exit(1); - }); + let file = fs::read_to_string(recipe_path)?; debug!("Recipe contents: {file}"); - serde_yaml::from_str::(file.as_str()).map_err(|e| { - error!("Failed to parse recipe {recipe_path_string}: {e}"); - process::exit(1); - }) + Ok(serde_yaml::from_str::(&file).map_err(|err| SerdeError::new(file, err))?) } fn get_os_version(&self) -> String { @@ -185,8 +174,11 @@ impl<'a> Recipe<'a> { let inspection: ImageInspection = match serde_json::from_str( String::from_utf8_lossy(&output.stdout).as_ref(), ) { - Err(_) => { - warn!("Issue deserializing 'skopeo' output, falling back to version defined in recipe"); + Err(err) => { + let err_msg = + SerdeError::new(String::from_utf8_lossy(&output.stdout).to_string(), err) + .to_string(); + warn!("Issue deserializing 'skopeo' output, falling back to version defined in recipe. {err_msg}",); return self.image_version.to_string(); } Ok(inspection) => inspection,