|
| 1 | +use std::future::Future; |
| 2 | +use std::io::Write; |
1 | 3 | use std::process::Command;
|
| 4 | +use std::time::Duration; |
2 | 5 |
|
3 | 6 | use anyhow::{Context, Result};
|
4 | 7 | use ostree::glib;
|
@@ -87,6 +90,35 @@ pub(crate) fn medium_visibility_warning(s: &str) {
|
87 | 90 | std::thread::sleep(std::time::Duration::from_secs(1));
|
88 | 91 | }
|
89 | 92 |
|
| 93 | +/// Call an async task function, and write a message to stdout |
| 94 | +/// with an automatic spinner to show that we're not blocked. |
| 95 | +/// Note that generally the called function should not output |
| 96 | +/// anything to stdout as this will interfere with the spinner. |
| 97 | +pub(crate) async fn async_task_with_spinner<F, T>(msg: &'static str, f: F) -> T |
| 98 | +where |
| 99 | + F: Future<Output = T>, |
| 100 | +{ |
| 101 | + let pb = indicatif::ProgressBar::new_spinner(); |
| 102 | + let style = indicatif::ProgressStyle::default_bar(); |
| 103 | + pb.set_style(style.template("{spinner} {msg}").unwrap()); |
| 104 | + pb.set_message(msg); |
| 105 | + pb.enable_steady_tick(Duration::from_millis(150)); |
| 106 | + // We need to handle the case where we aren't connected to |
| 107 | + // a tty, so indicatif would show nothing by default. |
| 108 | + if pb.is_hidden() { |
| 109 | + print!("{}...", msg); |
| 110 | + std::io::stdout().flush().unwrap(); |
| 111 | + } else { |
| 112 | + } |
| 113 | + let r = f.await; |
| 114 | + if pb.is_hidden() { |
| 115 | + println!("done"); |
| 116 | + } else { |
| 117 | + pb.finish_with_message(format!("{msg}: done")); |
| 118 | + } |
| 119 | + r |
| 120 | +} |
| 121 | + |
90 | 122 | /// Given a possibly tagged image like quay.io/foo/bar:latest and a digest 0ab32..., return
|
91 | 123 | /// the digested form quay.io/foo/bar:latest@sha256:0ab32...
|
92 | 124 | /// If the image already has a digest, it will be replaced.
|
|
0 commit comments