diff --git a/phpmon-updater/Updater.swift b/phpmon-updater/Updater.swift index 94d572b..550acb6 100644 --- a/phpmon-updater/Updater.swift +++ b/phpmon-updater/Updater.swift @@ -14,14 +14,17 @@ class Updater: NSObject, NSApplicationDelegate { var manifest: ReleaseManifest! = nil func applicationDidFinishLaunching(_ aNotification: Notification) { - print("PHP MONITOR SELF-UPDATER by Nico Verbruggen") self.updaterDirectory = "~/.config/phpmon/updater" .replacingOccurrences(of: "~", with: NSHomeDirectory()) + print("Updater directory set to: \(self.updaterDirectory)") + let manifestPath = "\(updaterDirectory)/update.json" + print("Checking manifest file at \(manifestPath)") + // Read out the correct information from the manifest JSON do { let manifestText = try String(contentsOfFile: manifestPath) @@ -30,24 +33,22 @@ class Updater: NSObject, NSApplicationDelegate { print("Parsing the manifest failed (or the manifest file doesn't exist)") showAlert( title: "Key information about the update is missing", - description: "The self-updater only works in combination with PHP Monitor. Please try searching for updates again in PHP Monitor. The app has not been updated." + description: "The app has not been updated. The self-updater only works in combination with PHP Monitor. Please try searching for updates again in PHP Monitor." ) exit(0) } - print("Updater directory set to: \(self.updaterDirectory)") - // Download the latest file let zipPath = self.download(manifest) - // Terminating all instances of PHP Monitor first + // Terminate all instances of PHP Monitor first terminatePhpMon() - // We made it! - install(zipPath: zipPath) + // Install the app based on the zip + let appPath = extractAndInstall(zipPath: zipPath) // Restart PHP Monitor, this will also close the updater - restartPhpMon(dev: zipPath.contains("dev")) + restartPhpMon(at: appPath) } func applicationWillTerminate(_ aNotification: Notification) { @@ -99,10 +100,14 @@ class Updater: NSObject, NSApplicationDelegate { return "\(updaterDirectory)/\(filename)" } - private func install(zipPath: String) { + private func extractAndInstall(zipPath: String) -> String { + // Remove the directory that will contain the extracted update system_quiet("rm -rf \(updaterDirectory)/extracted") + + // Recreate the directory where we will unzip the .app file system_quiet("mkdir -p \(updaterDirectory)/extracted") + // Make sure the updater directory exists var isDirectory: ObjCBool = true if !FileManager.default.fileExists(atPath: "\(updaterDirectory)/extracted", isDirectory: &isDirectory) { showAlert( @@ -112,29 +117,46 @@ class Updater: NSObject, NSApplicationDelegate { exit(0) } + // Unzip the file system_quiet("unzip \(zipPath) -d \(updaterDirectory)/extracted") - let expectedAppName = zipPath.contains("dev") - ? "PHP Monitor DEV.app" - : "PHP Monitor.app" + // Find the .app file + let app = system("ls \(updaterDirectory)/extracted | grep .app") + .trimmingCharacters(in: .whitespacesAndNewlines) - print("Removing \(expectedAppName) before replacing...") + print("Finished extracting: \(updaterDirectory)/extracted/\(app)") - system_quiet("rm -rf \"/Applications/\(expectedAppName)\"") - system_quiet("mv \"\(updaterDirectory)/extracted/\(expectedAppName)\" \"/Applications/\(expectedAppName)\"") + // Make sure the file was extracted + if app.isEmpty { + showAlert( + title: "The downloaded file could not be extracted", + description: "The automatic updater will quit. Make sure that ` ~/.config/phpmon/updater` is writeable." + ) + exit(0) + } + + print("Removing \(app) before replacing...") + + system_quiet("rm -rf \"/Applications/\(app)\"") + system_quiet("mv \"\(updaterDirectory)/extracted/\(app)\" \"/Applications/\(app)\"") + + return "/Applications/\(app)" } private func terminatePhpMon() { let runningApplications = NSWorkspace.shared.runningApplications + // Look for these instances let ids = [ "com.nicoverbruggen.phpmon.dev", "com.nicoverbruggen.phpmon" ] + // Terminate all instances found for id in ids { - if let phpmon = runningApplications - .first(where: { (application) in return application.bundleIdentifier == id }) { + if let phpmon = runningApplications.first(where: { + (application) in return application.bundleIdentifier == id + }) { phpmon.terminate() } } @@ -142,19 +164,17 @@ class Updater: NSObject, NSApplicationDelegate { private func smartRestartPhpMon() { if FileManager.default.fileExists(atPath: "/Applications/PHP Monitor.app") { - restartPhpMon(dev: false) + restartPhpMon(at: "/Applications/PHP Monitor.app") } else if FileManager.default.fileExists(atPath: "/Applications/PHP Monitor DEV.app") { - restartPhpMon(dev: true) + restartPhpMon(at: "/Applications/PHP Monitor DEV.app") } } - private func restartPhpMon(dev: Bool) { - let path = dev ? "/Applications/PHP Monitor DEV.app" : "/Applications/PHP Monitor.app" + private func restartPhpMon(at path: String) { let url = NSURL(fileURLWithPath: path, isDirectory: true) as URL let configuration = NSWorkspace.OpenConfiguration() NSWorkspace.shared.openApplication(at: url, configuration: configuration) { phpmon, error in - // Once we've opened PHP Monitor again... quit the updater exit(0) } }