commit 8768fdb04d79525734be0c79b7fa5d97d349a369 Author: Jakub Panek Date: Sun Mar 20 02:01:25 2022 +0000 remove update checker Signed-off-by: Jakub Panek diff --git a/wezterm-gui/src/main.rs b/wezterm-gui/src/main.rs index 6fd2dce53..c7a0f80c5 100644 --- a/wezterm-gui/src/main.rs +++ b/wezterm-gui/src/main.rs @@ -41,7 +41,6 @@ mod shapecache; mod stats; mod tabbar; mod termwindow; -mod update; mod utilsprites; pub use selection::SelectionMode; @@ -206,7 +205,6 @@ async fn async_run_with_domain_as_default( cmd: Option, ) -> anyhow::Result<()> { let mux = Mux::get().unwrap(); - crate::update::load_last_release_info_and_set_banner(); // Allow spawning local commands into new tabs/panes let local_domain: Arc = Arc::new(LocalDomain::new("local")?); @@ -539,7 +537,6 @@ fn setup_mux( .unwrap_or(mux::DEFAULT_WORKSPACE), ), ); - crate::update::load_last_release_info_and_set_banner(); update_mux_domains(config)?; let default_name = diff --git a/wezterm-gui/src/termwindow/mod.rs b/wezterm-gui/src/termwindow/mod.rs index fac803f07..0912772bd 100644 --- a/wezterm-gui/src/termwindow/mod.rs +++ b/wezterm-gui/src/termwindow/mod.rs @@ -811,7 +811,6 @@ impl TermWindow { myself.emit_status_event(); } - crate::update::start_update_checker(); front_end().record_known_window(window, mux_window_id); Ok(()) } diff --git a/wezterm-gui/src/update.rs b/wezterm-gui/src/update.rs deleted file mode 100644 index 1eac519f9..000000000 --- a/wezterm-gui/src/update.rs +++ /dev/null @@ -1,518 +0,0 @@ -use crate::ICON_DATA; -use anyhow::anyhow; -use config::{configuration, wezterm_version}; -use http_req::request::{HttpVersion, Request}; -use http_req::uri::Uri; -use mux::connui::ConnectionUI; -use portable_pty::PtySize; -use regex::Regex; -use serde::*; -use std::collections::HashMap; -use std::convert::TryFrom; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Mutex}; -use std::time::Duration; -use termwiz::cell::{AttributeChange, Hyperlink, Underline}; -use termwiz::color::AnsiColor; -use termwiz::escape::csi::{Cursor, Sgr}; -use termwiz::escape::osc::{ITermDimension, ITermFileData, ITermProprietary}; -use termwiz::escape::{OneBased, OperatingSystemCommand, CSI}; -use termwiz::surface::{Change, CursorVisibility}; -use wezterm_toast_notification::*; - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct Release { - pub url: String, - pub body: String, - pub html_url: String, - pub tag_name: String, - pub assets: Vec, -} - -impl Release { - pub fn classify_assets(&self) -> HashMap { - let mut map = HashMap::new(); - for asset in &self.assets { - let kind = classify_asset_name(&asset.name); - map.insert(kind, asset.clone()); - } - map - } -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct Asset { - pub name: String, - pub size: usize, - pub url: String, - pub browser_download_url: String, -} - -pub type DistVers = String; - -#[derive(Debug, PartialEq, Eq, Hash)] -pub enum AssetKind { - SourceCode, - AppImage, - AppImageZSync, - DebianDeb(DistVers), - UbuntuDeb(DistVers), - CentOSRpm(DistVers), - FedoraRpm(DistVers), - MacOSZip, - WindowsZip, - WindowsSetupExe, - Unknown, -} - -fn classify_asset_name(name: &str) -> AssetKind { - let winzip = Regex::new(r"WezTerm-windows-.*\.zip$").unwrap(); - let winsetup = Regex::new(r"WezTerm-.*-setup.exe$").unwrap(); - let maczip = Regex::new(r"WezTerm-macos-.*\.zip$").unwrap(); - let appimage = Regex::new(r"WezTerm-.*\.AppImage$").unwrap(); - let appimage_zsync = Regex::new(r"WezTerm-.*\.AppImage\.zsync$").unwrap(); - let source = Regex::new(r"wezterm-.*src\.tar\.gz$").unwrap(); - - let rpm = Regex::new(r"wezterm-.*-1\.([a-z]+)(\d+)\.x86_64\.rpm$").unwrap(); - for cap in rpm.captures_iter(name) { - match &cap[1] { - "fc" => return AssetKind::FedoraRpm(cap[2].to_string()), - "el" => return AssetKind::CentOSRpm(cap[2].to_string()), - _ => {} - } - } - - let nightly_rpm = Regex::new(r"wezterm-nightly-(fedora|centos)(\d+)\.rpm$").unwrap(); - for cap in nightly_rpm.captures_iter(name) { - match &cap[1] { - "fedora" => return AssetKind::FedoraRpm(cap[2].to_string()), - "centos" => return AssetKind::CentOSRpm(cap[2].to_string()), - _ => {} - } - } - - let dot_deb = Regex::new(r"wezterm-.*\.(Ubuntu|Debian)([0-9.]+)\.deb$").unwrap(); - for cap in dot_deb.captures_iter(name) { - match &cap[1] { - "Ubuntu" => return AssetKind::UbuntuDeb(cap[2].to_string()), - "Debian" => return AssetKind::DebianDeb(cap[2].to_string()), - _ => {} - } - } - - if winzip.is_match(name) { - AssetKind::WindowsZip - } else if winsetup.is_match(name) { - AssetKind::WindowsSetupExe - } else if maczip.is_match(name) { - AssetKind::MacOSZip - } else if appimage.is_match(name) { - AssetKind::AppImage - } else if appimage_zsync.is_match(name) { - AssetKind::AppImageZSync - } else if source.is_match(name) { - AssetKind::SourceCode - } else { - AssetKind::Unknown - } -} - -fn get_github_release_info(uri: &str) -> anyhow::Result { - let uri = Uri::try_from(uri)?; - - let mut latest = Vec::new(); - let _res = Request::new(&uri) - .version(HttpVersion::Http10) - .header("User-Agent", &format!("wez/wezterm-{}", wezterm_version())) - .send(&mut latest) - .map_err(|e| anyhow!("failed to query github releases: {}", e))?; - - /* - println!("Status: {} {}", _res.status_code(), _res.reason()); - println!("{}", String::from_utf8_lossy(&latest)); - */ - - let latest: Release = serde_json::from_slice(&latest)?; - Ok(latest) -} - -pub fn get_latest_release_info() -> anyhow::Result { - get_github_release_info("https://api.github.com/repos/wez/wezterm/releases/latest") -} - -#[allow(unused)] -pub fn get_nightly_release_info() -> anyhow::Result { - get_github_release_info("https://api.github.com/repos/wez/wezterm/releases/tags/nightly") -} - -lazy_static::lazy_static! { - static ref UPDATER_WINDOW: Mutex> = Mutex::new(None); -} - -fn show_update_available(release: Release) { - if !configuration().show_update_window { - return; - } - let mut updater = UPDATER_WINDOW.lock().unwrap(); - - let enable_close_delay = false; - let size = PtySize { - cols: 80, - rows: 35, - pixel_width: 0, - pixel_height: 0, - }; - let ui = ConnectionUI::with_dimensions(size, enable_close_delay); - ui.title("WezTerm Update Available"); - - let install = if cfg!(windows) { - "https://wezfurlong.org/wezterm/install/windows.html" - } else if cfg!(target_os = "macos") { - "https://wezfurlong.org/wezterm/install/macos.html" - } else if cfg!(target_os = "linux") { - "https://wezfurlong.org/wezterm/install/linux.html" - } else { - "https://wezfurlong.org/wezterm/installation.html" - }; - - let change_log = format!( - "https://wezfurlong.org/wezterm/changelog.html#{}", - release.tag_name - ); - - let brief_blurb = release - .body - // The default for the release body is a series of newlines. - // Trim that so that it doesn't make the window look weird - .trim_end() - // Normalize any dos line endings that might have wound - // up in the body field... - .replace("\r\n", "\n"); - - let mut render = crate::markdown::RenderState::new( - 78, - termwiz::terminal::ScreenSize { - cols: 80, - rows: 35, - xpixel: 0, - ypixel: 0, - }, - ); - render.parse_str(&brief_blurb); - - let mut output = vec![ - Change::CursorVisibility(CursorVisibility::Hidden), - Change::Attribute(AttributeChange::Underline(Underline::Single)), - Change::Attribute(AttributeChange::Hyperlink(Some(Arc::new(Hyperlink::new( - install, - ))))), - format!("\r\nVersion {} is now available!\r\n", release.tag_name).into(), - Change::Attribute(AttributeChange::Hyperlink(None)), - Change::Attribute(AttributeChange::Underline(Underline::None)), - format!("(this is version {})\r\n", wezterm_version()).into(), - ]; - output.append(&mut render.into_changes()); - output.extend_from_slice(&[ - "\r\n".into(), - Change::Attribute(AttributeChange::Hyperlink(Some(Arc::new(Hyperlink::new( - change_log, - ))))), - Change::Attribute(AttributeChange::Underline(Underline::Single)), - "View Change Log\r\n".into(), - Change::Attribute(AttributeChange::Hyperlink(None)), - ]); - ui.output(output); - - let assets = release.classify_assets(); - let appimage = assets.get(&AssetKind::AppImage); - let setupexe = assets.get(&AssetKind::WindowsSetupExe); - - fn emit_direct_download_link(asset: &Option<&Asset>, ui: &ConnectionUI) { - ui.output(vec![ - Change::Attribute(AttributeChange::Hyperlink(Some(Arc::new(Hyperlink::new( - &asset.unwrap().browser_download_url, - ))))), - Change::Attribute(AttributeChange::Underline(Underline::Single)), - format!("Download {}\r\n", asset.unwrap().name).into(), - Change::Attribute(AttributeChange::Hyperlink(None)), - ]); - } - - if cfg!(target_os = "linux") && std::env::var_os("APPIMAGE").is_some() && appimage.is_some() { - emit_direct_download_link(&appimage, &ui); - } else if cfg!(windows) && setupexe.is_some() { - emit_direct_download_link(&setupexe, &ui); - } else { - ui.output(vec![ - Change::Attribute(AttributeChange::Hyperlink(Some(Arc::new(Hyperlink::new( - install, - ))))), - Change::Attribute(AttributeChange::Underline(Underline::Single)), - "Open Download Page\r\n".into(), - Change::Attribute(AttributeChange::Hyperlink(None)), - ]); - } - - updater.replace(ui); -} - -pub fn load_last_release_info_and_set_banner() { - if !configuration().check_for_updates { - return; - } - - let update_file_name = config::RUNTIME_DIR.join("check_update"); - if let Ok(data) = std::fs::read(update_file_name) { - let latest: Release = match serde_json::from_slice(&data) { - Ok(d) => d, - Err(_) => return, - }; - - let current = wezterm_version(); - let force_ui = std::env::var_os("WEZTERM_ALWAYS_SHOW_UPDATE_UI").is_some(); - if latest.tag_name.as_str() <= current && !force_ui { - return; - } - - set_banner_from_release_info(&latest); - } -} - -fn set_banner_from_release_info(latest: &Release) { - let mux = crate::Mux::get().unwrap(); - let url = format!( - "https://wezfurlong.org/wezterm/changelog.html#{}", - latest.tag_name - ); - - let icon = ITermFileData { - name: None, - size: Some(ICON_DATA.len()), - width: ITermDimension::Automatic, - height: ITermDimension::Cells(2), - preserve_aspect_ratio: true, - inline: true, - do_not_move_cursor: false, - data: ICON_DATA.to_vec(), - }; - let icon = OperatingSystemCommand::ITermProprietary(ITermProprietary::File(Box::new(icon))); - let top_line_pos = CSI::Cursor(Cursor::CharacterAndLinePosition { - line: OneBased::new(1), - col: OneBased::new(6), - }); - let second_line_pos = CSI::Cursor(Cursor::CharacterAndLinePosition { - line: OneBased::new(2), - col: OneBased::new(6), - }); - let link_on = OperatingSystemCommand::SetHyperlink(Some(Hyperlink::new(url))); - let underline_color = CSI::Sgr(Sgr::UnderlineColor(AnsiColor::Blue.into())); - let underline_on = CSI::Sgr(Sgr::Underline(Underline::Single)); - let reset = CSI::Sgr(Sgr::Reset); - let link_off = OperatingSystemCommand::SetHyperlink(None); - mux.set_banner(Some(format!( - "{}{}WezTerm Update Available\r\n{}{}{}{}Click to see what's new{}{}\r\n", - icon, - top_line_pos, - second_line_pos, - link_on, - underline_color, - underline_on, - link_off, - reset, - ))); -} - -fn schedule_set_banner_from_release_info(latest: &Release) { - let current = wezterm_version(); - if latest.tag_name.as_str() <= current { - return; - } - promise::spawn::spawn_into_main_thread({ - let latest = latest.clone(); - async move { - set_banner_from_release_info(&latest); - } - }) - .detach(); -} - -/// Returns true if the provided socket path is dead. -fn update_checker() { - // Compute how long we should sleep for; - // if we've never checked, give it a few seconds after the first - // launch, otherwise compute the interval based on the time of - // the last check. - let update_interval = Duration::from_secs(configuration().check_for_updates_interval_seconds); - let initial_interval = Duration::from_secs(10); - - let force_ui = std::env::var_os("WEZTERM_ALWAYS_SHOW_UPDATE_UI").is_some(); - - let update_file_name = config::RUNTIME_DIR.join("check_update"); - let delay = update_file_name - .metadata() - .and_then(|metadata| metadata.modified()) - .map_err(|_| ()) - .and_then(|systime| { - let elapsed = systime.elapsed().unwrap_or(Duration::new(0, 0)); - update_interval.checked_sub(elapsed).ok_or(()) - }) - .unwrap_or(initial_interval); - - std::thread::sleep(if force_ui { initial_interval } else { delay }); - - let my_sock = config::RUNTIME_DIR.join(format!("gui-sock-{}", unsafe { libc::getpid() })); - - loop { - // Figure out which other wezterm-guis are running. - // We have a little "consensus protocol" to decide which - // of us will show the toast notification or show the update - // window: the one of us that sorts first in the list will - // own doing that, so that if there are a dozen gui processes - // running, we don't spam the user with a lot of notifications. - let socks = wezterm_client::discovery::discover_gui_socks(); - - if configuration().check_for_updates { - if let Ok(latest) = get_latest_release_info() { - schedule_set_banner_from_release_info(&latest); - let current = wezterm_version(); - if latest.tag_name.as_str() > current || force_ui { - log::info!( - "latest release {} is newer than current build {}", - latest.tag_name, - current - ); - - let url = format!( - "https://wezfurlong.org/wezterm/changelog.html#{}", - latest.tag_name - ); - - if force_ui || socks.is_empty() || socks[0] == my_sock { - persistent_toast_notification_with_click_to_open_url( - "WezTerm Update Available", - "Click to see what's new", - &url, - ); - show_update_available(latest.clone()); - } - } - - config::create_user_owned_dirs(update_file_name.parent().unwrap()).ok(); - - // Record the time of this check - if let Ok(f) = std::fs::OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .open(&update_file_name) - { - serde_json::to_writer_pretty(f, &latest).ok(); - } - } - } - - std::thread::sleep(Duration::from_secs( - configuration().check_for_updates_interval_seconds, - )); - } -} - -pub fn start_update_checker() { - static CHECKER_STARTED: AtomicBool = AtomicBool::new(false); - if let Ok(false) = - CHECKER_STARTED.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) - { - std::thread::Builder::new() - .name("update_checker".into()) - .spawn(update_checker) - .expect("failed to spawn update checker thread"); - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn classify_names() { - assert_eq!( - classify_asset_name("WezTerm-windows-20200505-090057-31c6155f.zip"), - AssetKind::WindowsZip - ); - assert_eq!( - classify_asset_name("WezTerm-windows-nightly.zip"), - AssetKind::WindowsZip - ); - assert_eq!( - classify_asset_name("WezTerm-nightly-setup.exe"), - AssetKind::WindowsSetupExe - ); - assert_eq!( - classify_asset_name("WezTerm-20200505-090057-31c6155f-setup.exe"), - AssetKind::WindowsSetupExe - ); - - assert_eq!( - classify_asset_name("WezTerm-macos-20200505-090057-31c6155f.zip"), - AssetKind::MacOSZip - ); - assert_eq!( - classify_asset_name("WezTerm-macos-nightly.zip"), - AssetKind::MacOSZip - ); - - assert_eq!( - classify_asset_name("wezterm-20200505_090057_31c6155f-1.fc32.x86_64.rpm"), - AssetKind::FedoraRpm("32".into()) - ); - assert_eq!( - classify_asset_name("wezterm-nightly-fedora32.rpm"), - AssetKind::FedoraRpm("32".into()) - ); - - assert_eq!( - classify_asset_name("wezterm-20200505_090057_31c6155f-1.fc31.x86_64.rpm"), - AssetKind::FedoraRpm("31".into()) - ); - assert_eq!( - classify_asset_name("wezterm-20200505_090057_31c6155f-1.el8.x86_64.rpm"), - AssetKind::CentOSRpm("8".into()) - ); - assert_eq!( - classify_asset_name("wezterm-20200505_090057_31c6155f-1.el7.x86_64.rpm"), - AssetKind::CentOSRpm("7".into()) - ); - assert_eq!( - classify_asset_name("wezterm-20200505-090057-31c6155f.Ubuntu20.04.tar.xz"), - AssetKind::Unknown - ); - assert_eq!( - classify_asset_name("wezterm-20200505-090057-31c6155f.Ubuntu20.04.deb"), - AssetKind::UbuntuDeb("20.04".into()) - ); - assert_eq!( - classify_asset_name("wezterm-20200505-090057-31c6155f.Ubuntu19.10.deb"), - AssetKind::UbuntuDeb("19.10".into()) - ); - assert_eq!( - classify_asset_name("wezterm-20200505-090057-31c6155f.Debian9.12.deb"), - AssetKind::DebianDeb("9.12".into()) - ); - assert_eq!( - classify_asset_name("wezterm-20200505-090057-31c6155f.Debian10.deb"), - AssetKind::DebianDeb("10".into()) - ); - assert_eq!( - classify_asset_name("WezTerm-20200505-090057-31c6155f-Ubuntu16.04.AppImage.zsync"), - AssetKind::AppImageZSync - ); - assert_eq!( - classify_asset_name("WezTerm-20200505-090057-31c6155f-Ubuntu16.04.AppImage"), - AssetKind::AppImage - ); - assert_eq!( - classify_asset_name("wezterm-20200505-090057-31c6155f-src.tar.gz"), - AssetKind::SourceCode - ); - } -}