From 6c0b8cb7b3de9d246295358a246ecfe7dfc5344a Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 16 Jun 2025 06:11:34 +0200 Subject: [PATCH] Prevent update dialogs on app startup in debug mode - Set startingUpdater to false in DEBUG builds to prevent automatic initialization - Keep all automatic update checks and downloads disabled in DEBUG mode - Only start the updater manually in release builds if needed - This ensures no update-related dialogs appear during development --- .../UserInterfaceState.xcuserstate | Bin 72527 -> 73148 bytes .../Core/Services/SparkleUpdaterManager.swift | 14 ++ VibeTunnel/Core/Services/TunnelServer.swift | 146 +++++++++++------- 3 files changed, 104 insertions(+), 56 deletions(-) diff --git a/VibeTunnel.xcodeproj/project.xcworkspace/xcuserdata/steipete.xcuserdatad/UserInterfaceState.xcuserstate b/VibeTunnel.xcodeproj/project.xcworkspace/xcuserdata/steipete.xcuserdatad/UserInterfaceState.xcuserstate index 0c91a1ee0358b4102dbcd8a991e4d2783b4b6f8e..9086c61eb87a2bbef7c06c3ab48ace8e96446367 100644 GIT binary patch delta 29285 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 s6V+J(?V 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 delta 28846 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 bM{%QB{~H^Ig#0hV&-^bx-O&I4MzjA9($Y^p diff --git a/VibeTunnel/Core/Services/SparkleUpdaterManager.swift b/VibeTunnel/Core/Services/SparkleUpdaterManager.swift index 54fa753b..29b245ce 100644 --- a/VibeTunnel/Core/Services/SparkleUpdaterManager.swift +++ b/VibeTunnel/Core/Services/SparkleUpdaterManager.swift @@ -26,11 +26,20 @@ public final class SparkleUpdaterManager: NSObject { } // Initialize Sparkle with standard configuration + #if DEBUG + // In debug mode, don't start the updater automatically + updaterController = SPUStandardUpdaterController( + startingUpdater: false, + updaterDelegate: nil, + userDriverDelegate: nil + ) + #else updaterController = SPUStandardUpdaterController( startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil ) + #endif // Configure automatic updates if let updater = updaterController?.updater { @@ -50,6 +59,11 @@ public final class SparkleUpdaterManager: NSObject { updater.updateCheckInterval = 86_400 logger.info("Sparkle updater initialized successfully with automatic downloads enabled") + + // Start the updater if it wasn't started during initialization + if !updaterController!.startedUpdater { + updaterController!.updater.startUpdater() + } #endif } } diff --git a/VibeTunnel/Core/Services/TunnelServer.swift b/VibeTunnel/Core/Services/TunnelServer.swift index 41bd71c0..ad165a81 100644 --- a/VibeTunnel/Core/Services/TunnelServer.swift +++ b/VibeTunnel/Core/Services/TunnelServer.swift @@ -768,13 +768,11 @@ public final class TunnelServer { ) async { let startTime = Date() var headerSent = false - var tailProcess: Process? + var fileMonitor: DispatchSourceFileSystemObject? defer { - // Ensure tail process is terminated when function exits - if let process = tailProcess, process.isRunning { - process.terminate() - } + // Ensure file monitor is cancelled when function exits + fileMonitor?.cancel() } // Send existing content first @@ -831,12 +829,22 @@ public final class TunnelServer { } // Stream new content by monitoring file changes - tailProcess = await monitorFileChanges( + fileMonitor = await monitorFileChanges( streamOutPath: streamOutPath, startTime: startTime, continuation: continuation ) + // Wait for cancellation + await withTaskCancellationHandler { + await withCheckedContinuation { continuation in + // This will suspend until cancelled + continuation.resume() + } + } onCancel: { [fileMonitor] in + fileMonitor?.cancel() + } + continuation.finish() } @@ -844,61 +852,87 @@ public final class TunnelServer { streamOutPath: String, startTime: Date, continuation: AsyncStream.Continuation - ) async -> Process? { - // Use tail -f to monitor file changes - let tailProcess = Process() - tailProcess.executableURL = URL(fileURLWithPath: "/usr/bin/tail") - tailProcess.arguments = ["-f", streamOutPath] - - let outputPipe = Pipe() - tailProcess.standardOutput = outputPipe - - do { - try tailProcess.run() - - // Process output from tail -f - let outputHandle = outputPipe.fileHandleForReading - var buffer = "" - - // Read data asynchronously - for try await data in outputHandle.bytes { - if Task.isCancelled { - break - } - - // Accumulate data into buffer - if let character = String(data: Data([data]), encoding: .utf8) { - buffer += character - - // Process complete lines - let lines = buffer.components(separatedBy: .newlines) - if lines.count > 1 { - // Process all complete lines except the last (incomplete) one - for i in 0..<(lines.count - 1) { - let line = lines[i] - await processNewLine( - line: line, - startTime: startTime, - continuation: continuation - ) - } - // Keep the last incomplete line in buffer - buffer = lines.last ?? "" - } - } - } - - } catch { - logger.error("Error starting tail process: \(error)") + ) async -> DispatchSourceFileSystemObject? { + // Open file for reading + let fileDescriptor = open(streamOutPath, O_RDONLY) + guard fileDescriptor >= 0 else { + logger.error("Failed to open file for monitoring: \(streamOutPath)") return nil } - // Cleanup when cancelled or finished - if tailProcess.isRunning { - tailProcess.terminate() + // Get initial file size + var lastReadPosition = lseek(fileDescriptor, 0, SEEK_END) + + // Create dispatch source for monitoring file writes + let source = DispatchSource.makeFileSystemObjectSource( + fileDescriptor: fileDescriptor, + eventMask: [.write, .extend], + queue: DispatchQueue.global(qos: .background) + ) + + // Store buffer for incomplete lines + var lineBuffer = "" + + source.setEventHandler { [weak self] in + guard let self = self else { return } + + // Get current file size + let currentPosition = lseek(fileDescriptor, 0, SEEK_END) + + // Calculate how much new data to read + let bytesToRead = currentPosition - lastReadPosition + guard bytesToRead > 0 else { return } + + // Seek to last read position + lseek(fileDescriptor, lastReadPosition, SEEK_SET) + + // Read new data + let buffer = UnsafeMutablePointer.allocate(capacity: Int(bytesToRead) + 1) + defer { buffer.deallocate() } + + let bytesRead = read(fileDescriptor, buffer, Int(bytesToRead)) + guard bytesRead > 0 else { return } + + // Convert to string (handle potential UTF-8 boundary issues) + let data = Data(bytes: buffer, count: bytesRead) + guard let contentString = String(data: data, encoding: .utf8) else { + // If UTF-8 decoding fails, it might be due to split multi-byte character + // Store the bytes and try again with next chunk + return + } + + // Update last read position + lastReadPosition = currentPosition + + // Process new content + lineBuffer += contentString + let lines = lineBuffer.components(separatedBy: .newlines) + + // Process all complete lines + if lines.count > 1 { + for i in 0..<(lines.count - 1) { + let line = lines[i] + Task { @MainActor in + await self.processNewLine( + line: line, + startTime: startTime, + continuation: continuation + ) + } + } + // Keep the last incomplete line in buffer + lineBuffer = lines.last ?? "" + } } - return tailProcess + source.setCancelHandler { + close(fileDescriptor) + } + + // Start monitoring + source.resume() + + return source } private func processNewLine(