Files
uv/crates/puffin-cli/src/commands/add.rs
T
Charlie Marsh 1fc03780f9 Use miette for puffin add diagnostics (#119)
Experiment in using `miette` for better user-facing diagnostics in the
CLI crate:

<img width="710" alt="Screen Shot 2023-10-18 at 2 11 54 PM"
src="https://github.com/astral-sh/puffin/assets/1309177/30299da0-da65-4972-944f-cb8cc5f72a77">

For now, only the `add` command has been migrated, and all the library
crates continue to use `anyhow`.
2023-10-18 14:24:09 -04:00

75 lines
2.3 KiB
Rust

use std::path::PathBuf;
use anyhow::Result;
use miette::{Diagnostic, IntoDiagnostic};
use thiserror::Error;
use tracing::info;
use puffin_workspace::WorkspaceError;
use crate::commands::ExitStatus;
use crate::printer::Printer;
/// Add a dependency to the workspace.
#[allow(clippy::unnecessary_wraps)]
pub(crate) fn add(name: &str, _printer: Printer) -> Result<ExitStatus> {
match add_impl(name) {
Ok(status) => Ok(status),
Err(err) => {
#[allow(clippy::print_stderr)]
{
eprint!("{err:?}");
}
Ok(ExitStatus::Failure)
}
}
}
#[derive(Error, Debug, Diagnostic)]
enum AddError {
#[error(
"Could not find a `pyproject.toml` file in the current directory or any of its parents"
)]
#[diagnostic(code(puffin::add::workspace_not_found))]
WorkspaceNotFound,
#[error("Failed to parse requirement: `{0}`")]
#[diagnostic(code(puffin::add::invalid_requirement))]
InvalidRequirement(String, #[source] pep508_rs::Pep508Error),
#[error("Failed to parse `pyproject.toml` at: `{0}`")]
#[diagnostic(code(puffin::add::parse_error))]
ParseError(PathBuf, #[source] WorkspaceError),
#[error("Failed to write `pyproject.toml` to: `{0}`")]
#[diagnostic(code(puffin::add::write_error))]
WriteError(PathBuf, #[source] WorkspaceError),
}
fn add_impl(name: &str) -> miette::Result<ExitStatus> {
let requirement = puffin_workspace::VerbatimRequirement::try_from(name)
.map_err(|err| AddError::InvalidRequirement(name.to_string(), err))?;
// Locate the workspace.
let cwd = std::env::current_dir().into_diagnostic()?;
let Some(workspace_root) = puffin_workspace::find_pyproject_toml(cwd) else {
return Err(AddError::WorkspaceNotFound.into());
};
info!("Found workspace at: {}", workspace_root.display());
// Parse the manifest.
let mut manifest = puffin_workspace::Workspace::try_from(workspace_root.as_path())
.map_err(|err| AddError::ParseError(workspace_root.clone(), err))?;
// Add the dependency.
manifest.add_dependency(&requirement);
// Write the manifest back to disk.
manifest
.save(&workspace_root)
.map_err(|err| AddError::WriteError(workspace_root.clone(), err))?;
Ok(ExitStatus::Success)
}