Skip to content
This repository was archived by the owner on Sep 17, 2023. It is now read-only.

Commit 6ebfdb4

Browse files
committed
refactor!: replace anyhow with thiserror
BREAKING CHANGE: Library functions no longer expose `anyhow::Result`, instead exposing `std::error::Error` via thiserror.
1 parent f26e2b5 commit 6ebfdb4

15 files changed

+148
-162
lines changed

Cargo.lock

Lines changed: 6 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,14 @@ name = "typescript_tools"
3636
path = "src/lib.rs"
3737

3838
[dependencies]
39-
anyhow = "=1.0.70"
4039
askama = "=0.12.0"
4140
clap = { version = "=4.2.1", features = ["cargo", "derive"] }
4241
globwalk = "=0.8.1"
43-
indoc = "=2.0.1"
4442
pariter = "=0.5.1"
4543
pathdiff = "=0.2.1"
4644
serde = { version = "=1.0.159", features = ["derive"] }
4745
serde_json = { version = "=1.0.95", features = ["preserve_order"] }
46+
thiserror = "=1.0.40"
4847

4948
[dev-dependencies]
5049
semantic-release-rust = "1.0.0-alpha.8"

src/configuration_file.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ use std::{
44
path::{Path, PathBuf},
55
};
66

7-
use anyhow::Result;
87
use serde::Serialize;
98

