ui: cleaner transient and completion output for pkh put
This commit is contained in:
+73
-12
@@ -75,22 +75,37 @@ pub async fn put(
|
|||||||
None => discover_changes(&opts.cwd)?,
|
None => discover_changes(&opts.cwd)?,
|
||||||
};
|
};
|
||||||
let changes = changes::parse(&changes_path)?;
|
let changes = changes::parse(&changes_path)?;
|
||||||
info!(
|
|
||||||
"Uploading {} {} ({}) to {}",
|
// The summary line stays up for the whole flow: the completion message
|
||||||
changes.source,
|
// replaces it on success, and the `PutBars` guard clears it on every
|
||||||
changes.version,
|
// early `?` bail so the error logged by main is not preceded by stale
|
||||||
ui::display_path(&changes_path),
|
// bars
|
||||||
target.label
|
let mut bars = PutBars::default();
|
||||||
);
|
let summary = multi.add(ProgressBar::new(0));
|
||||||
|
// Style and prefix go in before the steady tick: otherwise the first
|
||||||
|
// tick can render one frame with the default bar template
|
||||||
|
summary.set_style(ui::spinner_style());
|
||||||
|
summary.set_prefix(format!(
|
||||||
|
"Uploading {} {} to {}",
|
||||||
|
changes.source, changes.version, target.label
|
||||||
|
));
|
||||||
|
summary.enable_steady_tick(TICK);
|
||||||
|
bars.track(summary.clone());
|
||||||
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
|
||||||
// processing: a valid Section, a known target series, and the target
|
// processing: a valid Section, a known target series, and the target
|
||||||
// PPA actually existing (the SFTP queue itself is a blind write)
|
// PPA actually existing (the SFTP queue itself is a blind write)
|
||||||
check_control_section(&opts.cwd, "ubuntu")?;
|
check_control_section(&opts.cwd, "ubuntu")?;
|
||||||
info!("Checking {} on Launchpad...", target.label);
|
|
||||||
|
let checking = multi.add(ProgressBar::new(0));
|
||||||
|
checking.set_style(ui::spinner_style());
|
||||||
|
checking.set_prefix(format!("Checking {} on Launchpad...", target.label));
|
||||||
|
checking.enable_steady_tick(TICK);
|
||||||
|
bars.track(checking.clone());
|
||||||
launchpad::ppa_info(&opts.ppa).await?;
|
launchpad::ppa_info(&opts.ppa).await?;
|
||||||
launchpad::check_ppa_series(&changes.distribution).await?;
|
launchpad::check_ppa_series(&changes.distribution).await?;
|
||||||
|
clear_bar(&checking);
|
||||||
|
|
||||||
// Last pre-flight check: a version the PPA already publishes at or
|
// Last pre-flight check: a version the PPA already publishes at or
|
||||||
// above the changes' one would supersede (or reject) this upload
|
// above the changes' one would supersede (or reject) this upload
|
||||||
@@ -108,9 +123,14 @@ pub async fn put(
|
|||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Connecting to {login}@{host}:{port}...");
|
let connecting = multi.add(ProgressBar::new(0));
|
||||||
|
connecting.set_style(ui::spinner_style());
|
||||||
|
connecting.set_prefix(format!("Connecting to {login}@{host}:{port}..."));
|
||||||
|
connecting.enable_steady_tick(TICK);
|
||||||
|
bars.track(connecting.clone());
|
||||||
let session = ssh::connect(&host, port, &login, &ssh_config)?;
|
let session = ssh::connect(&host, port, &login, &ssh_config)?;
|
||||||
let sftp = ssh::sftp(&session)?;
|
let sftp = ssh::sftp(&session)?;
|
||||||
|
clear_bar(&connecting);
|
||||||
|
|
||||||
// Payload first, the .changes file last (like dput), so the server-side
|
// Payload first, the .changes file last (like dput), so the server-side
|
||||||
// queue processor can never pick up an incomplete upload
|
// queue processor can never pick up an incomplete upload
|
||||||
@@ -146,14 +166,55 @@ pub async fn put(
|
|||||||
|
|
||||||
record_upload(&upload_log_path()?, &record)?;
|
record_upload(&upload_log_path()?, &record)?;
|
||||||
|
|
||||||
|
// The completion lines replace the summary bar; the guard's own clear
|
||||||
|
// at scope exit is a no-op for the already-finished bars
|
||||||
|
clear_bar(&summary);
|
||||||
info!(
|
info!(
|
||||||
"Upload of {changes_name} to {} complete. Launchpad processes it asynchronously; \
|
"Upload of {} {} to {} complete.",
|
||||||
watch the PPA page or your inbox for acceptance/rejection",
|
changes.source, changes.version, target.label
|
||||||
target.label
|
);
|
||||||
|
info!(
|
||||||
|
"Launchpad processes it asynchronously; watch the PPA page or your \
|
||||||
|
inbox for acceptance/rejection"
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Steady tick interval of every bar rendered by a `put` run
|
||||||
|
const TICK: std::time::Duration = std::time::Duration::from_millis(50);
|
||||||
|
|
||||||
|
/// Stop `bar`'s steady tick and clear it from the terminal. The tick is
|
||||||
|
/// disabled first: a tick firing right after the clear would redraw a stale
|
||||||
|
/// frame, the race [`crate::ui::deb::DebUi::suspend`] guards against too.
|
||||||
|
/// Clearing twice is harmless: finished bars stay finished.
|
||||||
|
fn clear_bar(bar: &ProgressBar) {
|
||||||
|
bar.disable_steady_tick();
|
||||||
|
bar.finish_and_clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The bars rendered by one `put` run, cleared when the guard drops. The
|
||||||
|
/// error paths bail out early through `?` and `main` logs the error
|
||||||
|
/// afterwards, so a bar left unfinished would linger on screen above it.
|
||||||
|
#[derive(Default)]
|
||||||
|
struct PutBars {
|
||||||
|
bars: Vec<ProgressBar>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PutBars {
|
||||||
|
/// Track `bar` so it is cleared with the rest when the guard drops
|
||||||
|
fn track(&mut self, bar: ProgressBar) {
|
||||||
|
self.bars.push(bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for PutBars {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
for bar in &self.bars {
|
||||||
|
clear_bar(bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Validate the source package's `Section` (debian/control source stanza)
|
/// Validate the source package's `Section` (debian/control source stanza)
|
||||||
/// against the distribution's valid sections: a bare section or a
|
/// against the distribution's valid sections: a bare section or a
|
||||||
/// `section/subsection` is accepted. Archives reject uploads carrying an
|
/// `section/subsection` is accepted. Archives reject uploads carrying an
|
||||||
|
|||||||
Reference in New Issue
Block a user