Skip to content

Commit 3cc0b1a

Browse files
authored
Improved error message when build-dir template var is invalid (#15418)
### What does this PR try to resolve? This PR improves the error message when an invalid template variable is used in the `build.build-dir` config. I am using `closest_msg` to find a close match. If there are no close matches, we simply print the available template variables list. See #14125 r? @epage
2 parents 27366fd + fac2aaf commit 3cc0b1a

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

src/cargo/util/context/mod.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,14 @@ use crate::sources::CRATES_IO_REGISTRY;
7777
use crate::util::errors::CargoResult;
7878
use crate::util::network::http::configure_http_handle;
7979
use crate::util::network::http::http_handle;
80-
use crate::util::{internal, CanonicalUrl};
80+
use crate::util::{closest_msg, internal, CanonicalUrl};
8181
use crate::util::{Filesystem, IntoUrl, IntoUrlWithBase, Rustc};
8282
use anyhow::{anyhow, bail, format_err, Context as _};
8383
use cargo_credential::Secret;
8484
use cargo_util::paths;
8585
use cargo_util_schemas::manifest::RegistryName;
8686
use curl::easy::Easy;
87+
use itertools::Itertools;
8788
use lazycell::LazyCell;
8889
use serde::de::IntoDeserializer as _;
8990
use serde::Deserialize;
@@ -678,15 +679,27 @@ impl GlobalContext {
678679
}),
679680
];
680681

682+
let template_variables = replacements
683+
.iter()
684+
.map(|(key, _)| key[1..key.len() - 1].to_string())
685+
.collect_vec();
686+
681687
let path = val
682688
.resolve_templated_path(self, replacements)
683689
.map_err(|e| match e {
684690
path::ResolveTemplateError::UnexpectedVariable {
685691
variable,
686692
raw_template,
687-
} => anyhow!(
688-
"unexpected variable `{variable}` in build.build-dir path `{raw_template}`"
689-
),
693+
} => {
694+
let mut suggestion = closest_msg(&variable, template_variables.iter(), |key| key, "template variable");
695+
if suggestion == "" {
696+
let variables = template_variables.iter().map(|v| format!("`{{{v}}}`")).join(", ");
697+
suggestion = format!("\n\nhelp: available template variables are {variables}");
698+
}
699+
anyhow!(
700+
"unexpected variable `{variable}` in build.build-dir path `{raw_template}`{suggestion}"
701+
)
702+
},
690703
path::ResolveTemplateError::UnexpectedBracket { bracket_type, raw_template } => {
691704
let (btype, literal) = match bracket_type {
692705
path::BracketType::Opening => ("opening", "{"),

tests/testsuite/build_dir.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,33 @@ fn template_should_error_for_invalid_variables() {
512512
.with_stderr_data(str![[r#"
513513
[ERROR] unexpected variable `fake` in build.build-dir path `{fake}/build-dir`
514514
515+
[HELP] available template variables are `{workspace-root}`, `{cargo-cache-home}`, `{workspace-path-hash}`
516+
517+
"#]])
518+
.run();
519+
}
520+
521+
#[cargo_test]
522+
fn template_should_suggest_nearest_variable() {
523+
let p = project()
524+
.file("src/lib.rs", "")
525+
.file(
526+
".cargo/config.toml",
527+
r#"
528+
[build]
529+
build-dir = "{workspace-ro}/build-dir"
530+
"#,
531+
)
532+
.build();
533+
534+
p.cargo("build -Z build-dir")
535+
.masquerade_as_nightly_cargo(&["build-dir"])
536+
.with_status(101)
537+
.with_stderr_data(str![[r#"
538+
[ERROR] unexpected variable `workspace-ro` in build.build-dir path `{workspace-ro}/build-dir`
539+
540+
[HELP] a template variable with a similar name exists: `workspace-root`
541+
515542
"#]])
516543
.run();
517544
}

0 commit comments

Comments
 (0)