9+
use crate::error::Error;
10+
1011
// REFACTOR: most of this impl is the same across all types
1112
/// Configuration file for some component of the monorepo.
1213
pub trait ConfigurationFile: Sized {
@@ -17,7 +18,7 @@ pub trait ConfigurationFile: Sized {
1718

1819
/// Create an instance of this configuration file by reading
1920
/// the specified file from this directory on disk.
20-
fn from_directory(monorepo_root: &Path, directory: &Path) -> Result<Self>;
21+
fn from_directory(monorepo_root: &Path, directory: &Path) -> Result<Self, Error>;
2122

2223
/// Relative path to directory containing this configuration file,
2324
/// from monorepo root.
@@ -31,11 +32,26 @@ pub trait ConfigurationFile: Sized {
3132
fn write(
3233
monorepo_root: &Path,
3334
configuration_file: impl ConfigurationFile,
34-
) -> std::io::Result<()> {
35-
let file = File::create(monorepo_root.join(configuration_file.path()))?;
35+
) -> Result<(), Error> {
36+
let filename = monorepo_root.join(configuration_file.path());
37+
let file = File::create(filename.clone()).map_err(|source| Error::WriteFile {
38+
filename: filename.clone(),
39+
source,
40+
})?;
3641
let mut writer = BufWriter::new(file);
37-
serde_json::to_writer_pretty(&mut writer, configuration_file.contents())?;
38-
writer.write_all(b"\n")?;
39-
writer.flush()
42+
serde_json::to_writer_pretty(&mut writer, configuration_file.contents()).map_err(
43+
|source| Error::SerializeJSON {
44+
filename: filename.clone(),
45+
source,
46+
},
47+
)?;
48+
writer
49+
.write_all(b"\n")
50+
.and_then(|_| writer.flush())
51+
.map_err(|source| Error::WriteFile {
52+
filename: filename.clone(),
53+
source,
54+
})?;
55+
Ok(())
4056
}
4157
}

src/error.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use std::path::PathBuf;
2+
3+
#[derive(Debug, thiserror::Error)]
4+
pub enum Error {
5+
#[error("Unable to read file {filename:?}: {source}")]
6+
ReadFile {
7+
filename: PathBuf,
8+
source: std::io::Error,
9+
},
10+
11+
#[error("Unable to parse JSON from file {filename:?}: {source}")]
12+
ParseJSON {
13+
filename: PathBuf,
14+
source: serde_json::Error,
15+
},
16+
17+
#[error("Unable to serialize JSON into {filename:?}: {source}")]
18+
SerializeJSON {
19+
filename: PathBuf,
20+
source: serde_json::Error,
21+
},
22+
23+
#[error("Unable to write file {filename:?}: {source}")]
24+
WriteFile {
25+
filename: PathBuf,
26+
source: std::io::Error,
27+
},
28+
29+
#[error("Project references are out-of-date")]
30+
ProjectReferencesOutOfDate,
31+
32+
#[error("Unexpected dependency versions for internal packages")]
33+
UnexpectedInternalDependencyVersion,
34+
35+
#[error("Unable to write to buffer")]
36+
BufferWrite(#[source] std::io::Error),
37+
38+
#[error("Unable to convert value into JSON")]
39+
ToJSON(#[source] serde_json::Error),
40+
}

src/io.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
1-
use anyhow::Context;
21
use std::fs;
32
use std::path::Path;
43

5-
use anyhow::Result;
6-
74
use serde::Deserialize;
85

9-
pub(crate) fn read_json_from_file<T>(filename: &Path) -> Result<T>
6+
use crate::error::Error;
7+
8+
pub(crate) fn read_json_from_file<T>(filename: &Path) -> Result<T, Error>
109
where
1110
for<'de> T: Deserialize<'de>,
1211
{
1312
// Reading a file into a string before invoking Serde is faster than
1413
// invoking Serde from a BufReader, see
1514
// https://github.com/serde-rs/json/issues/160
16-
let string = fs::read_to_string(filename)?;
17-
serde_json::from_str(&string)
18-
.with_context(|| format!("Unable to parse JSON from file {:?}", filename))
15+
let string = fs::read_to_string(filename).map_err(|source| Error::ReadFile {
16+
filename: filename.to_owned(),
17+
source,
18+
})?;
19+
serde_json::from_str(&string).map_err(|source| Error::ParseJSON {
20+
filename: filename.to_owned(),
21+
source,
22+
})
1923
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod io;
44
mod typescript_config;
55

66
pub mod configuration_file;
7+
pub mod error;
78
pub mod link;
89
pub mod lint;
910
pub mod make_depend;

src/link.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use std::collections::HashMap;
22
use std::path::PathBuf;
33

4-
use anyhow::{bail, Result};
5-
64
use pathdiff::diff_paths;
75

86
use crate::configuration_file::ConfigurationFile;
7+
use crate::error::Error;
98
use crate::monorepo_manifest::MonorepoManifest;
109
use crate::opts;
1110
use crate::package_manifest::PackageManifest;
@@ -47,7 +46,10 @@ fn create_project_references(mut children: Vec<String>) -> Vec<TypescriptProject
4746

4847
// Create a tsconfig.json file in each parent directory to an internal package.
4948
// This permits us to compile the monorepo from the top down.
50-
fn link_children_packages(opts: &opts::Link, lerna_manifest: &MonorepoManifest) -> Result<bool> {
49+
fn link_children_packages(
50+
opts: &opts::Link,
51+
lerna_manifest: &MonorepoManifest,
52+
) -> Result<bool, Error> {
5153
let mut is_exit_success = true;
5254

5355
lerna_manifest
@@ -56,7 +58,7 @@ fn link_children_packages(opts: &opts::Link, lerna_manifest: &MonorepoManifest)
5658
.fold(HashMap::new(), key_children_by_parent)
5759
.into_iter()
5860
// DISCUSS: trying all of this in parallel
59-
.try_for_each(|(directory, children)| -> Result<()> {
61+
.try_for_each(|(directory, children)| -> Result<(), Error> {
6062
let desired_project_references = create_project_references(children);
6163
let mut tsconfig =
6264
TypescriptParentProjectReference::from_directory(&opts.root, &directory)?;
@@ -67,7 +69,11 @@ fn link_children_packages(opts: &opts::Link, lerna_manifest: &MonorepoManifest)
6769
}
6870
if opts.check_only {
6971
is_exit_success = false;
70-
let serialized = serde_json::to_string_pretty(&desired_project_references)?;
72+
let serialized = serde_json::to_string_pretty(&desired_project_references)
73+
.map_err(|source| Error::SerializeJSON {
74+
filename: tsconfig.path(),
75+
source,
76+
})?;
7177
println!(
7278
"File has out-of-date project references: {:?}, expecting:",
7379
tsconfig.path()
@@ -85,7 +91,10 @@ fn link_children_packages(opts: &opts::Link, lerna_manifest: &MonorepoManifest)
8591
Ok(is_exit_success)
8692
}
8793

88-
fn link_package_dependencies(opts: &opts::Link, lerna_manifest: &MonorepoManifest) -> Result<bool> {
94+
fn link_package_dependencies(
95+
opts: &opts::Link,
96+
lerna_manifest: &MonorepoManifest,
97+
) -> Result<bool, Error> {
8998
// NOTE: this line calls LernaManifest::get_internal_package_manifests (the sloweset function) twice
9099
let package_manifest_by_package_name = lerna_manifest.package_manifests_by_package_name()?;
91100

@@ -137,23 +146,29 @@ fn link_package_dependencies(opts: &opts::Link, lerna_manifest: &MonorepoManifes
137146
// Update the current tsconfig with the desired references
138147
tsconfig.contents.insert(
139148
String::from("references"),
140-
serde_json::to_value(desired_project_references)?,
149+
serde_json::to_value(desired_project_references).map_err(Error::ToJSON)?,
141150
);
142151

143152
Ok(Some(tsconfig))
144153
})
145-
.collect::<Result<Vec<Option<TypescriptConfig>>>>()?;
154+
.collect::<Result<Vec<Option<TypescriptConfig>>, Error>>()?;
146155

147156
// take action on the computed diffs
148157
let mut is_exit_success = true;
149158

150159
tsconfig_diffs
151160
.into_iter()
152161
.flatten()
153-
.map(|tsconfig| -> Result<()> {
162+
.map(|tsconfig| -> Result<(), Error> {
154163
if opts.check_only {
155164
is_exit_success = false;
156-
let serialized = serde_json::to_string_pretty(&tsconfig.contents)?;
165+
let serialized =
166+
serde_json::to_string_pretty(&tsconfig.contents).map_err(|source| {
167+
Error::SerializeJSON {
168+
filename: tsconfig.path(),
169+
source,
170+
}
171+
})?;
157172
println!(
158173
"File has out-of-date project references: {:?}, expecting:",
159174
tsconfig.path()
@@ -170,7 +185,7 @@ fn link_package_dependencies(opts: &opts::Link, lerna_manifest: &MonorepoManifes
170185
Ok(is_exit_success)
171186
}
172187

173-
pub fn link_typescript_project_references(opts: opts::Link) -> Result<()> {
188+
pub fn link_typescript_project_references(opts: opts::Link) -> Result<(), Error> {
174189
let lerna_manifest =
175190
MonorepoManifest::from_directory(&opts.root).expect("Unable to read monorepo manifest");
176191

@@ -181,7 +196,7 @@ pub fn link_typescript_project_references(opts: opts::Link) -> Result<()> {
181196
.expect("Unable to link internal package dependencies");
182197

183198
if opts.check_only && !(is_children_link_success && is_dependencies_link_success) {
184-
bail!("Found out-of-date project references")
199+
return Err(Error::ProjectReferencesOutOfDate);
185200
}
186201

187202
// TODO(7): create `tsconfig.settings.json` files

src/lint.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
use std::collections::HashMap;
22

3-
use anyhow::{ensure, Result};
4-
5-
use crate::opts;
6-
73
use crate::configuration_file::ConfigurationFile;
4+
use crate::error::Error;
85
use crate::monorepo_manifest::MonorepoManifest;
6+
use crate::opts;
97

10-
pub fn handle_subcommand(opts: opts::Lint) -> Result<()> {
8+
pub fn handle_subcommand(opts: opts::Lint) -> Result<(), Error> {
119
match opts.subcommand {
1210
opts::ClapLintSubCommand::DependencyVersion(args) => lint_dependency_version(&args),
1311
}
@@ -27,7 +25,7 @@ fn most_common_dependency_version(
2725
.map(|(k, _v)| k.to_owned())
2826
}
2927

30-
fn lint_dependency_version(opts: &opts::DependencyVersion) -> Result<()> {
28+
fn lint_dependency_version(opts: &opts::DependencyVersion) -> Result<(), Error> {
3129
let opts::DependencyVersion { root, dependencies } = opts;
3230

3331
let lerna_manifest = MonorepoManifest::from_directory(root)?;
@@ -88,6 +86,8 @@ fn lint_dependency_version(opts: &opts::DependencyVersion) -> Result<()> {
8886
is_exit_success = false;
8987
}
9088

91-
ensure!(is_exit_success, "Found unexpected dependency versions");
89+
if !is_exit_success {
90+
return Err(Error::UnexpectedInternalDependencyVersion);
91+
}
9292
Ok(())
9393
}

src/main.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
#![forbid(unsafe_code)]
22

3-
use anyhow::Result;
4-
53
use clap::Parser;
64

75
use typescript_tools::{link, lint, make_depend, opts, pin, query};
86

9-
fn main() -> Result<()> {
7+
fn main() -> Result<(), Box<dyn std::error::Error>> {
108
let opts = opts::Opts::parse();
119

12-
match opts.subcommand {
10+
Ok(match opts.subcommand {
1311
opts::ClapSubCommand::Link(args) => link::link_typescript_project_references(args),
1412
opts::ClapSubCommand::Pin(args) => pin::pin_version_numbers_in_internal_packages(args),
1513
opts::ClapSubCommand::MakeDepend(args) => make_depend::make_dependency_makefile(args),
1614
opts::ClapSubCommand::Query(args) => query::handle_subcommand(args),
1715
opts::ClapSubCommand::Lint(args) => lint::handle_subcommand(args),
18-
}
16+
}?)
1917
}

0 commit comments

Comments
 (0)