new: surface cargo vendor failures and pin the vendoring toolchain

This commit is contained in:
2026-09-16 23:24:43 +02:00
parent 9cb3e29a3e
commit 84824f61c6
5 changed files with 415 additions and 111 deletions
+55 -8
View File
@@ -24,7 +24,7 @@ use indicatif::MultiProgress;
use crate::new::detect::{self, Detection};
use crate::new::options::{self, NewCli, NewOptions, SourceDir, TemplateId};
use crate::new::templates::{self, ProbeResult};
use crate::new::templates::{self, ProbeResult, ScaffoldOutcome};
use crate::ui::prompt;
/// Answer of the "where is the source code?" question: fresh skeleton.
@@ -411,10 +411,17 @@ async fn run_wizard(mut cli: NewCli) -> Result<NewOptions, Box<dyn Error>> {
/// (`pkh build`, offered yes) and the binary build (`pkh deb`, offered no —
/// it needs network + build deps). A failed verification build never undoes
/// the scaffold: the error is printed together with the manual next steps.
pub async fn offer_verification(opts: &NewOptions, multi: &MultiProgress, no_verify: bool) {
if no_verify || !is_interactive() {
return;
}
///
/// When the scaffold's vendoring step failed (`outcome`), a prominent notice
/// states that the tree will not build until the dependencies are vendored —
/// printed with or without a TTY — and the build offer is reworded with its
/// default flipped to *no*.
pub async fn offer_verification(
opts: &NewOptions,
outcome: &ScaffoldOutcome,
multi: &MultiProgress,
no_verify: bool,
) {
let tree = opts.target_dir(&std::env::current_dir().unwrap_or_default());
let display = crate::ui::display_path(&tree);
let display = if display.is_empty() {
@@ -423,7 +430,30 @@ pub async fn offer_verification(opts: &NewOptions, multi: &MultiProgress, no_ver
display
};
let verify_source = match prompt::confirm("Verify with `pkh build` now?", true) {
if outcome.vendoring_failed {
// Set apart from the surrounding success output by blank lines: a
// single warning between two success lines is easy to miss.
println!();
log::warn!(
"The Cargo dependencies could NOT be vendored: this package will \
not build until the vendoring is completed by hand:\n\
\x20 1. `cd {display} && cargo vendor`\n\
\x20 2. add the printed source replacement to .cargo/config.toml, \
plus `[net] offline = true`"
);
println!();
}
if no_verify || !is_interactive() {
return;
}
let build_offer = if outcome.vendoring_failed {
"Verify with `pkh build` now? (it will fail until dependencies are vendored)"
} else {
"Verify with `pkh build` now?"
};
let verify_source = match prompt::confirm(build_offer, !outcome.vendoring_failed) {
Ok(answer) => answer,
Err(_) => return,
};
@@ -720,8 +750,12 @@ pub fn summary_text(opts: &NewOptions) -> String {
lines.push(format!(" Depends {}", opts.depends.join(", ")));
}
} else if opts.template == TemplateId::Rust {
lines
.push(" debian/rules cargo build --release --offline (vendored)".to_string());
// Nothing is vendored yet at this point: only announce that the
// generation will attempt it.
lines.push(
" debian/rules cargo build --release --offline (vendored at generation)"
.to_string(),
);
} else {
lines.push(format!(" debian/rules {}", template.rules_dh_line()));
}
@@ -948,6 +982,19 @@ mod tests {
assert!(text.contains("debian/watch release watcher"), "{text}");
}
/// The rust summary only announces the vendoring attempt of the
/// generation, it must not assert an outcome that has not been tried
/// yet (regression: it claimed "(vendored)" before generating).
#[test]
fn summary_screen_rust_does_not_presume_vendoring() {
let text = summary_text(&opts(Tid::Rust));
assert!(
text.contains("cargo build --release --offline (vendored at generation)"),
"{text}"
);
assert!(!text.contains("(vendored)"), "{text}");
}
#[test]
fn answer_validators() {
assert!(validate_revision_answer("1").is_ok());