From fd9d38481b9ea540d689ae5cf18d99f74c1e460f Mon Sep 17 00:00:00 2001 From: hanna Date: Fri, 19 Jul 2024 10:04:48 -0700 Subject: [PATCH 1/3] refactor: attempted autoupdate configuration --- include/ghostty.h | 1 + macos/Sources/App/macOS/AppDelegate.swift | 8 +++++++- macos/Sources/Ghostty/Ghostty.Config.swift | 11 +++++++++++ src/config/Config.zig | 14 ++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/ghostty.h b/include/ghostty.h index b413dec41..12eb26840 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -12,6 +12,7 @@ extern "C" { #endif +#include #include #include #include diff --git a/macos/Sources/App/macOS/AppDelegate.swift b/macos/Sources/App/macOS/AppDelegate.swift index 603523e80..d1f12ad0f 100644 --- a/macos/Sources/App/macOS/AppDelegate.swift +++ b/macos/Sources/App/macOS/AppDelegate.swift @@ -108,7 +108,13 @@ class AppDelegate: NSObject, // Initial config loading configDidReload(ghostty) - + + updaterController.updater.updateCheckInterval = 60 + updaterController.updater.automaticallyChecksForUpdates = + ghostty.config.autoUpdates == "check" || ghostty.config.autoUpdates == "download" + updaterController.updater.automaticallyDownloadsUpdates = + ghostty.config.autoUpdates == "download" + // Register our service provider. This must happen after everything is initialized. NSApp.servicesProvider = ServiceProvider() diff --git a/macos/Sources/Ghostty/Ghostty.Config.swift b/macos/Sources/Ghostty/Ghostty.Config.swift index e917bf2c0..4ddb986f9 100644 --- a/macos/Sources/Ghostty/Ghostty.Config.swift +++ b/macos/Sources/Ghostty/Ghostty.Config.swift @@ -360,6 +360,17 @@ extension Ghostty { _ = ghostty_config_get(config, &v, key, UInt(key.count)) return v; } + + var autoUpdates: String { + let defaultValue = "off" + guard let config = self.config else { return defaultValue } + let key = "auto-updates" + + var value: UnsafePointer? = nil + guard ghostty_config_get(config, &value, key, UInt(key.count)) else { return defaultValue } + guard let pointer = value else { return defaultValue } + return String(cString: pointer) + } } } diff --git a/src/config/Config.zig b/src/config/Config.zig index d853f0481..b9217d0e3 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -1462,6 +1462,13 @@ term: []const u8 = "xterm-ghostty", /// running. Defaults to an empty string if not set. @"enquiry-response": []const u8 = "", +/// This controls the automatic update functionality on macOS by setting the +/// properties on the Squirrel automatic update component. By default this is +/// set to "off" which doesn't do anything. The "check" option will automatically +/// check for updates but will NOT download them, while as the "download" option +/// will both check AND download updates automatically for the user. +@"auto-updates": AutoUpdates = .off, + /// This is set by the CLI parser for deinit. _arena: ?ArenaAllocator = null, @@ -4096,6 +4103,13 @@ pub const LinuxCgroup = enum { @"single-instance", }; +/// See auto-updates +pub const AutoUpdates = enum { + check, + download, + off, +}; + pub const Duration = struct { /// Duration in nanoseconds duration: u64 = 0, From 359272a5f5be35f00910d34536c5f35ebc65ae92 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 10 Sep 2024 21:54:27 -0700 Subject: [PATCH 2/3] macos: start Sparkle after loading config --- include/ghostty.h | 1 - macos/Sources/App/macOS/AppDelegate.swift | 19 +++++++------ macos/Sources/Ghostty/Ghostty.Config.swift | 22 +++++++++------ src/config/Config.zig | 33 ++++++++++++++++------ 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/include/ghostty.h b/include/ghostty.h index 12eb26840..b413dec41 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -12,7 +12,6 @@ extern "C" { #endif -#include #include #include #include diff --git a/macos/Sources/App/macOS/AppDelegate.swift b/macos/Sources/App/macOS/AppDelegate.swift index d1f12ad0f..2f311a415 100644 --- a/macos/Sources/App/macOS/AppDelegate.swift +++ b/macos/Sources/App/macOS/AppDelegate.swift @@ -75,7 +75,7 @@ class AppDelegate: NSObject, override init() { terminalManager = TerminalManager(ghostty) updaterController = SPUStandardUpdaterController( - startingUpdater: true, + startingUpdater: false, updaterDelegate: updaterDelegate, userDriverDelegate: nil ) @@ -108,13 +108,10 @@ class AppDelegate: NSObject, // Initial config loading configDidReload(ghostty) - - updaterController.updater.updateCheckInterval = 60 - updaterController.updater.automaticallyChecksForUpdates = - ghostty.config.autoUpdates == "check" || ghostty.config.autoUpdates == "download" - updaterController.updater.automaticallyDownloadsUpdates = - ghostty.config.autoUpdates == "download" - + + // Start our update checker. + updaterController.startUpdater() + // Register our service provider. This must happen after everything is initialized. NSApp.servicesProvider = ServiceProvider() @@ -382,6 +379,12 @@ class AppDelegate: NSObject, default: UserDefaults.standard.removeObject(forKey: "NSQuitAlwaysKeepsWindows") } + // Sync our auto-update settings + updaterController.updater.automaticallyChecksForUpdates = + ghostty.config.autoUpdate == .check || ghostty.config.autoUpdate == .download + updaterController.updater.automaticallyDownloadsUpdates = + ghostty.config.autoUpdate == .download + // Config could change keybindings, so update everything that depends on that syncMenuShortcuts() terminalManager.relabelAllTabs() diff --git a/macos/Sources/Ghostty/Ghostty.Config.swift b/macos/Sources/Ghostty/Ghostty.Config.swift index 4ddb986f9..8ea9371fe 100644 --- a/macos/Sources/Ghostty/Ghostty.Config.swift +++ b/macos/Sources/Ghostty/Ghostty.Config.swift @@ -361,15 +361,15 @@ extension Ghostty { return v; } - var autoUpdates: String { - let defaultValue = "off" + var autoUpdate: AutoUpdate { + let defaultValue = AutoUpdate.check guard let config = self.config else { return defaultValue } - let key = "auto-updates" - - var value: UnsafePointer? = nil - guard ghostty_config_get(config, &value, key, UInt(key.count)) else { return defaultValue } - guard let pointer = value else { return defaultValue } - return String(cString: pointer) + var v: UnsafePointer? = nil + let key = "auto-update" + guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue } + guard let ptr = v else { return defaultValue } + let str = String(cString: ptr) + return AutoUpdate(rawValue: str) ?? defaultValue } } } @@ -377,6 +377,12 @@ extension Ghostty { // MARK: Configuration Enums extension Ghostty.Config { + enum AutoUpdate : String { + case off + case check + case download + } + enum ResizeOverlay : String { case always case never diff --git a/src/config/Config.zig b/src/config/Config.zig index b9217d0e3..c6c5e8c94 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -1462,12 +1462,29 @@ term: []const u8 = "xterm-ghostty", /// running. Defaults to an empty string if not set. @"enquiry-response": []const u8 = "", -/// This controls the automatic update functionality on macOS by setting the -/// properties on the Squirrel automatic update component. By default this is -/// set to "off" which doesn't do anything. The "check" option will automatically -/// check for updates but will NOT download them, while as the "download" option -/// will both check AND download updates automatically for the user. -@"auto-updates": AutoUpdates = .off, +/// Control the auto-update functionality of Ghostty. This is only supported +/// on macOS currently, since Linux builds are distributed via package +/// managers that are not centrally controlled by Ghostty. +/// +/// Checking or downloading an update does not send any information to +/// the project beyond standard network information mandated by the +/// underlying protocols. To put it another way: Ghostty doesn't explicitly +/// add any tracking to the update process. The update process works by +/// downloading information about the latest version and comparing it +/// client-side to the current version. +/// +/// Valid values are: +/// +/// * `off` - Disable auto-updates. +/// * `check` - Check for updates and notify the user if an update is +/// available, but do not automatically download or install the update. +/// * `download` - Check for updates, automatically download the update, +/// notify the user, but do not automatically install the update. +/// +/// The default value is `check`. +/// +/// Changing this value at runtime works after a small delay. +@"auto-update": AutoUpdate = .check, /// This is set by the CLI parser for deinit. _arena: ?ArenaAllocator = null, @@ -4104,10 +4121,10 @@ pub const LinuxCgroup = enum { }; /// See auto-updates -pub const AutoUpdates = enum { +pub const AutoUpdate = enum { + off, check, download, - off, }; pub const Duration = struct { From bcfe7d0f6c9b122d05bb8cf93fb45b61249b0d3f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 10 Sep 2024 21:55:53 -0700 Subject: [PATCH 3/3] macos: update comment on why we don't start updater --- macos/Sources/App/macOS/AppDelegate.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/macos/Sources/App/macOS/AppDelegate.swift b/macos/Sources/App/macOS/AppDelegate.swift index 2f311a415..01031c9a5 100644 --- a/macos/Sources/App/macOS/AppDelegate.swift +++ b/macos/Sources/App/macOS/AppDelegate.swift @@ -75,6 +75,9 @@ class AppDelegate: NSObject, override init() { terminalManager = TerminalManager(ghostty) updaterController = SPUStandardUpdaterController( + // Important: we must not start the updater here because we need to read our configuration + // first to determine whether we're automatically checking, downloading, etc. The updater + // is started later in applicationDidFinishLaunching startingUpdater: false, updaterDelegate: updaterDelegate, userDriverDelegate: nil