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

Improve errors #60

Merged
merged 15 commits into from
Nov 15, 2022
Merged
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
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ serde = { version = "1.0.146", features = ["derive"] }
miette = "5.4.1"
regex = "1.7.0"
serde_json = "1.0.87"
thiserror = "1.0.37"
update-informer = "0.5.0"

[target.aarch64-unknown-linux-gnu.dependencies]
Expand Down
23 changes: 13 additions & 10 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{host_triple::HostTriple, targets::Target, toolchain::rust::XtensaRust};
use crate::{error::Error, host_triple::HostTriple, targets::Target, toolchain::rust::XtensaRust};
use directories_next::ProjectDirs;
use miette::{ErrReport, IntoDiagnostic, Result, WrapErr};
use miette::{IntoDiagnostic, Result};
use serde::{Deserialize, Serialize};
use std::{
collections::HashSet,
Expand Down Expand Up @@ -31,31 +31,34 @@ pub struct Config {

impl Config {
/// Load the config from config file
pub fn load() -> Result<Self> {
pub fn load() -> Result<Self, Error> {
let dirs = ProjectDirs::from("rs", "esp", "espup").unwrap();
let file = dirs.config_dir().join("espup.toml");

let config = if let Ok(data) = read(file) {
toml::from_slice(&data).into_diagnostic()?
let config = if let Ok(data) = read(&file) {
toml::from_slice(&data)
.into_diagnostic()
.map_err(|_| Error::FailedToDeserialize)?
} else {
return Err(ErrReport::msg("No config file found"));
return Err(Error::FileNotFound(file.to_string_lossy().into_owned()));
};
Ok(config)
}

/// Save the config to file
pub fn save(&self) -> Result<()> {
pub fn save(&self) -> Result<(), Error> {
let dirs = ProjectDirs::from("rs", "esp", "espup").unwrap();
let file = dirs.config_dir().join("espup.toml");

let serialized = toml::to_string(&self.clone())
.into_diagnostic()
.wrap_err("Failed to serialize config")?;
.map_err(|_| Error::FailedToSerialize)?;
create_dir_all(file.parent().unwrap())
.into_diagnostic()
.wrap_err("Failed to create config directory")?;
.map_err(|e| Error::FailedToCreateConfigFile(e.to_string()))?;
write(&file, serialized)
.into_diagnostic()
.wrap_err_with(|| format!("Failed to write config to {}", file.display()))
.map_err(|_| Error::FailedToWrite(file.display().to_string()))?;
Ok(())
}
}
81 changes: 81 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use crate::emoji;

#[derive(Debug, miette::Diagnostic, thiserror::Error)]
pub enum Error {
// Host Triple
#[diagnostic(code(espup::host_triple::unsupported_host_triple))]
#[error("{} Host triple '{0}' is not supported", emoji::ERROR)]
UnsupportedHostTriple(String),
// Target
#[diagnostic(code(espup::targets::unsupported_target))]
#[error("{} Target '{0}' is not supported", emoji::ERROR)]
UnsupportedTarget(String),
// Config
#[diagnostic(code(espup::config::file_not_found))]
#[error("{} No config file found in '{0}'", emoji::ERROR)]
FileNotFound(String),
#[diagnostic(code(espup::config::failed_to_deserialize))]
#[error("{} Failed to deserialize config", emoji::ERROR)]
FailedToDeserialize,
#[diagnostic(code(espup::config::failed_to_serialize))]
#[error("{} Failed to serialize config", emoji::ERROR)]
FailedToSerialize,
#[diagnostic(code(espup::config::failed_to_create_config_file))]
#[error("{} Failed to create config directory", emoji::ERROR)]
FailedToCreateConfigFile(String),
#[diagnostic(code(espup::config::failed_to_write))]
#[error("{} Failed to write config to '{0}'", emoji::ERROR)]
FailedToWrite(String),
// Toolchain
#[error(transparent)]
IoError(#[from] std::io::Error),
#[error(transparent)]
RewquestError(#[from] reqwest::Error),
#[diagnostic(code(espup::toolchain::failed_to_create_directory))]
#[error("{} Creating directory '{0}' failed", emoji::ERROR)]
FailedToCreateDirectory(String),
#[diagnostic(code(espup::toolchain::unsupported_file_extension))]
#[error("{} Unsuported file extension: '{0}'", emoji::ERROR)]
UnsuportedFileExtension(String),
// Toolchain - Rust
#[diagnostic(code(espup::toolchain::rust::failed_to_get_latest_version))]
#[error("{} Failed To serialize Json from string.", emoji::ERROR)]
FailedToSerializeJson,
#[diagnostic(code(espup::toolchain::rust::xtensa_rust_already_installed))]
#[error("{} Previous installation of Rust Toolchain exists in: '{0}'. Please, remove the directory before new installation.", emoji::ERROR)]
XtensaToolchainAlreadyInstalled(String),
#[diagnostic(code(espup::toolchain::rust::invalid_version))]
#[error(
"{} Invalid toolchain version '{0}', must be in the form of '<major>.<minor>.<patch>.<subpatch>'",
emoji::ERROR
)]
InvalidXtensaToolchanVersion(String),
#[diagnostic(code(espup::toolchain::rust::detection_error))]
#[error("{} Error detecting rustup: {0}", emoji::ERROR)]
RustupDetectionError(String),
#[error(transparent)]
CmdError(#[from] embuild::cmd::CmdError),
// Toolchain - ESP-IDF
#[diagnostic(code(espup::toolchain::espidf::failed_to_instatiate_cmake))]
#[error("{} Failed to add CMake to ESP-IDF tools", emoji::ERROR)]
FailedToInstantiateCmake,
#[diagnostic(code(espup::toolchain::espidf::failed_to_create_esp_idf_install_closure))]
#[error("{} Failed to create ESP-IDF install closure", emoji::ERROR)]
FailedToCreateEspIdfInstallClosure,
#[diagnostic(code(espup::toolchain::espidf::failed_to_install_esp_idf))]
#[error("{} Failed to install ESP-IDF", emoji::ERROR)]
FailedToInstallEspIdf,
// Main
#[diagnostic(code(espup::wrong_windows_arguments))]
#[error(
"{} When installing esp-idf in Windows, only --targets \"all\" is supported.",
emoji::ERROR
)]
WrongWindowsArguments,
#[diagnostic(code(espup::failed_to_remove_directory))]
#[error(
"{} Failed to remove '{0}' direcretory. Please, manually verify that the directory is properly removed.",
emoji::ERROR
)]
FailedToRemoveDirectory(String),
}
20 changes: 8 additions & 12 deletions src/host_triple.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::emoji;
use anyhow::{Context, Result};
use crate::error::Error;
use guess_host_triple::guess_host_triple;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
Expand Down Expand Up @@ -30,17 +29,14 @@ pub enum HostTriple {
}

/// Parse the host triple if specified, otherwise guess it.
pub fn get_host_triple(host_triple_arg: Option<String>) -> Result<HostTriple> {
if let Some(host_triple_arg) = host_triple_arg {
HostTriple::from_str(&host_triple_arg).context(format!(
"{} Host triple '{}' is not supported.",
emoji::ERROR,
host_triple_arg,
))
pub fn get_host_triple(host_triple_arg: Option<String>) -> Result<HostTriple, Error> {
let host_triple = if let Some(host_triple) = &host_triple_arg {
host_triple
} else {
HostTriple::from_str(guess_host_triple().unwrap())
.context(format!("{} Unable to guess host triple.", emoji::ERROR,))
}
guess_host_triple().unwrap()
};

HostTriple::from_str(host_triple).map_err(|_| Error::UnsupportedHostTriple(host_triple.into()))
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod config;
pub mod emoji;
pub mod error;
pub mod host_triple;
pub mod targets;
pub mod toolchain;
Expand Down
38 changes: 18 additions & 20 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use anyhow::{bail, Result};
use clap::Parser;
use directories_next::ProjectDirs;
use dirs::home_dir;
Expand All @@ -9,6 +8,7 @@ use embuild::{
use espup::{
config::Config,
emoji,
error::Error,
host_triple::get_host_triple,
logging::initialize_logger,
targets::{parse_targets, Target},
Expand All @@ -25,6 +25,7 @@ use espup::{
update::check_for_update,
};
use log::{debug, info, warn};
use miette::Result;
use std::{
collections::HashSet,
fs::{remove_dir_all, remove_file, File},
Expand Down Expand Up @@ -128,7 +129,7 @@ pub struct UninstallOpts {
}

/// Installs the Rust for ESP chips environment
fn install(args: InstallOpts) -> Result<()> {
fn install(args: InstallOpts) -> Result<(), Error> {
initialize_logger(&args.log_level);
check_for_update(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
info!("{} Installing esp-rs", emoji::DISC);
Expand Down Expand Up @@ -233,9 +234,7 @@ fn install(args: InstallOpts) -> Result<()> {
targets,
xtensa_rust,
};
if let Err(e) = config.save() {
bail!("{} Failed to save config {:#}", emoji::ERROR, e);
}
config.save()?;

info!("{} Installation successfully completed!", emoji::CHECK);
warn!(
Expand All @@ -246,7 +245,7 @@ fn install(args: InstallOpts) -> Result<()> {
}

/// Uninstalls the Rust for ESP chips environment
fn uninstall(args: UninstallOpts) -> Result<()> {
fn uninstall(args: UninstallOpts) -> Result<(), Error> {
initialize_logger(&args.log_level);
check_for_update(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));

Expand Down Expand Up @@ -304,7 +303,7 @@ fn uninstall(args: UninstallOpts) -> Result<()> {
}

/// Updates Xtensa Rust toolchain.
fn update(args: UpdateOpts) -> Result<()> {
fn update(args: UpdateOpts) -> Result<(), Error> {
initialize_logger(&args.log_level);
check_for_update(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));

Expand Down Expand Up @@ -343,15 +342,13 @@ fn update(args: UpdateOpts) -> Result<()> {
config.xtensa_rust = Some(xtensa_rust);
}

if let Err(e) = config.save() {
bail!("{} Failed to save config {:#}", emoji::ERROR, e);
}
config.save()?;

info!("{} Update successfully completed!", emoji::CHECK);
Ok(())
}

fn main() -> Result<()> {
fn main() -> Result<(), Error> {
match Cli::parse().subcommand {
SubCommand::Install(args) => install(*args),
SubCommand::Update(args) => update(args),
Expand All @@ -360,7 +357,7 @@ fn main() -> Result<()> {
}

/// Deletes dist folder.
fn clear_dist_folder() -> Result<()> {
fn clear_dist_folder() -> Result<(), Error> {
let dist_path = PathBuf::from(get_dist_path(""));
if dist_path.exists() {
info!("{} Clearing dist folder", emoji::WRENCH);
Expand All @@ -370,7 +367,7 @@ fn clear_dist_folder() -> Result<()> {
}

/// Returns the absolute path to the export file, uses the DEFAULT_EXPORT_FILE if no arg is provided.
fn get_export_file(export_file: Option<PathBuf>) -> Result<PathBuf> {
fn get_export_file(export_file: Option<PathBuf>) -> Result<PathBuf, Error> {
if let Some(export_file) = export_file {
if export_file.is_absolute() {
Ok(export_file)
Expand All @@ -385,7 +382,7 @@ fn get_export_file(export_file: Option<PathBuf>) -> Result<PathBuf> {
}

/// Creates the export file with the necessary environment variables.
fn export_environment(export_file: &PathBuf, exports: &[String]) -> Result<()> {
fn export_environment(export_file: &PathBuf, exports: &[String]) -> Result<(), Error> {
info!("{} Creating export file", emoji::WRENCH);
let mut file = File::create(export_file)?;
for e in exports.iter() {
Expand Down Expand Up @@ -413,17 +410,18 @@ fn export_environment(export_file: &PathBuf, exports: &[String]) -> Result<()> {

#[cfg(windows)]
/// For Windows, we need to check that we are installing all the targets if we are installing esp-idf.
pub fn check_arguments(targets: &HashSet<Target>, esp_idf_version: &Option<String>) -> Result<()> {
if esp_idf_version.is_some()

pub fn check_arguments(
targets: &HashSet<Target>,
espidf_version: &Option<String>,
) -> Result<(), Error> {
if espidf_version.is_some()
&& (!targets.contains(&Target::ESP32)
|| !targets.contains(&Target::ESP32C3)
|| !targets.contains(&Target::ESP32S2)
|| !targets.contains(&Target::ESP32S3))
{
bail!(
"{} When installing esp-idf in Windows, only --targets \"all\" is supported.",
emoji::ERROR
);
return Err(Error::WrongWindowsArguments);
}

Ok(())
Expand Down
Loading