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:
2026-09-19 00:52:31 +02:00
parent bd8f814a53
commit 6caedce61a
11 changed files with 154 additions and 66 deletions
+37 -18
View File
@@ -5,13 +5,30 @@ use std::fs::File;
use std::io::{Read, Write};
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
pub fn generate_entry(
changelog_file: &str,
cwd: Option<&Path>,
user_version: 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 {
path.join(changelog_file)
} else {
@@ -19,8 +36,7 @@ pub fn generate_entry(
};
// Parse existing changelog to get current (old) version
let (package, old_version, series) = parse_changelog_header(&changelog_path)?;
log::info!("Found package: {}, version: {}", package, old_version);
let (package, old_version, current_series) = parse_changelog_header(&changelog_path)?;
// Open git repo, and find commits since last version tag
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 series = target_series.unwrap_or(&series).to_string();
let series = target_series.unwrap_or(&current_series).to_string();
let new_entry = format_entry(
&package,
&new_version,
@@ -56,9 +72,13 @@ pub fn generate_entry(
prepend_to_file(&changelog_path, &new_entry)?;
log::info!("Added new changelog entry to {}", changelog_path.display());
Ok(())
Ok(GeneratedEntry {
package,
previous_version: old_version,
new_version,
series,
path: changelog_path,
})
}
/// 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 {
match crate::distro_info::get_dist_from_series(&current).await {
Ok(dist) => {
match crate::distro_info::get_ordered_series_name(&dist).await {
Ok(options) if !options.is_empty() => Some(SeriesCandidates::Choose {
options,
default: current.clone(),
fallback: current,
}),
// An empty list offers nothing to choose from
_ => Some(SeriesCandidates::Keep(current)),
}
}
Ok(dist) => match crate::distro_info::get_ordered_series_name(&dist).await {
// Even an empty list goes through the selector: its
// fallback prints and takes the default, like it always has
Ok(options) => Some(SeriesCandidates::Choose {
options,
default: current.clone(),
fallback: current,
}),
Err(_) => Some(SeriesCandidates::Keep(current)),
},
Err(_) => Some(SeriesCandidates::Keep(current)),
}
}