Add a puffin remove command (#120)

This commit is contained in:
Charlie Marsh 2023-10-18 14:50:08 -04:00 committed by GitHub
parent 1fc03780f9
commit 2d14c0647e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 142 additions and 8 deletions

View file

@ -5,6 +5,7 @@ pub(crate) use add::add;
pub(crate) use clean::clean;
pub(crate) use compile::compile;
pub(crate) use freeze::freeze;
pub(crate) use remove::remove;
pub(crate) use sync::{sync, SyncFlags};
pub(crate) use uninstall::uninstall;
pub(crate) use venv::venv;
@ -13,6 +14,7 @@ mod add;
mod clean;
mod compile;
mod freeze;
mod remove;
mod reporters;
mod sync;
mod uninstall;

View file

@ -0,0 +1,73 @@
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;
/// Remove a dependency from the workspace.
#[allow(clippy::unnecessary_wraps)]
pub(crate) fn remove(name: &str, _printer: Printer) -> Result<ExitStatus> {
match remove_impl(name) {
Ok(status) => Ok(status),
Err(err) => {
#[allow(clippy::print_stderr)]
{
eprint!("{err:?}");
}
Ok(ExitStatus::Failure)
}
}
}
#[derive(Error, Debug, Diagnostic)]
enum RemoveError {
#[error(
"Could not find a `pyproject.toml` file in the current directory or any of its parents"
)]
#[diagnostic(code(puffin::remove::workspace_not_found))]
WorkspaceNotFound,
#[error("Failed to parse `pyproject.toml` at: `{0}`")]
#[diagnostic(code(puffin::remove::parse_error))]
ParseError(PathBuf, #[source] WorkspaceError),
#[error("Failed to write `pyproject.toml` to: `{0}`")]
#[diagnostic(code(puffin::remove::write_error))]
WriteError(PathBuf, #[source] WorkspaceError),
#[error("Failed to remove `{0}` from `pyproject.toml`")]
#[diagnostic(code(puffin::remove::parse_error))]
RemovalError(String, #[source] WorkspaceError),
}
fn remove_impl(name: &str) -> miette::Result<ExitStatus> {
// Locate the workspace.
let cwd = std::env::current_dir().into_diagnostic()?;
let Some(workspace_root) = puffin_workspace::find_pyproject_toml(cwd) else {
return Err(RemoveError::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| RemoveError::ParseError(workspace_root.clone(), err))?;
// Remove the dependency.
manifest
.remove_dependency(name)
.map_err(|err| RemoveError::RemovalError(name.to_string(), err))?;
// Write the manifest back to disk.
manifest
.save(&workspace_root)
.map_err(|err| RemoveError::WriteError(workspace_root.clone(), err))?;
Ok(ExitStatus::Success)
}

View file

@ -1,7 +1,7 @@
use std::fmt::Write;
use std::path::Path;
use anyhow::{Context, Result};
use anyhow::Result;
use colored::Colorize;
use fs_err::tokio as fs;
@ -29,8 +29,8 @@ pub(crate) async fn venv(
)?;
// If the path already exists, remove it.
fs::remove_file(path).await.context("Foo")?;
fs::remove_dir_all(path).await?;
fs::remove_file(path).await.ok();
fs::remove_dir_all(path).await.ok();
writeln!(
printer,

View file

@ -47,6 +47,8 @@ enum Commands {
Venv(VenvArgs),
/// Add a dependency to the workspace.
Add(AddArgs),
/// Remove a dependency from the workspace.
Remove(RemoveArgs),
}
#[derive(Args)]
@ -87,7 +89,13 @@ struct VenvArgs {
#[derive(Args)]
struct AddArgs {
/// The name of the package to add.
/// The name of the package to add (e.g., `Django==4.2.6`).
name: String,
}
#[derive(Args)]
struct RemoveArgs {
/// The name of the package to remove (e.g., `Django`).
name: String,
}
@ -162,6 +170,7 @@ async fn main() -> ExitCode {
}
Commands::Venv(args) => commands::venv(&args.name, args.python.as_deref(), printer).await,
Commands::Add(args) => commands::add(&args.name, printer),
Commands::Remove(args) => commands::remove(&args.name, printer),
};
match result {