From 37984fbb4480f00399be794a9df8e0a6f6a63270 Mon Sep 17 00:00:00 2001 From: Firas al-Khalil Date: Sat, 22 Mar 2025 21:02:43 +0100 Subject: [PATCH] chore(deps): stop depending on miette Working with it is a PITA, and all we really need is anyhow --- Cargo.toml | 2 +- src/build.rs | 30 ++++++++---------------------- src/config.rs | 26 +++++++------------------- src/display.rs | 5 ++--- src/error.rs | 46 +++++++++++++++++++++++++++------------------- src/git.rs | 23 +++++++++++------------ src/lib.rs | 4 ++-- src/logging.rs | 10 +++------- src/main.rs | 29 +++++++++++------------------ src/parser.rs | 7 +++---- src/sh.rs | 10 +++++----- src/tree_sitter.rs | 34 ++++++++++++---------------------- tests/config.rs | 24 +++++++++++------------- 13 files changed, 103 insertions(+), 147 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 33bde95..fb8f313 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ repo = "https://github.com/tree-sitter/tree-sitter" version = "0.24.7" [dependencies] +anyhow = "1.0" async-compression = { version = "0.4.12", features = ["tokio", "gzip"] } atty = "0.2" better-panic = "0.3.0" @@ -56,7 +57,6 @@ human-panic = "2.0.1" ignore = "0.4" indicatif = "0.17" log = "0.4" -miette = { version = "7.2.0", features = ["fancy"] } num_cpus = "1.16" reqwest = { version = "0.12.7", default-features = false, features = [ "http2", diff --git a/src/build.rs b/src/build.rs index 80516b3..805c4bf 100644 --- a/src/build.rs +++ b/src/build.rs @@ -5,7 +5,7 @@ use std::{ sync::{Arc, Mutex}, }; -use miette::{Context, IntoDiagnostic, Result}; +use anyhow::{Context, Result}; use tokio::time; use url::Url; @@ -34,13 +34,10 @@ fn clear(command: &BuildCommand, progress: &mut Progress) -> Result<()> { let handle = progress.register("Fresh Build", 1); let disp = &command.build_dir.display(); fs::remove_dir_all(&command.build_dir) - .into_diagnostic() - .wrap_err(format!("Removing the build_dir {disp} for a fresh build"))?; + .with_context(|| format!("Removing the build_dir {disp} for a fresh build"))?; handle.fin(format!("Cleaned {disp}")); } - fs::create_dir_all(&command.build_dir) - .into_diagnostic() - .wrap_err("Creating the build dir")?; + fs::create_dir_all(&command.build_dir).context("Creating the build dir")?; Ok(()) } @@ -49,14 +46,13 @@ fn build(command: &BuildCommand, progress: Progress) -> Result<()> { .enable_all() .worker_threads(command.ncpus) .build() - .into_diagnostic() - .wrap_err("Failed to initialize tokio runtime")?; + .context("Failed to initialize tokio runtime")?; let _guard = rt.enter(); let screen = Arc::new(Mutex::new(progress)); rt.spawn(update_screen(screen.clone())); let ts_cli = rt .block_on(tree_sitter::prepare(command, screen.clone())) - .wrap_err("Preparing tree-sitter")?; + .context("Preparing tree-sitter")?; let languages = collect_languages( ts_cli, screen, @@ -67,11 +63,7 @@ fn build(command: &BuildCommand, progress: Progress) -> Result<()> { &command.prefix, )?; create_dir_all(&command.out_dir) - .into_diagnostic() - .wrap_err(format!( - "Creating output dir {}", - &command.out_dir.display() - ))?; + .with_context(|| format!("Creating output dir {}", &command.out_dir.display()))?; rt.block_on(build_languages(languages)) } @@ -183,11 +175,7 @@ fn get_language_coords( resolve_git_ref(git_ref), from.as_ref().map_or_else( || default_repo(language), - |f| { - Url::parse(f) - .into_diagnostic() - .wrap_err(format!("Parsing {f} for {language}")) - }, + |f| Url::parse(f).with_context(|| format!("Parsing {f} for {language}")), ), ), _ => (None, String::from("HEAD").into(), default_repo(language)), @@ -210,7 +198,5 @@ fn resolve_git_ref(git_ref: &str) -> Ref { fn default_repo(language: &str) -> Result { let url = format!("{TSDL_FROM}{language}"); - Url::parse(&url) - .into_diagnostic() - .wrap_err(format!("Creating url {url} for {language}")) + Url::parse(&url).with_context(|| format!("Creating url {url} for {language}")) } diff --git a/src/config.rs b/src/config.rs index 48aa0e4..2b68042 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,11 +1,11 @@ use std::path::Path; +use anyhow::{Context, Result}; use diff::Diff; use figment::{ providers::{Format, Serialized, Toml}, Figment, }; -use miette::{Context, IntoDiagnostic, Result}; use tracing::debug; use crate::{ @@ -19,15 +19,10 @@ pub fn run(command: &ConfigCommand, config: &Path) -> Result<()> { let config: BuildCommand = current(config, None)?; println!( "{}", - toml::to_string(&config) - .into_diagnostic() - .wrap_err("Generating default TOML config")? + toml::to_string(&config).context("Generating default TOML config")? ); } - ConfigCommand::Default => println!( - "{}", - toml::to_string(&BuildCommand::default()).into_diagnostic()? - ), + ConfigCommand::Default => println!("{}", toml::to_string(&BuildCommand::default())?), }; Ok(()) } @@ -38,8 +33,7 @@ pub fn current(config: &Path, command: Option<&BuildCommand>) -> Result { debug!("Merging cli args + config files"); @@ -73,11 +67,10 @@ pub fn show(command: &BuildCommand) -> Result<()> { "{}", String::from_utf8( git::column(&langs.join(" "), " ", 80) - .wrap_err("Printing requested languages")? + .context("Printing requested languages")? .stdout ) - .into_diagnostic() - .wrap_err("Converting column-formatted languages to a string for printing")? + .context("Converting column-formatted languages to a string for printing")? ); } else { println!("Building all languages."); @@ -85,12 +78,7 @@ pub fn show(command: &BuildCommand) -> Result<()> { } println!("Running with the following configuration:"); println!(); - print_indent( - &toml::to_string(&command) - .into_diagnostic() - .wrap_err("Showing config")?, - " ", - ); + print_indent(&toml::to_string(&command).context("Showing config")?, " "); println!(); Ok(()) } diff --git a/src/display.rs b/src/display.rs index 9d9808d..930d96f 100644 --- a/src/display.rs +++ b/src/display.rs @@ -18,11 +18,11 @@ use std::{ time, }; +use anyhow::{Context, Result}; use clap_verbosity_flag::{InfoLevel, Verbosity}; use console::style; use enum_dispatch::enum_dispatch; use log::Level; -use miette::{Context, IntoDiagnostic, Result}; use crate::{args::ProgressStyle, format_duration}; @@ -143,8 +143,7 @@ impl ProgressState for Fancy { fn clear(&self) -> Result<()> { self.multi .clear() - .into_diagnostic() - .wrap_err("Clearing the multi-progress bar") + .context("Clearing the multi-progress bar") } fn register(&mut self, name: impl Into, num_tasks: usize) -> ProgressHandle { diff --git a/src/error.rs b/src/error.rs index 42b9e1a..2f98a3a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,10 +1,9 @@ use std::path::PathBuf; use derive_more::derive::Display; -use miette::Diagnostic; use thiserror::Error; -#[derive(Debug, Diagnostic, Error)] +#[derive(Debug, Error)] #[error("{msg}\nStdOut:\n{stdout}\nStdErr:\n{stderr}")] pub struct Command { pub msg: String, @@ -12,37 +11,31 @@ pub struct Command { pub stdout: String, } -#[derive(Debug, Diagnostic, Error)] -#[error("Could not figure out all languages")] +#[derive(Debug, Error)] +#[error("Could not figure out all languages:\n{}", format_languages(.related))] pub struct LanguageCollection { - #[related] pub related: Vec, } -#[derive(Debug, Error, Diagnostic)] -#[error("{name}")] +#[derive(Debug, Error)] +#[error("{name}.\n{source:?}")] pub struct Language { pub name: String, - #[source] - #[diagnostic_source] - pub source: Box, + pub source: Box, } -#[derive(Debug, Diagnostic, Error)] -#[error("Could not build all parsers")] +#[derive(Debug, Error)] +#[error("Could not build all parsers.\n{}", format_errors(.related))] pub struct Parser { - #[related] - pub related: Vec>, + pub related: Vec>, } -#[derive(Debug, Error, Diagnostic)] -#[error("{name}: {kind}")] +#[derive(Debug, Error)] +#[error("{name}: {kind}.\n{source:?}")] pub struct Step { pub name: String, pub kind: ParserOp, - #[source] - #[diagnostic_source] - pub source: Box, + pub source: Box, } #[derive(Debug, Display)] @@ -56,3 +49,18 @@ pub enum ParserOp { #[display("Could not generate in {}", dir.display())] Generate { dir: PathBuf }, } + +fn format_languages(langs: &[Language]) -> String { + langs + .iter() + .map(std::string::ToString::to_string) + .collect::>() + .join(", ") +} + +fn format_errors(errs: &Vec>) -> String { + errs.iter() + .map(|e| format!("{e:?}")) + .collect::>() + .join("\n") +} diff --git a/src/git.rs b/src/git.rs index 48bf686..5580fa3 100644 --- a/src/git.rs +++ b/src/git.rs @@ -5,8 +5,8 @@ use std::{ process::{Output, Stdio}, }; +use anyhow::{Context, Result}; use derive_more::{AsRef, Deref, From, FromStr, Into}; -use miette::{IntoDiagnostic, Result}; use tokio::{fs, process::Command}; use crate::sh::Exec; @@ -81,7 +81,7 @@ pub async fn clone_fast(repo: &str, git_ref: &str, cwd: &Path) -> Result<()> { async fn init_fetch_and_checkout(cwd: &Path, repo: &str, git_ref: &str) -> Result<()> { clean_anyway(cwd).await?; - fs::create_dir_all(cwd).await.into_diagnostic()?; + fs::create_dir_all(cwd).await?; Command::new("git") .current_dir(cwd) @@ -120,7 +120,7 @@ async fn get_head_sha1(cwd: &Path) -> Result { .await? .stdout, ) - .into_diagnostic() + .context("rev-parse HEAD is not a valid utf-8") } async fn clean_anyway(cwd: &Path) -> Result<()> { @@ -129,8 +129,7 @@ async fn clean_anyway(cwd: &Path) -> Result<()> { fs::remove_dir_all(cwd).await } else { fs::remove_file(cwd).await - } - .into_diagnostic()?; + }?; } Ok(()) } @@ -148,7 +147,7 @@ async fn get_remote_url(cwd: &Path) -> Result { .await? .stdout, ) - .into_diagnostic() + .context("remote get-url origin did not return a valid utf-8") } async fn is_valid_git_dir(cwd: &Path) -> bool { @@ -191,8 +190,7 @@ pub async fn tag_for_ref(cwd: &Path, git_ref: &str) -> Result { .exec() .await? .stdout, - ) - .into_diagnostic()? + )? .trim() .to_string()) } @@ -205,10 +203,11 @@ pub fn column(input: &str, indent: &str, width: usize) -> Result { .arg(format!("--width={width}",)) .stdin(Stdio::piped()) .stdout(Stdio::piped()) - .spawn() - .into_diagnostic()?; + .spawn()?; if let Some(mut stdin) = child.stdin.take() { - stdin.write_all(input.as_bytes()).into_diagnostic()?; + stdin.write_all(input.as_bytes())?; } - child.wait_with_output().into_diagnostic() + child + .wait_with_output() + .context("git column did not finish normally") } diff --git a/src/lib.rs b/src/lib.rs index 7c0da42..9320f37 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,7 +55,7 @@ use std::{ time, }; -use miette::{IntoDiagnostic, Result}; +use anyhow::Result; extern crate log; @@ -81,7 +81,7 @@ impl SafeCanonicalize for Path { if self.is_absolute() { Ok(self.to_path_buf()) } else { - let current_dir = env::current_dir().into_diagnostic()?; + let current_dir = env::current_dir()?; Ok(current_dir.join(self)) } } diff --git a/src/logging.rs b/src/logging.rs index 9a09145..bb5a3ce 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -3,7 +3,7 @@ use std::{ path::{Path, PathBuf}, }; -use miette::{Context, IntoDiagnostic as _, Result}; +use anyhow::{Context, Result}; use tracing::level_filters::LevelFilter; use tracing_appender::non_blocking::WorkerGuard; use tracing_log::AsTrace; @@ -74,11 +74,7 @@ fn init_log_file(args: &Args) -> Result { ); let parent = log.parent().unwrap_or(Path::new(".")); if !parent.exists() { - fs::create_dir_all(parent) - .into_diagnostic() - .wrap_err("Preparing log directory")?; + fs::create_dir_all(parent).context("Preparing log directory")?; } - File::create(&log) - .into_diagnostic() - .wrap_err("Creating log file") + File::create(&log).context("Creating log file") } diff --git a/src/main.rs b/src/main.rs index 0bdfec2..46d1241 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use std::{fs, path::PathBuf}; +use anyhow::{bail, Result}; use clap::Parser; -use miette::{bail, IntoDiagnostic, Result}; use self_update::self_replace; use semver::Version; use tracing::{error, info}; @@ -36,17 +36,15 @@ fn run(args: &args::Args) -> Result<()> { fn self_update(mut progress: Progress) -> Result<()> { let tsdl = env!("CARGO_BIN_NAME"); - let current_version = Version::parse(env!("CARGO_PKG_VERSION")).into_diagnostic()?; + let current_version = Version::parse(env!("CARGO_PKG_VERSION"))?; let mut handle = progress.register("selfupdate", 4); handle.start("fetching releases".to_string()); let releases = self_update::backends::github::ReleaseList::configure() .repo_owner("stackmystack") .repo_name(tsdl) - .build() - .into_diagnostic()? - .fetch() - .into_diagnostic()?; + .build()? + .fetch()?; let name = format!("{tsdl}-{TREE_SITTER_PLATFORM}.gz"); let asset = releases[0].assets.iter().find(|&asset| asset.name == name); @@ -54,7 +52,7 @@ fn self_update(mut progress: Progress) -> Result<()> { bail!("Could not find a suitable release for your platform"); } - let latest_version = Version::parse(&releases[0].version).into_diagnostic()?; + let latest_version = Version::parse(&releases[0].version)?; if latest_version <= current_version { handle.msg("already at the latest version".to_string()); return Ok(()); @@ -62,17 +60,13 @@ fn self_update(mut progress: Progress) -> Result<()> { handle.step(format!("downloading {latest_version}")); let asset = asset.unwrap(); - let tmp_dir = tempfile::tempdir().into_diagnostic()?; + let tmp_dir = tempfile::tempdir()?; let tmp_gz_path = tmp_dir.path().join(&asset.name); - let tmp_gz = fs::File::create_new(&tmp_gz_path).into_diagnostic()?; + let tmp_gz = fs::File::create_new(&tmp_gz_path)?; self_update::Download::from_url(&asset.download_url) - .set_header( - reqwest::header::ACCEPT, - "application/octet-stream".parse().into_diagnostic()?, - ) - .download_to(&tmp_gz) - .into_diagnostic()?; + .set_header(reqwest::header::ACCEPT, "application/octet-stream".parse()?) + .download_to(&tmp_gz)?; handle.step(format!("extracting {latest_version}")); let tsdl_bin = PathBuf::from(tsdl); @@ -80,11 +74,10 @@ fn self_update(mut progress: Progress) -> Result<()> { .archive(self_update::ArchiveKind::Plain(Some( self_update::Compression::Gz, ))) - .extract_file(tmp_dir.path(), &tsdl_bin) - .into_diagnostic()?; + .extract_file(tmp_dir.path(), &tsdl_bin)?; let new_exe = tmp_dir.path().join(tsdl_bin); - self_replace::self_replace(new_exe).into_diagnostic()?; + self_replace::self_replace(new_exe)?; handle.fin(format!("{latest_version}")); Ok(()) diff --git a/src/parser.rs b/src/parser.rs index 134a5bc..462ec5b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4,8 +4,8 @@ use std::{ sync::Arc, }; +use anyhow::{anyhow, Context, Result}; use ignore::{overrides::OverrideBuilder, types::TypesBuilder, WalkBuilder}; -use miette::{miette, Context, IntoDiagnostic, Result}; use tokio::{fs, process::Command, sync::mpsc}; use tracing::warn; use url::Url; @@ -209,8 +209,7 @@ impl Language { fs::copy(&dll, &dst) .await - .into_diagnostic() - .wrap_err_with(|| format!("cp {} {}", &dll.display(), dst.display())) + .with_context(|| format!("cp {} {}", &dll.display(), dst.display())) .map_err(|err| self.create_copy_error(&dll, err.to_string()).into()) .and(Ok(())) } @@ -305,7 +304,7 @@ impl Language { src: self.out_dir.clone(), dst: dir.to_path_buf(), }, - source: miette!(message).into(), + source: anyhow!(message).into(), } } } diff --git a/src/sh.rs b/src/sh.rs index e667b57..74de502 100644 --- a/src/sh.rs +++ b/src/sh.rs @@ -1,6 +1,6 @@ use std::{env, fmt::Write, os::unix::process::ExitStatusExt, process::Output}; -use miette::{IntoDiagnostic, Result}; +use anyhow::Result; use tokio::process::Command; use tracing::{error, trace}; @@ -21,7 +21,7 @@ impl Exec for Command { let cmd = self.display()?; trace!("{}", cmd); - let output = self.output().await.into_diagnostic()?; + let output = self.output().await?; if output.status.success() { return Ok(output); } @@ -55,13 +55,13 @@ impl Exec for Command { let mut res = String::new(); if let Some(path) = cwd { - write!(res, "[{}] ", relative_to_cwd(path).to_string_lossy()).into_diagnostic()?; + write!(res, "[{}] ", relative_to_cwd(path).to_string_lossy())?; } - write!(res, "{program} ").into_diagnostic()?; + write!(res, "{program} ")?; for arg in args { - write!(res, "{} ", arg.to_string_lossy()).into_diagnostic()?; + write!(res, "{} ", arg.to_string_lossy())?; } Ok(res.trim_end().to_string()) diff --git a/src/tree_sitter.rs b/src/tree_sitter.rs index 35c09b0..665c811 100644 --- a/src/tree_sitter.rs +++ b/src/tree_sitter.rs @@ -5,8 +5,8 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::{Arc, Mutex}; +use anyhow::{anyhow, Context, Result}; use async_compression::tokio::bufread::GzipDecoder; -use miette::{miette, Context, IntoDiagnostic, Result}; use tokio::process::Command; use tokio::{fs, io}; use tracing::trace; @@ -91,42 +91,34 @@ async fn download_and_extract(gz: &Path, url: &str, res: &Path) -> Result<()> { download(gz, url).await?; gunzip(gz).await?; chmod_x(res).await?; - fs::remove_file(gz).await.into_diagnostic()?; + fs::remove_file(gz).await?; Ok(()) } async fn download(gz: &Path, url: &str) -> Result<()> { - fs::write( - gz, - reqwest::get(url) - .await - .into_diagnostic()? - .bytes() - .await - .into_diagnostic()?, - ) - .await - .into_diagnostic() + fs::write(gz, reqwest::get(url).await.context("fetch")?.bytes().await?) + .await + .with_context(|| format!("downloading {url} to {}", gz.display())) } async fn gunzip(gz: &Path) -> Result<()> { - let file = fs::File::open(gz).await.into_diagnostic()?; + let file = fs::File::open(gz).await?; let mut decompressor = GzipDecoder::new(tokio::io::BufReader::new(file)); let out_path = gz.with_extension(""); - let mut out_file = tokio::fs::File::create(out_path).await.into_diagnostic()?; + let mut out_file = tokio::fs::File::create(out_path).await?; io::copy(&mut decompressor, &mut out_file) .await - .into_diagnostic() .and(Ok(())) + .with_context(|| format!("decompressing {}", gz.display())) } async fn chmod_x(prog: &Path) -> Result<()> { - let metadata = fs::metadata(prog).await.into_diagnostic()?; + let metadata = fs::metadata(prog).await?; let mut permissions = metadata.permissions(); permissions.set_mode(permissions.mode() | 0o111); fs::set_permissions(prog, permissions) .await - .into_diagnostic() + .with_context(|| format!("chmod +x {}", prog.display())) } pub async fn prepare(args: &BuildCommand, progress: Arc>) -> Result { @@ -134,12 +126,10 @@ pub async fn prepare(args: &BuildCommand, progress: Arc>) -> Res progress .lock() .map(|mut lock| lock.register("tree-sitter-cli", 3)) - .or(Err(miette!("Acquiring progress lock")))? + .or(Err(anyhow!("Acquiring progress lock")))? }; - let repo = Url::parse(&args.tree_sitter.repo) - .into_diagnostic() - .wrap_err("Parsing the tree-sitter URL")?; + let repo = Url::parse(&args.tree_sitter.repo).context("Parsing the tree-sitter URL")?; let version = &args.tree_sitter.version; handle.start(format!("Figuring out tag from version {version}")); let tag = tag(repo.as_str(), version).await?; diff --git a/tests/config.rs b/tests/config.rs index c9cf3e9..0d49963 100644 --- a/tests/config.rs +++ b/tests/config.rs @@ -1,6 +1,6 @@ +use anyhow::Result; use assert_fs::prelude::*; use indoc::{formatdoc, indoc}; -use miette::{IntoDiagnostic, Result}; #[cfg(test)] use pretty_assertions::{assert_eq, assert_ne}; @@ -15,32 +15,30 @@ use tsdl::{ #[test] fn current_from_generated_default() -> Result<()> { - let temp = assert_fs::TempDir::new().into_diagnostic()?; + let temp = assert_fs::TempDir::new()?; let generated = temp.child("generated.toml"); let def = BuildCommand::default(); - generated - .write_str(&toml::to_string(&def).into_diagnostic()?) - .into_diagnostic()?; + generated.write_str(&toml::to_string(&def)?)?; assert_eq!(def, config::current(&generated, None).unwrap()); Ok(()) } #[test] fn current_from_empty() -> Result<()> { - let temp = assert_fs::TempDir::new().into_diagnostic()?; + let temp = assert_fs::TempDir::new()?; let generated = temp.child("generated.toml"); let def = BuildCommand::default(); - generated.touch().into_diagnostic()?; + generated.touch()?; assert_eq!(def, config::current(&generated, None).unwrap()); Ok(()) } #[test] fn current_preserve_languages() -> Result<()> { - let temp = assert_fs::TempDir::new().into_diagnostic()?; + let temp = assert_fs::TempDir::new()?; let generated = temp.child("generated.toml"); let mut def = BuildCommand::default(); - generated.touch().into_diagnostic()?; + generated.touch()?; def.languages = None; assert_eq!(def, config::current(&generated, Some(&def)).unwrap()); def.languages = Some(vec![]); @@ -74,10 +72,10 @@ fn current_default_is_default() -> Result<()> { TREE_SITTER_REPO, TREE_SITTER_PLATFORM, }; - let temp = assert_fs::TempDir::new().into_diagnostic()?; + let temp = assert_fs::TempDir::new()?; let generated = temp.child("generated.toml"); let def = BuildCommand::default(); - generated.write_str(&config).into_diagnostic()?; + generated.write_str(&config)?; assert_eq!(def, config::current(&generated, None).unwrap()); assert_eq!(def, config::current(&generated, Some(&def)).unwrap()); Ok(()) @@ -98,10 +96,10 @@ fn current_overrides_default() -> Result<()> { platform = "linux-arm64" "# }; - let temp = assert_fs::TempDir::new().into_diagnostic()?; + let temp = assert_fs::TempDir::new()?; let generated = temp.child("generated.toml"); let def = BuildCommand::default(); - generated.write_str(config).into_diagnostic()?; + generated.write_str(config)?; generated.assert(config); assert_ne!(def, config::current(&generated, None).unwrap()); assert_ne!(def, config::current(&generated, Some(&def)).unwrap());