Skip to content

Commit 99871bc

Browse files
author
Eyal Kalderon
committed
Use failure as application-wide error type
This matches the upstream convention used by Cargo with its `CargoResult` type aliasing `failure::Error`. In later versions of Cargo, `failure` has been replaced by `anyhow` (rust-lang/cargo#7776), but this should suffice for the time being while we still depend on this Cargo version. The pattern of `try_main()` seen here is a common pattern seen in other CLI tools such as `ripgrep`. Having `main()` return a `Result` isn't useful here because it only shows the `Debug` output and not `Display`, which typically results in a very poor experince for the end-user.
1 parent fe597b6 commit 99871bc

File tree

4 files changed

+33
-15
lines changed

4 files changed

+33
-15
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.nix

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ license = "MIT"
88
cargo = "0.41.0"
99
cargo-platform = "0.1.0"
1010
colorify = "0.2.3"
11+
failure = "0.1.6"
1112
pathdiff = "0.1.0"
1213
semver = "0.9.0"
1314
serde = { version = "1.0.104", features = ["derive"] }

src/main.rs

+30-15
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use cargo::{
1919
};
2020
use cargo_platform::Platform;
2121
use colorify::colorify;
22+
use failure::{Error, ResultExt};
2223
use semver::{Version, VersionReq};
2324
use tera::Tera;
2425

@@ -33,24 +34,34 @@ mod template;
3334
type Feature<'a> = &'a str;
3435
type PackageName<'a> = &'a str;
3536
type RootFeature<'a> = (PackageName<'a>, Feature<'a>);
37+
type Result<T> = std::result::Result<T, Error>;
3638

3739
const VERSION_ATTRIBUTE_NAME: &str = "cargo2nixVersion";
3840

3941
fn main() {
4042
let args: Vec<String> = std::env::args().collect();
4143
let args: Vec<&str> = args.iter().map(AsRef::as_ref).collect();
44+
if let Err(err) = try_main(&args) {
45+
eprintln!("{}", err);
46+
std::process::exit(1);
47+
}
48+
}
4249

50+
fn try_main(args: &[&str]) -> Result<()> {
4351
match &args[1..] {
4452
["--stdout"] | ["-s"] => generate_cargo_nix(io::stdout().lock()),
4553
["--file"] | ["-f"] => write_to_file("Cargo.nix"),
4654
["--file", file] | ["-f", file] => write_to_file(file),
4755
["--help"] | ["-h"] => print_help(),
48-
["--version"] | ["-v"] => println!("{}", version()),
56+
["--version"] | ["-v"] => {
57+
println!("{}", version());
58+
Ok(())
59+
}
4960
[] => print_help(),
5061
_ => {
5162
println!("Invalid arguments: {:?}", &args[1..]);
5263
println!("\nTry again, with help: \n");
53-
print_help();
64+
print_help()
5465
}
5566
}
5667
}
@@ -93,17 +104,18 @@ fn version_req(path: &Path) -> (VersionReq, Version) {
93104
)
94105
}
95106

96-
fn print_help() {
107+
fn print_help() -> Result<()> {
97108
println!("cargo2nix-{}\n", version());
98109
println!("$ cargo2nix # Print the help");
99110
println!("$ cargo2nix -s,--stdout # Output to stdout");
100111
println!("$ cargo2nix -f,--file # Output to Cargo.nix");
101112
println!("$ cargo2nix -f,--file <file> # Output to the given file");
102113
println!("$ cargo2nix -v,--version # Print version of cargo2nix");
103114
println!("$ cargo2nix -h,--help # Print the help");
115+
Ok(())
104116
}
105117

106-
fn write_to_file(file: impl AsRef<Path>) {
118+
fn write_to_file(file: impl AsRef<Path>) -> Result<()> {
107119
let path = file.as_ref();
108120
if path.exists() {
109121
let (vers_req, ver) = version_req(path);
@@ -121,7 +133,7 @@ fn write_to_file(file: impl AsRef<Path>) {
121133
colorify!(red: "Please upgrade your cargo2nix ({}) to proceed.\n"),
122134
vers_req
123135
);
124-
return;
136+
return Ok(());
125137
}
126138
println!(
127139
colorify!(green_bold: "\nVersion {} matches the requirement {} [{}]\n"),
@@ -140,22 +152,24 @@ fn write_to_file(file: impl AsRef<Path>) {
140152
.expect("failed to read input");
141153
if line.trim() != "yes" {
142154
println!("aborted!");
143-
return;
155+
return Ok(());
144156
}
145157
}
146158

147159
let mut temp_file = tempfile::Builder::new()
148160
.tempfile()
149161
.expect("could not create new temporary file");
150162

151-
generate_cargo_nix(&mut temp_file);
163+
generate_cargo_nix(&mut temp_file)?;
152164

153165
temp_file
154166
.persist(path)
155-
.unwrap_or_else(|e| panic!("could not write file to {}: {}", path.display(), e));
167+
.with_context(|e| format!("could not write file to {}: {}", path.display(), e))?;
168+
169+
Ok(())
156170
}
157171

158-
fn generate_cargo_nix(mut out: impl io::Write) {
172+
fn generate_cargo_nix(mut out: impl io::Write) -> Result<()> {
159173
let config = {
160174
let mut c = cargo::Config::default().unwrap();
161175
c.configure(0, None, &None, false, true, false, &None, &[])
@@ -208,7 +222,8 @@ fn generate_cargo_nix(mut out: impl io::Write) {
208222
)
209223
.expect("error adding template");
210224
let context = tera::Context::from_serialize(plan).unwrap();
211-
write!(out, "{}", tera.render("Cargo.nix.tera", &context).unwrap()).expect("write error")
225+
write!(out, "{}", tera.render("Cargo.nix.tera", &context).unwrap())?;
226+
Ok(())
212227
}
213228

214229
fn simplify_optionality<'a, 'b: 'a>(
@@ -525,7 +540,7 @@ fn display_root_feature((pkg_name, feature): RootFeature) -> String {
525540
format!("{}/{}", pkg_name, feature)
526541
}
527542

528-
fn prefetch_git(url: &str, rev: &str) -> Result<String, Box<dyn std::error::Error>> {
543+
fn prefetch_git(url: &str, rev: &str) -> Result<String> {
529544
use std::process::{Command, Output};
530545

531546
let Output {
@@ -539,16 +554,16 @@ fn prefetch_git(url: &str, rev: &str) -> Result<String, Box<dyn std::error::Erro
539554
.output()?;
540555

541556
if status.success() {
542-
Ok(serde_json::from_slice::<serde_json::Value>(&stdout)?
557+
serde_json::from_slice::<serde_json::Value>(&stdout)?
543558
.get("sha256")
544559
.and_then(|v| v.as_str())
545560
.map(|s| s.to_string())
546-
.ok_or("unexpected JSON output")?)
561+
.ok_or_else(|| failure::format_err!("unexpected JSON output"))
547562
} else {
548-
Err(format!(
563+
Err(failure::format_err!(
549564
"process failed with stderr {:?}",
550565
String::from_utf8(stderr)
551-
))?
566+
))
552567
}
553568
}
554569

0 commit comments

Comments
 (0)