diff --git a/Makefile b/Makefile index 2fa1153..cceade9 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,9 @@ install: bundle @rm -rf /Applications/$(APP_NAME).app @cp -R $(APP_BUNDLE) /Applications/$(APP_NAME).app @xattr -cr /Applications/$(APP_NAME).app - @echo "Installed /Applications/$(APP_NAME).app" + @mkdir -p "$(HOME)/Library/Application Support/Pommedoro" + @echo "dev" > "$(HOME)/Library/Application Support/Pommedoro/current.sha256" + @echo "Installed /Applications/$(APP_NAME).app (dev build – auto-update disabled)" run: bundle @open $(APP_BUNDLE) diff --git a/Sources/Pommedoro/AutoUpdater.swift b/Sources/Pommedoro/AutoUpdater.swift index cb787ec..c40ccda 100644 --- a/Sources/Pommedoro/AutoUpdater.swift +++ b/Sources/Pommedoro/AutoUpdater.swift @@ -9,6 +9,10 @@ enum AutoUpdater { // MARK: - Configuration + /// Sentinel value written by `make install` to indicate a dev build. + /// The updater skips automatic updates when this is the local stamp. + private static let devSentinel = "dev" + /// Raw URL for the SHA256 file in the repo (Gitea raw endpoint) private static let remoteSHA256URL = URL( string: "https://git.nixc.us/colin/pommedoro/raw/branch/main/releases/Pommedoro.dmg.sha256" @@ -49,48 +53,56 @@ enum AutoUpdater { // MARK: - Core Logic private static func performCheck(silent: Bool) { - // 1. Fetch remote SHA256 + // 1. Read local SHA256 (written at last install/build) + let localSHA = readLocalSHA() + + // 2. Dev builds are stamped "dev" – skip silent checks entirely + if localSHA == devSentinel { + if !silent { + showAlert(title: "Dev Build", message: "Auto-update is disabled for local dev builds.") + } + return + } + + // 3. Fetch remote SHA256 guard let remoteSHA = fetchRemoteSHA() else { if !silent { showAlert(title: "Update Check Failed", message: "Could not reach the update server.") } return } - // 2. Read local SHA256 (written at last install/build) - let localSHA = readLocalSHA() - - // 3. Compare + // 4. Compare if remoteSHA == localSHA { if !silent { showAlert(title: "Up to Date", message: "You are running the latest version.") } return } - // 4. There's an update – prompt user + // 5. There's an update – prompt user let shouldUpdate = promptForUpdate() guard shouldUpdate else { return } - // 5. Download new DMG + // 6. Download new DMG guard downloadDMG() else { showAlert(title: "Update Failed", message: "Could not download the update.") return } - // 6. Verify downloaded DMG matches remote SHA + // 7. Verify downloaded DMG matches remote SHA guard let downloadedSHA = sha256(of: downloadedDMGPath), downloadedSHA == remoteSHA else { showAlert(title: "Update Failed", message: "Downloaded file integrity check failed.") try? FileManager.default.removeItem(at: downloadedDMGPath) return } - // 7. Extract new app from DMG to staging area + // 8. Extract new app from DMG to staging area guard stageFromDMG() else { showAlert(title: "Update Failed", message: "Could not extract the update.") return } - // 8. Save new SHA so we don't re-update next launch + // 9. Save new SHA so we don't re-update next launch try? remoteSHA.write(to: localSHAPath, atomically: true, encoding: .utf8) - // 9. Spawn swap script, then terminate so applicationWillTerminate saves state + // 10. Spawn swap script, then terminate so applicationWillTerminate saves state spawnSwapAndRelaunch() DispatchQueue.main.async { @@ -142,7 +154,7 @@ enum AutoUpdater { // MARK: - SHA256 Computation - private static func sha256(of fileURL: URL) -> String? { + static func sha256(of fileURL: URL) -> String? { guard let handle = try? FileHandle(forReadingFrom: fileURL) else { return nil } defer { handle.closeFile() } @@ -242,7 +254,6 @@ enum AutoUpdater { proc.arguments = [scriptPath] proc.standardOutput = FileHandle.nullDevice proc.standardError = FileHandle.nullDevice - // Detach from our process group so it survives our exit proc.qualityOfService = .utility try? proc.run() } diff --git a/releases/Pommedoro.dmg b/releases/Pommedoro.dmg index bfb63c8..e3df925 100644 Binary files a/releases/Pommedoro.dmg and b/releases/Pommedoro.dmg differ diff --git a/releases/Pommedoro.dmg.sha256 b/releases/Pommedoro.dmg.sha256 index 8ac8a02..e9dc16b 100644 --- a/releases/Pommedoro.dmg.sha256 +++ b/releases/Pommedoro.dmg.sha256 @@ -1 +1 @@ -7e15ab9b42481c28c9566c7d71bad03558bb2cdec7dcceb956443caf5cb1724a +98fa348545458a05d36e15656fdd788564e309784c4536a060499f0827141260