summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2022-12-19 14:31:19 -0500
committerGitHub <noreply@github.com>2022-12-19 14:31:19 -0500
commit2ff27a1f9327bf913d7b9d6aadc703a30a297e11 (patch)
tree2643c8b11279542c462c6c3d50da5f89d22e0d8f /cli
parent5a8adc342bcf01f535079d06778a9f244ba7e96f (diff)
fix: hide progress bars when showing permission prompt (#17130)
Also adds download bytes progress when downloading remote specifiers. Closes #16860
Diffstat (limited to 'cli')
-rw-r--r--cli/file_fetcher.rs49
-rw-r--r--cli/http_util.rs60
-rw-r--r--cli/main.rs4
-rw-r--r--cli/util/draw_thread.rs82
-rw-r--r--cli/util/progress_bar/mod.rs3
5 files changed, 116 insertions, 82 deletions
diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs
index f714a18ca..8738e4f48 100644
--- a/cli/file_fetcher.rs
+++ b/cli/file_fetcher.rs
@@ -1,15 +1,17 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::args::CacheSetting;
+use crate::auth_tokens::AuthToken;
use crate::auth_tokens::AuthTokens;
use crate::cache::HttpCache;
use crate::colors;
+use crate::http_util;
use crate::http_util::resolve_redirect_from_response;
use crate::http_util::CacheSemantics;
-use crate::http_util::FetchOnceArgs;
-use crate::http_util::FetchOnceResult;
+use crate::http_util::HeadersMap;
use crate::http_util::HttpClient;
use crate::util::progress_bar::ProgressBar;
+use crate::util::progress_bar::UpdateGuard;
use crate::util::text_encoding;
use data_url::DataUrl;
@@ -21,6 +23,7 @@ use deno_core::error::AnyError;
use deno_core::futures;
use deno_core::futures::future::FutureExt;
use deno_core::parking_lot::Mutex;
+use deno_core::url::Url;
use deno_core::ModuleSpecifier;
use deno_runtime::deno_fetch::reqwest::header::HeaderValue;
use deno_runtime::deno_fetch::reqwest::header::ACCEPT;
@@ -470,6 +473,7 @@ impl FileFetcher {
maybe_accept: maybe_accept.clone(),
maybe_etag,
maybe_auth_token,
+ maybe_progress_guard: maybe_progress_guard.as_ref(),
},
)
.await?
@@ -637,14 +641,30 @@ impl FileFetcher {
}
}
+#[derive(Debug, Eq, PartialEq)]
+enum FetchOnceResult {
+ Code(Vec<u8>, HeadersMap),
+ NotModified,
+ Redirect(Url, HeadersMap),
+}
+
+#[derive(Debug)]
+struct FetchOnceArgs<'a> {
+ pub url: Url,
+ pub maybe_accept: Option<String>,
+ pub maybe_etag: Option<String>,
+ pub maybe_auth_token: Option<AuthToken>,
+ pub maybe_progress_guard: Option<&'a UpdateGuard>,
+}
+
/// Asynchronously fetches the given HTTP URL one pass only.
/// If no redirect is present and no error occurs,
/// yields Code(ResultPayload).
/// If redirect occurs, does not follow and
/// yields Redirect(url).
-async fn fetch_once(
+async fn fetch_once<'a>(
http_client: &HttpClient,
- args: FetchOnceArgs,
+ args: FetchOnceArgs<'a>,
) -> Result<FetchOnceResult, AnyError> {
let mut request = http_client.get_no_redirect(args.url.clone());
@@ -710,7 +730,11 @@ async fn fetch_once(
return Err(err);
}
- let body = response.bytes().await?.to_vec();
+ let body = http_util::get_response_body_with_progress(
+ response,
+ args.maybe_progress_guard,
+ )
+ .await?;
Ok(FetchOnceResult::Code(body, result_headers))
}
@@ -1760,6 +1784,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -1787,6 +1812,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -1815,6 +1841,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -1837,6 +1864,7 @@ mod tests {
maybe_accept: None,
maybe_etag: Some("33a64df551425fcc55e".to_string()),
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -1857,6 +1885,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -1887,6 +1916,7 @@ mod tests {
maybe_accept: Some("application/json".to_string()),
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -1913,6 +1943,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -1953,6 +1984,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -1990,6 +2022,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -2025,6 +2058,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -2066,6 +2100,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -2110,6 +2145,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -2133,6 +2169,7 @@ mod tests {
maybe_accept: None,
maybe_etag: Some("33a64df551425fcc55e".to_string()),
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -2170,6 +2207,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
@@ -2200,6 +2238,7 @@ mod tests {
maybe_accept: None,
maybe_etag: None,
maybe_auth_token: None,
+ maybe_progress_guard: None,
},
)
.await;
diff --git a/cli/http_util.rs b/cli/http_util.rs
index 966ba693e..e7fbcd1f3 100644
--- a/cli/http_util.rs
+++ b/cli/http_util.rs
@@ -1,5 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
-use crate::auth_tokens::AuthToken;
use crate::util::progress_bar::UpdateGuard;
use crate::version::get_user_agent;
@@ -218,21 +217,6 @@ impl CacheSemantics {
}
}
-#[derive(Debug, Eq, PartialEq)]
-pub enum FetchOnceResult {
- Code(Vec<u8>, HeadersMap),
- NotModified,
- Redirect(Url, HeadersMap),
-}
-
-#[derive(Debug)]
-pub struct FetchOnceArgs {
- pub url: Url,
- pub maybe_accept: Option<String>,
- pub maybe_etag: Option<String>,
- pub maybe_auth_token: Option<AuthToken>,
-}
-
#[derive(Debug, Clone)]
pub struct HttpClient(reqwest::Client);
@@ -312,24 +296,9 @@ impl HttpClient {
);
}
- if let Some(progress_guard) = progress_guard {
- if let Some(total_size) = response.content_length() {
- progress_guard.set_total_size(total_size);
- let mut current_size = 0;
- let mut data = Vec::with_capacity(total_size as usize);
- let mut stream = response.bytes_stream();
- while let Some(item) = stream.next().await {
- let bytes = item?;
- current_size += bytes.len() as u64;
- progress_guard.set_position(current_size);
- data.extend(bytes.into_iter());
- }
- return Ok(Some(data));
- }
- }
-
- let bytes = response.bytes().await?;
- Ok(Some(bytes.into()))
+ get_response_body_with_progress(response, progress_guard)
+ .await
+ .map(Some)
}
async fn get_redirected_response<U: reqwest::IntoUrl>(
@@ -358,6 +327,29 @@ impl HttpClient {
}
}
+pub async fn get_response_body_with_progress(
+ response: reqwest::Response,
+ progress_guard: Option<&UpdateGuard>,
+) -> Result<Vec<u8>, AnyError> {
+ if let Some(progress_guard) = progress_guard {
+ if let Some(total_size) = response.content_length() {
+ progress_guard.set_total_size(total_size);
+ let mut current_size = 0;
+ let mut data = Vec::with_capacity(total_size as usize);
+ let mut stream = response.bytes_stream();
+ while let Some(item) = stream.next().await {
+ let bytes = item?;
+ current_size += bytes.len() as u64;
+ progress_guard.set_position(current_size);
+ data.extend(bytes.into_iter());
+ }
+ return Ok(data);
+ }
+ }
+ let bytes = response.bytes().await?;
+ Ok(bytes.into())
+}
+
#[cfg(test)]
mod test {
use super::*;
diff --git a/cli/main.rs b/cli/main.rs
index ecff408d7..462e9e0a4 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -260,6 +260,10 @@ pub fn main() {
util::windows::ensure_stdio_open();
#[cfg(windows)]
colors::enable_ansi(); // For Windows 10
+ deno_runtime::permissions::set_prompt_callbacks(
+ Box::new(util::draw_thread::DrawThread::hide),
+ Box::new(util::draw_thread::DrawThread::show),
+ );
let args: Vec<String> = env::args().collect();
diff --git a/cli/util/draw_thread.rs b/cli/util/draw_thread.rs
index b069a14b7..49c45312c 100644
--- a/cli/util/draw_thread.rs
+++ b/cli/util/draw_thread.rs
@@ -30,7 +30,6 @@ impl Drop for DrawThreadGuard {
#[derive(Debug, Clone)]
struct InternalEntry {
- priority: u8,
id: u16,
renderer: Arc<dyn DrawThreadRenderer>,
}
@@ -69,6 +68,13 @@ static INTERNAL_STATE: Lazy<Arc<Mutex<InternalState>>> = Lazy::new(|| {
}))
});
+static IS_TTY_WITH_CONSOLE_SIZE: Lazy<bool> = Lazy::new(|| {
+ atty::is(atty::Stream::Stderr)
+ && console_size()
+ .map(|s| s.cols > 0 && s.rows > 0)
+ .unwrap_or(false)
+});
+
/// The draw thread is responsible for rendering multiple active
/// `DrawThreadRenderer`s to stderr. It is global because the
/// concept of stderr in the process is also a global concept.
@@ -78,31 +84,17 @@ pub struct DrawThread;
impl DrawThread {
/// Is using a draw thread supported.
pub fn is_supported() -> bool {
- atty::is(atty::Stream::Stderr)
- && log::log_enabled!(log::Level::Info)
- && console_size()
- .map(|s| s.cols > 0 && s.rows > 0)
- .unwrap_or(false)
+ // don't put the log level in the lazy because the
+ // log level may change as the application runs
+ log::log_enabled!(log::Level::Info) && *IS_TTY_WITH_CONSOLE_SIZE
}
- /// Adds a renderer to the draw thread with a given priority.
- /// Renderers are sorted by priority with higher priority
- /// entries appearing at the bottom of the screen.
- pub fn add_entry(
- priority: u8,
- renderer: Arc<dyn DrawThreadRenderer>,
- ) -> DrawThreadGuard {
+ /// Adds a renderer to the draw thread.
+ pub fn add_entry(renderer: Arc<dyn DrawThreadRenderer>) -> DrawThreadGuard {
let internal_state = &*INTERNAL_STATE;
let mut internal_state = internal_state.lock();
let id = internal_state.next_entry_id;
- internal_state.entries.push(InternalEntry {
- id,
- priority,
- renderer,
- });
- internal_state
- .entries
- .sort_by(|a, b| a.priority.cmp(&b.priority));
+ internal_state.entries.push(InternalEntry { id, renderer });
if internal_state.next_entry_id == u16::MAX {
internal_state.next_entry_id = 0;
@@ -116,16 +108,15 @@ impl DrawThread {
}
/// Hides the draw thread.
- #[allow(dead_code)]
pub fn hide() {
let internal_state = &*INTERNAL_STATE;
let mut internal_state = internal_state.lock();
internal_state.hide = true;
+
Self::clear_and_stop_draw_thread(&mut internal_state);
}
/// Shows the draw thread if it was previously hidden.
- #[allow(dead_code)]
pub fn show() {
let internal_state = &*INTERNAL_STATE;
let mut internal_state = internal_state.lock();
@@ -159,7 +150,11 @@ impl DrawThread {
}
fn maybe_start_draw_thread(internal_state: &mut InternalState) {
- if internal_state.has_draw_thread || internal_state.hide {
+ if internal_state.has_draw_thread
+ || internal_state.hide
+ || internal_state.entries.is_empty()
+ || !DrawThread::is_supported()
+ {
return;
}
@@ -168,7 +163,7 @@ impl DrawThread {
let drawer_id = internal_state.drawer_id;
tokio::task::spawn_blocking(move || {
- let mut previous_size = console_size().unwrap();
+ let mut previous_size = console_size();
loop {
let mut delay_ms = 120;
{
@@ -182,6 +177,10 @@ impl DrawThread {
internal_state.entries.clone()
};
+ // this should always be set, but have the code handle
+ // it not being for some reason
+ let size = console_size();
+
// Call into the renderers outside the lock to prevent a potential
// deadlock between our internal state lock and the renderers
// internal state lock.
@@ -194,13 +193,12 @@ impl DrawThread {
// which attempts to acquire the other thread's Render's internal
// lock causing a deadlock
let mut text = String::new();
- let size = console_size().unwrap();
if size != previous_size {
// means the user is actively resizing the console...
// wait a little bit until they stop resizing
previous_size = size;
delay_ms = 200;
- } else {
+ } else if let Some(size) = size {
let mut should_new_line_next = false;
for entry in entries {
let new_text = entry.renderer.render(&size);
@@ -210,23 +208,23 @@ impl DrawThread {
should_new_line_next = !new_text.is_empty();
text.push_str(&new_text);
}
- }
- // now reacquire the lock, ensure we should still be drawing, then
- // output the text
- {
- let internal_state = &*INTERNAL_STATE;
- let mut internal_state = internal_state.lock();
- if internal_state.should_exit_draw_thread(drawer_id) {
- break;
+ // now reacquire the lock, ensure we should still be drawing, then
+ // output the text
+ {
+ let internal_state = &*INTERNAL_STATE;
+ let mut internal_state = internal_state.lock();
+ if internal_state.should_exit_draw_thread(drawer_id) {
+ break;
+ }
+ internal_state.static_text.eprint_with_size(
+ &text,
+ console_static_text::ConsoleSize {
+ cols: Some(size.cols as u16),
+ rows: Some(size.rows as u16),
+ },
+ );
}
- internal_state.static_text.eprint_with_size(
- &text,
- console_static_text::ConsoleSize {
- cols: Some(size.cols as u16),
- rows: Some(size.rows as u16),
- },
- );
}
}
diff --git a/cli/util/progress_bar/mod.rs b/cli/util/progress_bar/mod.rs
index 8651e2d20..a20ac43c9 100644
--- a/cli/util/progress_bar/mod.rs
+++ b/cli/util/progress_bar/mod.rs
@@ -23,6 +23,7 @@ mod renderer;
// Inspired by Indicatif, but this custom implementation allows
// for more control over what's going on under the hood.
+#[derive(Debug)]
pub struct UpdateGuard {
maybe_entry: Option<ProgressBarEntry>,
}
@@ -183,7 +184,7 @@ impl ProgressBarInner {
{
internal_state.start_time = SystemTime::now();
internal_state.draw_thread_guard =
- Some(DrawThread::add_entry(0, Arc::new(self.clone())));
+ Some(DrawThread::add_entry(Arc::new(self.clone())));
}
}
}