Skip to content

Commit

Permalink
add error handling for json decoding errors
Browse files Browse the repository at this point in the history
  • Loading branch information
ssanj committed Aug 14, 2024
1 parent ccad76f commit f07964c
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 9 deletions.
37 changes: 37 additions & 0 deletions remote-config.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/ssanj/zat/remote-config.schema.json",
"title": "Remote Config",
"description": "Remote Config Definition",
"type": "array",
"items":
{
"type": "object",
"properties":
{
"name":
{
"description": "The name of the repository",
"type": "string",
"minLength": 1
},
"description":
{
"description": "A description of what the repository is",
"type": "string",
"minLength": 1
},
"url":
{
"description": "The Git URL of the repository",
"type": "string",
"minLength": 1
}
},
"required":
[
"name", "description", "url"
]
},
"minItems": 1
}
3 changes: 2 additions & 1 deletion src/args/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use clap::{Args as SubArgs, Parser, Subcommand, ValueEnum};
///
/// Templates: Are files that end with a '.tmpl'. Eg. 'README.md.tmpl'. They can have tokens in their name and in their content. The tokens in their names and content will get replaced when the repository is processed. The '.tmpl' suffix is removed when the processed template is written to the target directory.
///
/// See https://github.com/ssanj/zat for more information on the '.variables.zat-prompt' format and more examples.
/// See https://github.com/ssanj/zat/blob/main/docs/user-manual/defining-a-template.md for more information on the '.variables.zat-prompt' format for more examples.
/// JSON Schema can be verified with a tool like boon: https://github.com/santhosh-tekuri/boon
#[derive(Parser, Debug, Clone)]
#[command(author, version, about)]
pub struct Args {
Expand Down
6 changes: 2 additions & 4 deletions src/command/process_remote_templates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,10 @@ fn get_remote_selection_from_user(remote_config_file: RemoteConfigFile) -> ZatRe
}

fn get_remote_url_from_config_file(remote_config: &std::path::Path) -> ZatResult<RemoteRepositoryChoice> {
// TODO: Add better error handling
let file = File::open(remote_config).unwrap();
let file = File::open(remote_config).map_err(|e| ZatError::could_not_open_repository_file(e.to_string(), remote_config))?;
let reader = BufReader::new(file);

// TODO: Add better error handling
let remote_config_file = serde_json::from_reader(reader).unwrap();
let remote_config_file = serde_json::from_reader(reader).map_err(|e| ZatError::could_not_decode_repository_file(e.to_string(), remote_config))?;

// TODO: Print out in verbose mode
// println!("json: {json:#?}");
Expand Down
6 changes: 5 additions & 1 deletion src/error/process_remote_command_error_reason.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ pub enum ProcessRemoteCommandErrorReason {
CouldNotCreateCheckoutDirectoryStructure(String, String, String),
GitCloneFailed(String, String, String),
GitCloneStatusError(String, String),
InvalidArgumentError(String, String)
InvalidArgumentError(String, String),
CouldNotOpenRepositoryFile(String, String, String),
CouldNotDecodeRepositoryFile(String, String, String),
}


Expand All @@ -23,6 +25,8 @@ impl From<&ProcessRemoteCommandErrorReason> for ErrorFormat {
ProcessRemoteCommandErrorReason::GitCloneFailed(error, exception, remediation) => (error.to_owned(), Some(exception.to_owned()), Some(remediation.to_owned())),
ProcessRemoteCommandErrorReason::GitCloneStatusError(error, remediation) => (error.to_owned(), None, Some(remediation.to_owned())),
ProcessRemoteCommandErrorReason::InvalidArgumentError(error, remediation) => (error.to_owned(), None, Some(remediation.to_owned())),
ProcessRemoteCommandErrorReason::CouldNotOpenRepositoryFile(error, exception, remediation) => (error.to_owned(), Some(exception.to_owned()), Some(remediation.to_owned())),
ProcessRemoteCommandErrorReason::CouldNotDecodeRepositoryFile(error, exception, remediation) => (error.to_owned(), Some(exception.to_owned()), Some(remediation.to_owned())),
};

ErrorFormat {
Expand Down
29 changes: 27 additions & 2 deletions src/error/zat_error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

use std::path::Path;

use format as s;
use url::Url;
use super::ErrorFormat;
Expand Down Expand Up @@ -163,11 +165,12 @@ impl ZatError {
}

pub fn variable_file_cant_be_decoded(path: &str, reason: &str) -> ZatError {
let doc_url = "https://github.com/ssanj/zat/blob/main/docs/user-manual/defining-a-template/defining-tokens.md";
ZatError::ProcessCommandError(
ProcessCommandErrorReason::VariableFileError(
VariableFileErrorReason::VariableDecodeError(
s!("Variable file '{}' could not be decoded as JSON into the expected format. It failed decoding with this error: {}. Zat uses this file to retrieve tokens that will be replaced when rendering the templates.", path, reason),
s!("Make the variable file '{}' is a valid JSON file in the format required by Zat. See `zat --help` for more details on the format", path)
s!("Make the variable file '{}' is a valid JSON file in the format required by Zat. See `{doc_url}` for more details on the format", path)
)
)
)
Expand Down Expand Up @@ -401,7 +404,7 @@ impl ZatError {
)
}

// TODO: Test

pub fn remote_command_argument_error() -> ZatError {
ZatError::ProcessRemoteCommandError(
ProcessRemoteCommandErrorReason::InvalidArgumentError(
Expand All @@ -412,6 +415,28 @@ impl ZatError {
}


pub fn could_not_open_repository_file(error: String, repository_file: &Path) -> ZatError {
ZatError::ProcessRemoteCommandError(
ProcessRemoteCommandErrorReason::CouldNotOpenRepositoryFile(
s!("Zat could not open the supplied repository file '{}'. Zat reads remote repositories from this file.", repository_file.to_string_lossy()),
error,
s!("Please ensure the repository file '{}' exists and can be read.", repository_file.to_string_lossy())
)
)
}


pub fn could_not_decode_repository_file(error: String, repository_file: &Path) -> ZatError {
ZatError::ProcessRemoteCommandError(
ProcessRemoteCommandErrorReason::CouldNotDecodeRepositoryFile(
s!("Zat could not decode the supplied repository file '{}'. Zat reads remote repositories from this file.", repository_file.to_string_lossy()),
error,
s!("Please ensure the repository file '{}' matches the format of remote-config.schema.json. See sameple-remote-config.json for an example.", repository_file.to_string_lossy())
)
)
}


// -------------------------------------------------------------------------------------------------------------------
// Plugin Errors
// -------------------------------------------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion tests/errors_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ fn error_message_on_non_json_variables_file() -> Result<(), Box<dyn std::error::
ErrorParts::new(
"Got an error processing variables".to_owned(),
s!("Variable file '{}/.variables.zat-prompt' could not be decoded as JSON into the expected format. It failed decoding with this error: invalid type: integer `123`, expected a sequence at line 1 column 3. Zat uses this file to retrieve tokens that will be replaced when rendering the templates.", source_directory),
s!("Make the variable file '{}/.variables.zat-prompt' is a valid JSON file in the format required by Zat. See `zat --help` for more details on the format", source_directory),
s!("Make the variable file '{}/.variables.zat-prompt' is a valid JSON file in the format required by Zat. See `https://github.com/ssanj/zat/blob/main/docs/user-manual/defining-a-template/defining-tokens.md` for more details on the format", source_directory),
);

let error_test_config = ErrorTestConfig::source_no_input_directory_not_exists(test_directory, error_parts);
Expand Down

0 comments on commit f07964c

Please sign in to comment.