report: reproduce the pre-refactor CLI output through the ports
Instead of carrying raw UI in core, the ports now represent everything
the CLI used to do inline:
- Prompter::present shows context outside of a question (the wizard
summary screen, the vendoring notice spacing); TerminalPrompter
prints it on stdout exactly like the println!s it replaces, server
embeds forward it as a display event.
- generate_entry returns the generated entry (package, versions,
series, path) instead of printing; the CLI renders the same lines.
- BuildTarget carries a flow-composed display line and a tee_log flag:
the terminal adapter renders it verbatim ("Building source package
...", "Building ... for series/arch", "Uploading ... to ...") and
uploads open no build log.
- The unmet build-dependency diagnostics are rendered by the CLI from
the typed error, in the original order (details, then summary).
- --verbose constructs no live view at all (an idle widget used to
linger), and the re-vendor offer only logs when it is actually
asked, so headless runs print the error exactly once.
This commit is contained in:
+17
-3
@@ -169,6 +169,13 @@ fn retry_after_revendor(
|
|||||||
opts: &SourceBuildOptions,
|
opts: &SourceBuildOptions,
|
||||||
original: Box<dyn Error>,
|
original: Box<dyn Error>,
|
||||||
) -> Result<SourceBuildOutput, Box<dyn Error>> {
|
) -> Result<SourceBuildOutput, Box<dyn Error>> {
|
||||||
|
// The offer is only made when someone can answer it: headless prompters
|
||||||
|
// answer with the default (false) without the error being logged here —
|
||||||
|
// the caller logs the returned error itself, exactly once.
|
||||||
|
if !prompter.interactive() {
|
||||||
|
view.finish_failure();
|
||||||
|
return Err(original);
|
||||||
|
}
|
||||||
log::error!("{original}");
|
log::error!("{original}");
|
||||||
if !prompter
|
if !prompter
|
||||||
.confirm(
|
.confirm(
|
||||||
@@ -301,7 +308,14 @@ pub fn run_source_build(
|
|||||||
package: &entry.source,
|
package: &entry.source,
|
||||||
version: &entry.version.full(),
|
version: &entry.version.full(),
|
||||||
target: &entry.distribution,
|
target: &entry.distribution,
|
||||||
|
display: format!(
|
||||||
|
"Building source package {} ({}) for {}",
|
||||||
|
entry.source,
|
||||||
|
entry.version.full(),
|
||||||
|
entry.distribution
|
||||||
|
),
|
||||||
source_only: true,
|
source_only: true,
|
||||||
|
tee_log: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
let source_display = entry.source.clone();
|
let source_display = entry.source.clone();
|
||||||
@@ -389,9 +403,9 @@ pub fn run_source_build(
|
|||||||
};
|
};
|
||||||
let report = crate::debian::deps::check_build_depends(&ctrl, &check_opts)?;
|
let report = crate::debian::deps::check_build_depends(&ctrl, &check_opts)?;
|
||||||
if !report.is_ok() {
|
if !report.is_ok() {
|
||||||
// The diagnostics travel inside the error (its Display carries
|
// The typed error carries the diagnostics (UnmetReport is
|
||||||
// report.message()); main renders it and maps the type to exit
|
// public); the caller renders them and maps the type to exit
|
||||||
// status 3, like dpkg-buildpackage.
|
// status 3, like dpkg-buildpackage does.
|
||||||
return Err(Box::new(crate::debian::deps::UnmetBuildDependencies(
|
return Err(Box::new(crate::debian::deps::UnmetBuildDependencies(
|
||||||
report,
|
report,
|
||||||
)));
|
)));
|
||||||
|
|||||||
+37
-18
@@ -5,13 +5,30 @@ use std::fs::File;
|
|||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
/// Outcome of a successful [`generate_entry`] call: everything the CLI
|
||||||
|
/// renders for the user, and everything a library consumer needs to chain
|
||||||
|
/// further steps.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct GeneratedEntry {
|
||||||
|
/// Source package name from the previous changelog entry.
|
||||||
|
pub package: String,
|
||||||
|
/// Version the changelog carried before the new entry was prepended.
|
||||||
|
pub previous_version: String,
|
||||||
|
/// Version of the freshly added entry.
|
||||||
|
pub new_version: String,
|
||||||
|
/// Distribution series the new entry targets.
|
||||||
|
pub series: String,
|
||||||
|
/// The changelog file that was updated.
|
||||||
|
pub path: std::path::PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
/// Automatically generate a changelog entry from a commit history and previous changelog
|
/// Automatically generate a changelog entry from a commit history and previous changelog
|
||||||
pub fn generate_entry(
|
pub fn generate_entry(
|
||||||
changelog_file: &str,
|
changelog_file: &str,
|
||||||
cwd: Option<&Path>,
|
cwd: Option<&Path>,
|
||||||
user_version: Option<&str>,
|
user_version: Option<&str>,
|
||||||
target_series: Option<&str>,
|
target_series: Option<&str>,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<GeneratedEntry, Box<dyn std::error::Error>> {
|
||||||
let changelog_path = if let Some(path) = cwd {
|
let changelog_path = if let Some(path) = cwd {
|
||||||
path.join(changelog_file)
|
path.join(changelog_file)
|
||||||
} else {
|
} else {
|
||||||
@@ -19,8 +36,7 @@ pub fn generate_entry(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Parse existing changelog to get current (old) version
|
// Parse existing changelog to get current (old) version
|
||||||
let (package, old_version, series) = parse_changelog_header(&changelog_path)?;
|
let (package, old_version, current_series) = parse_changelog_header(&changelog_path)?;
|
||||||
log::info!("Found package: {}, version: {}", package, old_version);
|
|
||||||
|
|
||||||
// Open git repo, and find commits since last version tag
|
// Open git repo, and find commits since last version tag
|
||||||
let repo_path = if let Some(path) = cwd {
|
let repo_path = if let Some(path) = cwd {
|
||||||
@@ -44,7 +60,7 @@ pub fn generate_entry(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let (maintainer_name, maintainer_email) = get_maintainer_info()?;
|
let (maintainer_name, maintainer_email) = get_maintainer_info()?;
|
||||||
let series = target_series.unwrap_or(&series).to_string();
|
let series = target_series.unwrap_or(¤t_series).to_string();
|
||||||
let new_entry = format_entry(
|
let new_entry = format_entry(
|
||||||
&package,
|
&package,
|
||||||
&new_version,
|
&new_version,
|
||||||
@@ -56,9 +72,13 @@ pub fn generate_entry(
|
|||||||
|
|
||||||
prepend_to_file(&changelog_path, &new_entry)?;
|
prepend_to_file(&changelog_path, &new_entry)?;
|
||||||
|
|
||||||
log::info!("Added new changelog entry to {}", changelog_path.display());
|
Ok(GeneratedEntry {
|
||||||
|
package,
|
||||||
Ok(())
|
previous_version: old_version,
|
||||||
|
new_version,
|
||||||
|
series,
|
||||||
|
path: changelog_path,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the next (most probable) version number of a package, from old version and
|
/// Compute the next (most probable) version number of a package, from old version and
|
||||||
@@ -195,17 +215,16 @@ pub async fn series_candidates(changelog_path: &Path) -> Option<SeriesCandidates
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match crate::distro_info::get_dist_from_series(¤t).await {
|
match crate::distro_info::get_dist_from_series(¤t).await {
|
||||||
Ok(dist) => {
|
Ok(dist) => match crate::distro_info::get_ordered_series_name(&dist).await {
|
||||||
match crate::distro_info::get_ordered_series_name(&dist).await {
|
// Even an empty list goes through the selector: its
|
||||||
Ok(options) if !options.is_empty() => Some(SeriesCandidates::Choose {
|
// fallback prints and takes the default, like it always has
|
||||||
options,
|
Ok(options) => Some(SeriesCandidates::Choose {
|
||||||
default: current.clone(),
|
options,
|
||||||
fallback: current,
|
default: current.clone(),
|
||||||
}),
|
fallback: current,
|
||||||
// An empty list offers nothing to choose from
|
}),
|
||||||
_ => Some(SeriesCandidates::Keep(current)),
|
Err(_) => Some(SeriesCandidates::Keep(current)),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
Err(_) => Some(SeriesCandidates::Keep(current)),
|
Err(_) => Some(SeriesCandidates::Keep(current)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -225,7 +225,9 @@ async fn build_binary_package_impl(
|
|||||||
package: &package,
|
package: &package,
|
||||||
version: &version,
|
version: &version,
|
||||||
target: &format!("{series}/{arch}"),
|
target: &format!("{series}/{arch}"),
|
||||||
|
display: format!("Building {package} ({version}) for {series}/{arch}"),
|
||||||
source_only: false,
|
source_only: false,
|
||||||
|
tee_log: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create an ephemeral unshare context for all Local builds. It is kept in
|
// Create an ephemeral unshare context for all Local builds. It is kept in
|
||||||
|
|||||||
+1
-5
@@ -890,11 +890,7 @@ pub struct UnmetBuildDependencies(pub UnmetReport);
|
|||||||
|
|
||||||
impl std::fmt::Display for UnmetBuildDependencies {
|
impl std::fmt::Display for UnmetBuildDependencies {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(
|
write!(f, "build dependencies/conflicts unsatisfied; aborting")
|
||||||
f,
|
|
||||||
"build dependencies/conflicts unsatisfied; aborting\n{}",
|
|
||||||
self.0.message()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+39
-10
@@ -418,15 +418,23 @@ fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = generate_entry(
|
let entry = match generate_entry(
|
||||||
"debian/changelog",
|
"debian/changelog",
|
||||||
Some(&cwd),
|
Some(&cwd),
|
||||||
version,
|
version,
|
||||||
target_series.as_deref(),
|
target_series.as_deref(),
|
||||||
) {
|
) {
|
||||||
error!("{}", e);
|
Ok(entry) => entry,
|
||||||
std::process::exit(1);
|
Err(e) => {
|
||||||
}
|
error!("{}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
println!(
|
||||||
|
"Found package: {}, version: {}",
|
||||||
|
entry.package, entry.previous_version
|
||||||
|
);
|
||||||
|
println!("Added new changelog entry to {}", entry.path.display());
|
||||||
|
|
||||||
let editor = match std::env::var("EDITOR") {
|
let editor = match std::env::var("EDITOR") {
|
||||||
Ok(e) => e,
|
Ok(e) => e,
|
||||||
@@ -461,8 +469,15 @@ fn main() {
|
|||||||
// Live build view, unless --verbose (DebUi additionally disables
|
// Live build view, unless --verbose (DebUi additionally disables
|
||||||
// itself when stdout is not a terminal)
|
// itself when stdout is not a terminal)
|
||||||
let quiet = pkh::report::Quiet;
|
let quiet = pkh::report::Quiet;
|
||||||
let live = pkh::ui::deb::DebUi::new(&multi);
|
let live = if verbose {
|
||||||
let view: &dyn pkh::report::BuildView = if verbose { &quiet } else { &live };
|
None
|
||||||
|
} else {
|
||||||
|
Some(pkh::ui::deb::DebUi::new(&multi))
|
||||||
|
};
|
||||||
|
let view: &dyn pkh::report::BuildView = live
|
||||||
|
.as_ref()
|
||||||
|
.map(|v| v as &dyn pkh::report::BuildView)
|
||||||
|
.unwrap_or(&quiet);
|
||||||
let prompter = pkh::ui::prompt::TerminalPrompter;
|
let prompter = pkh::ui::prompt::TerminalPrompter;
|
||||||
|
|
||||||
let orig_source = match sub_matches.get_one::<String>("orig").map(String::as_str) {
|
let orig_source = match sub_matches.get_one::<String>("orig").map(String::as_str) {
|
||||||
@@ -490,12 +505,19 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if output.signed {
|
if output.signed {
|
||||||
info!("Package built and signed successfully!");
|
println!("Package built and signed successfully!");
|
||||||
} else {
|
} else {
|
||||||
info!("Package built successfully (unsigned).");
|
println!("Package built successfully (unsigned).");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
// The unmet-dependency diagnostics first, then the
|
||||||
|
// summary: the exact rendering the flow used to do.
|
||||||
|
if let Some(unmet) =
|
||||||
|
e.downcast_ref::<pkh::debian::deps::UnmetBuildDependencies>()
|
||||||
|
{
|
||||||
|
eprintln!("{}", unmet.0.message());
|
||||||
|
}
|
||||||
error!("{}", e);
|
error!("{}", e);
|
||||||
// Unmet build dependencies/conflicts exit with status 3,
|
// Unmet build dependencies/conflicts exit with status 3,
|
||||||
// like dpkg-buildpackage does.
|
// like dpkg-buildpackage does.
|
||||||
@@ -581,8 +603,15 @@ fn main() {
|
|||||||
// Live build view, unless --verbose (DebUi additionally disables
|
// Live build view, unless --verbose (DebUi additionally disables
|
||||||
// itself when stdout is not a terminal)
|
// itself when stdout is not a terminal)
|
||||||
let quiet = pkh::report::Quiet;
|
let quiet = pkh::report::Quiet;
|
||||||
let live = pkh::ui::deb::DebUi::new(&multi);
|
let live = if verbose {
|
||||||
let view: &dyn pkh::report::BuildView = if verbose { &quiet } else { &live };
|
None
|
||||||
|
} else {
|
||||||
|
Some(pkh::ui::deb::DebUi::new(&multi))
|
||||||
|
};
|
||||||
|
let view: &dyn pkh::report::BuildView = live
|
||||||
|
.as_ref()
|
||||||
|
.map(|v| v as &dyn pkh::report::BuildView)
|
||||||
|
.unwrap_or(&quiet);
|
||||||
|
|
||||||
let result = rt.block_on(async {
|
let result = rt.block_on(async {
|
||||||
pkh::deb::build_binary_package(pkh::deb::DebBuildOptions {
|
pkh::deb::build_binary_package(pkh::deb::DebBuildOptions {
|
||||||
|
|||||||
@@ -541,7 +541,7 @@ async fn run_wizard(
|
|||||||
|
|
||||||
// Summary screen + final confirmation: Ctrl+C or 'n' abort with
|
// Summary screen + final confirmation: Ctrl+C or 'n' abort with
|
||||||
// nothing written (generation is all-or-nothing later anyway).
|
// nothing written (generation is all-or-nothing later anyway).
|
||||||
log::info!("{}", summary_text(&opts, toolchain_pin.as_deref()));
|
prompter.present(&summary_text(&opts, toolchain_pin.as_deref()));
|
||||||
if !prompter.confirm("Generate?", true)? {
|
if !prompter.confirm("Generate?", true)? {
|
||||||
return Err("Aborted: nothing was written to disk.".into());
|
return Err("Aborted: nothing was written to disk.".into());
|
||||||
}
|
}
|
||||||
@@ -575,6 +575,9 @@ pub async fn offer_verification(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if outcome.vendoring_failed {
|
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.
|
||||||
|
prompter.present("");
|
||||||
log::warn!(
|
log::warn!(
|
||||||
"The Cargo dependencies could NOT be vendored: this package will \
|
"The Cargo dependencies could NOT be vendored: this package will \
|
||||||
not build until the vendoring is completed by hand:\n\
|
not build until the vendoring is completed by hand:\n\
|
||||||
@@ -582,6 +585,7 @@ pub async fn offer_verification(
|
|||||||
\x20 2. add the printed source replacement to .cargo/config.toml, \
|
\x20 2. add the printed source replacement to .cargo/config.toml, \
|
||||||
plus `[net] offline = true`"
|
plus `[net] offline = true`"
|
||||||
);
|
);
|
||||||
|
prompter.present("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if no_verify || !prompter.interactive() {
|
if no_verify || !prompter.interactive() {
|
||||||
|
|||||||
@@ -976,8 +976,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
/// Serve canned byte responses on a local port, one per connection (the
|
/// Serve canned byte responses on a local port, one per connection (the
|
||||||
/// last response repeats), and return the base URL
|
/// last response repeats), and return the base URL
|
||||||
///
|
///
|
||||||
|
|||||||
+15
-5
@@ -26,7 +26,7 @@ use crate::debian::checksums::FileChecksums;
|
|||||||
use crate::debian::control::ControlInfo;
|
use crate::debian::control::ControlInfo;
|
||||||
use crate::debian::version::DebianVersion;
|
use crate::debian::version::DebianVersion;
|
||||||
use crate::launchpad;
|
use crate::launchpad;
|
||||||
use crate::report::{BuildView, Prompter};
|
use crate::report::{BuildTarget, BuildView, Prompter};
|
||||||
|
|
||||||
/// Everything `put` needs to run.
|
/// Everything `put` needs to run.
|
||||||
pub struct PutOptions<'a> {
|
pub struct PutOptions<'a> {
|
||||||
@@ -89,10 +89,20 @@ async fn put_impl(opts: &PutOptions<'_>) -> Result<(), Box<dyn std::error::Error
|
|||||||
};
|
};
|
||||||
let changes = changes::parse(&changes_path)?;
|
let changes = changes::parse(&changes_path)?;
|
||||||
|
|
||||||
opts.view.message(&format!(
|
// The summary line stays up for the whole flow: rendered as the view's
|
||||||
"Uploading {} {} to {}",
|
// persistent status, with the per-step messages below it
|
||||||
changes.source, changes.version, target.label
|
opts.view.target(BuildTarget {
|
||||||
));
|
package: &changes.source,
|
||||||
|
version: &changes.version,
|
||||||
|
target: &target.label,
|
||||||
|
display: format!(
|
||||||
|
"Uploading {} {} to {}",
|
||||||
|
changes.source, changes.version, target.label
|
||||||
|
),
|
||||||
|
source_only: false,
|
||||||
|
// An upload runs no subprocess: nothing to tee
|
||||||
|
tee_log: false,
|
||||||
|
});
|
||||||
changes::validate(&changes)?;
|
changes::validate(&changes)?;
|
||||||
|
|
||||||
// Pre-flight checks for everything the upload queue only rejects after
|
// Pre-flight checks for everything the upload queue only rejects after
|
||||||
|
|||||||
+23
-4
@@ -30,18 +30,28 @@ pub type Validator = dyn Fn(&str) -> Result<(), String>;
|
|||||||
|
|
||||||
/// Identity of the build whose events follow, as announced through
|
/// Identity of the build whose events follow, as announced through
|
||||||
/// [`BuildView::target`].
|
/// [`BuildView::target`].
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BuildTarget<'a> {
|
pub struct BuildTarget<'a> {
|
||||||
/// Source package name (e.g. `hello`).
|
/// Source package name (e.g. `hello`).
|
||||||
pub package: &'a str,
|
pub package: &'a str,
|
||||||
/// Full version being built (e.g. `2.10-3`).
|
/// Full version being built (e.g. `2.10-3`).
|
||||||
pub version: &'a str,
|
pub version: &'a str,
|
||||||
/// What the build targets: a distribution series, optionally with an
|
/// What the build targets: a distribution series, optionally with an
|
||||||
/// architecture (`noble`, `sid`, `noble/arm64`).
|
/// architecture (`noble`, `sid`, `noble/arm64`), or the upload target
|
||||||
|
/// label.
|
||||||
pub target: &'a str,
|
pub target: &'a str,
|
||||||
/// Whether this is a source-only build (producing a `.dsc`) as opposed
|
/// Ready-to-render status line for display adapters, composed by the
|
||||||
/// to a binary build (producing `.deb` files).
|
/// flow (e.g. "Building source package hello (2.10-3) for unstable",
|
||||||
|
/// "Uploading hello (2.10-3) to ppa:user/ppa"): the wording is the
|
||||||
|
/// flow's, adapters render it verbatim.
|
||||||
|
pub display: String,
|
||||||
|
/// Whether this is a source-only build (producing a `.dsc`); names the
|
||||||
|
/// terminal adapter's tee log (`build-*.log` vs `deb-*.log`).
|
||||||
pub source_only: bool,
|
pub source_only: bool,
|
||||||
|
/// Whether the view should tee raw subprocess output to its log file.
|
||||||
|
/// Flows without subprocess output (uploads) pass `false` and create
|
||||||
|
/// no log file.
|
||||||
|
pub tee_log: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Observer of a running build: target identification, phases, status
|
/// Observer of a running build: target identification, phases, status
|
||||||
@@ -156,6 +166,15 @@ pub trait Prompter: Send + Sync {
|
|||||||
fn accept_host_key(&self, _host: &str, _key_type: &str, _fingerprint: &str) -> bool {
|
fn accept_host_key(&self, _host: &str, _key_type: &str, _fingerprint: &str) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Present information to the user outside of any question: the
|
||||||
|
/// scaffold wizard's summary screen, prominent notices around a
|
||||||
|
/// warning. Terminal implementations print the text as-is (unstyled,
|
||||||
|
/// on stdout); server implementations forward it as a display event.
|
||||||
|
/// Implementations that cannot show anything drop it — flows only
|
||||||
|
/// present context that is also available structurally (returned data,
|
||||||
|
/// log records).
|
||||||
|
fn present(&self, _text: &str) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inert view and prompter: drops every event and answers every question
|
/// Inert view and prompter: drops every event and answers every question
|
||||||
|
|||||||
+11
-18
@@ -83,8 +83,7 @@ impl DebUi {
|
|||||||
let pb = multi.add(ProgressBar::new(0));
|
let pb = multi.add(ProgressBar::new(0));
|
||||||
pb.enable_steady_tick(Duration::from_millis(80));
|
pb.enable_steady_tick(Duration::from_millis(80));
|
||||||
pb.set_style(spinner_style());
|
pb.set_style(spinner_style());
|
||||||
// Neutral identity until a `target` event names the build
|
pb.set_prefix("Building package");
|
||||||
pb.set_prefix("pkh");
|
|
||||||
pb.set_message("(starting…)");
|
pb.set_message("(starting…)");
|
||||||
pb
|
pb
|
||||||
} else {
|
} else {
|
||||||
@@ -270,24 +269,18 @@ impl DebUi {
|
|||||||
/// widget.
|
/// widget.
|
||||||
impl crate::report::BuildView for DebUi {
|
impl crate::report::BuildView for DebUi {
|
||||||
fn target(&self, target: BuildTarget<'_>) {
|
fn target(&self, target: BuildTarget<'_>) {
|
||||||
let kind = if target.source_only {
|
|
||||||
"source package "
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
};
|
|
||||||
if self.shared.enabled {
|
if self.shared.enabled {
|
||||||
self.shared.top.set_prefix(format!(
|
self.shared.top.set_prefix(target.display.clone());
|
||||||
"Building {kind}{} ({}) for {}",
|
}
|
||||||
target.package, target.version, target.target
|
if target.tee_log {
|
||||||
));
|
let kind = if target.source_only { "build" } else { "deb" };
|
||||||
|
self.open_log(
|
||||||
|
kind,
|
||||||
|
target.package,
|
||||||
|
target.version,
|
||||||
|
&format!("for {}", target.target),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let log_kind = if target.source_only { "build" } else { "deb" };
|
|
||||||
self.open_log(
|
|
||||||
log_kind,
|
|
||||||
target.package,
|
|
||||||
target.version,
|
|
||||||
&format!("for {}", target.target),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn phase(&self, name: &str, classifier: Box<dyn Classifier>) {
|
fn phase(&self, name: &str, classifier: Box<dyn Classifier>) {
|
||||||
|
|||||||
@@ -167,6 +167,10 @@ impl crate::report::Prompter for TerminalPrompter {
|
|||||||
println!("{key_type} key fingerprint is {fingerprint}.");
|
println!("{key_type} key fingerprint is {fingerprint}.");
|
||||||
confirm("Accept and store this host key?", false).unwrap_or(false)
|
confirm("Accept and store this host key?", false).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn present(&self, text: &str) {
|
||||||
|
println!("{text}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run `prompt` with the terminal in raw mode, always restoring it
|
/// Run `prompt` with the terminal in raw mode, always restoring it
|
||||||
|
|||||||
Reference in New Issue
Block a user