Skip to content

Commit 05a5c59

Browse files
authored
codegen: Simplify match Err + bail! reporting with .context() and ? operator (#308)
As mentioned in [#299] these verbose `Err` unwrapping structs accidentally slept in thanks to `anyhow` being pulled in with `default-features = false`; default features are now enabled which allow `anyhow` to do what it was designed for: turn any `Error` type into an `anyhow::Error` for painless propagation/bubbling of many different error types. As a bonus we can use their `Context` trait to rewrap errors with more information where necessary, such as file paths or describing the operation at hand (as was already done manually in the `bail!` macros, while `Display`-formatting the underlying error). [#299]: bitshifter/glam-rs#299 (comment)
1 parent 411eb37 commit 05a5c59

1 file changed

Lines changed: 21 additions & 61 deletions

File tree

src/main.rs

Lines changed: 21 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
mod outputs;
22

3-
use anyhow::bail;
3+
use anyhow::{bail, Context};
44
use clap::{arg, command};
55
use rustfmt_wrapper::rustfmt;
6-
use std::fs::File;
7-
use std::io::Write;
86
use std::path::Path;
97

108
use outputs::build_output_pairs;
@@ -13,19 +11,9 @@ const GLAM_ROOT: &str = "..";
1311

1412
fn is_modified(repo: &git2::Repository, output_path: &str) -> anyhow::Result<bool> {
1513
match repo.status_file(Path::new(output_path)) {
16-
Ok(status) => {
17-
Ok(status.is_wt_modified())
18-
// if status.is_wt_modified() {
19-
// bail!("{} is already modified, revert or stash your changes.", output_path);
20-
// }
21-
}
22-
Err(e) => {
23-
if e.code() == git2::ErrorCode::NotFound {
24-
Ok(false)
25-
} else {
26-
bail!("git file status failed for {}: {}", output_path, e);
27-
}
28-
}
14+
Ok(status) => Ok(status.is_wt_modified()),
15+
Err(e) if e.code() == git2::ErrorCode::NotFound => Ok(false),
16+
Err(e) => Err(e).with_context(|| format!("git file status failed for {}", output_path)),
2917
}
3018
}
3119

@@ -34,14 +22,8 @@ fn generate_file(
3422
context: &tera::Context,
3523
template_path: &str,
3624
) -> anyhow::Result<String> {
37-
let buffer = match tera.render(template_path, context) {
38-
Ok(output) => output,
39-
Err(e) => {
40-
bail!("tera error encountered: {}", e);
41-
}
42-
};
43-
44-
Ok(buffer)
25+
tera.render(template_path, context)
26+
.context("tera render error")
4527
}
4628

4729
fn main() -> anyhow::Result<()> {
@@ -65,26 +47,22 @@ fn main() -> anyhow::Result<()> {
6547
let verbose = matches.is_present("verbose");
6648

6749
if stdout && output_path_glob.is_none() {
50+
// TODO: What if the glob matches multiple files?
6851
bail!("specify a single file to output to stdout.");
6952
}
7053

7154
let glob = if let Some(output_path_glob) = output_path_glob {
72-
match globset::Glob::new(output_path_glob) {
73-
Ok(glob) => Some(glob.compile_matcher()),
74-
Err(e) => bail!("failed to compile glob: {}", e),
75-
}
55+
Some(
56+
globset::Glob::new(output_path_glob)
57+
.context("failed to compile glob")?
58+
.compile_matcher(),
59+
)
7660
} else {
7761
None
7862
};
79-
let tera = match tera::Tera::new("templates/**/*.rs.tera") {
80-
Ok(t) => t,
81-
Err(e) => bail!("Parsing error(s): {}", e),
82-
};
63+
let tera = tera::Tera::new("templates/**/*.rs.tera").context("tera parsing error(s)")?;
8364

84-
let repo = match git2::Repository::open(GLAM_ROOT) {
85-
Ok(repo) => repo,
86-
Err(e) => bail!("failed to open git repo: {}", e),
87-
};
65+
let repo = git2::Repository::open(GLAM_ROOT).context("failed to open git repo")?;
8866
let workdir = repo.workdir().unwrap();
8967

9068
let output_pairs = build_output_pairs();
@@ -126,33 +104,23 @@ fn main() -> anyhow::Result<()> {
126104
let mut output_str = generate_file(&tera, context, template_path)?;
127105

128106
if fmt_output || check {
129-
match rustfmt(&output_str) {
130-
Ok(output) => output_str = output,
131-
Err(e) => {
132-
bail!("rustfmt error encountered: {}", e);
133-
}
134-
}
107+
output_str = rustfmt(&output_str).context("rustfmt failed")?;
135108
}
136109

137110
let full_output_path = workdir.join(output_path);
138111

139112
if check {
140-
match File::open(&full_output_path) {
141-
Ok(mut file) => {
142-
use std::io::Read;
143-
let mut original_str = String::new();
144-
if let Err(e) = file.read_to_string(&mut original_str) {
145-
println!("'{output_path}' could not be read: {e}");
146-
output_differences += 1;
147-
} else if output_str != original_str {
113+
match std::fs::read_to_string(&full_output_path) {
114+
Ok(original_str) => {
115+
if output_str != original_str {
148116
println!("'{output_path}' is different");
149117
output_differences += 1;
150118
} else if verbose {
151119
println!("'{output_path}' is the same");
152120
}
153121
}
154122
Err(e) => {
155-
println!("{output_path} could not be opened: {e}");
123+
println!("{output_path} could not be opened or read: {e}");
156124
output_differences += 1;
157125
}
158126
};
@@ -164,16 +132,8 @@ fn main() -> anyhow::Result<()> {
164132
continue;
165133
}
166134

167-
let mut output_file = match File::create(&full_output_path) {
168-
Ok(file) => file,
169-
Err(e) => {
170-
bail!("failed to create {}: {}", full_output_path.display(), e);
171-
}
172-
};
173-
174-
if let Err(e) = write!(output_file, "{}", output_str) {
175-
bail!("failed to write output: {}", e);
176-
}
135+
std::fs::write(&full_output_path, output_str)
136+
.with_context(|| format!("failed to write {}", full_output_path.display()))?;
177137
}
178138

179139
if check && output_differences > 0 {

0 commit comments

Comments
 (0)