Skip to content

Commit

Permalink
auto upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
fuji246 committed Sep 8, 2019
1 parent 2a7cc13 commit 881826e
Show file tree
Hide file tree
Showing 62 changed files with 7,990 additions and 29 deletions.
110 changes: 98 additions & 12 deletions LomoAgent.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions LomoAgent.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions LomoAgent.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
type = "0"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "LomoAgent/AppDelegate.swift"
timestampString = "589589393.718982"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "76"
endingLineNumber = "76"
landmarkName = "applicationDidFinishLaunching(_:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
16 changes: 13 additions & 3 deletions LomoAgent/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ extension OSLog {
static let logic = OSLog(subsystem: subsystem, category: "Logic")
}

func setupSigHandler() {
signal(SIGTERM) { signal in
os_log("Interrupted! Cleaning up...", log: .logic, type: .info)
NotificationCenter.default.post(name: .NotifyExit, object: nil)
}
}

func getLomodService() -> LomodService? {
guard let appDelegate = NSApplication.shared.delegate as? AppDelegate else {
os_log("getLomodService, error when getting AppDelegate", log: .logic, type: .error)
Expand All @@ -34,7 +41,7 @@ extension Notification.Name {
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

var lomodService = LomodService()
let lomodService = LomodService()

func applicationWillFinishLaunching(_ aNotification: Notification) {
let version = Bundle.main.infoDictionary?["CFBundleVersion"] as! String
Expand All @@ -56,12 +63,15 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}

func applicationDidFinishLaunching(_ aNotification: Notification) {
setupSigHandler()
let runningApps = NSWorkspace.shared.runningApplications
let isRunning = !runningApps.filter { $0.bundleIdentifier == launcherAppId }.isEmpty

if isRunning {
DistributedNotificationCenter.default().post(name: .killLauncher,
object: Bundle.main.bundleIdentifier!)
DistributedNotificationCenter.default().post(
name: .killLauncher,
object: Bundle.main.bundleIdentifier!
)
}
}

Expand Down
4 changes: 2 additions & 2 deletions LomoAgent/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>f3479b7</string>
<string>2a7cc13</string>
<key>CFBundleVersion</key>
<string>2019_09_04.09_22_08.0.f3479b7</string>
<string>2019_09_07.21_36_19.0.2a7cc13</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
Expand Down
11 changes: 1 addition & 10 deletions LomoAgent/LomoAgent.entitlements
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
<dict/>
</plist>
229 changes: 229 additions & 0 deletions LomoAgent/LomoUpgrade.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
//
// LomoUpgrade.swift
// LomoAgent
//
// Created by Jiantao Fu on 9/4/19.
// Copyright © 2019 lomoware. All rights reserved.
//

import Foundation
import os.log
import Zip

let LOMO_UPGRADE_URL = "https://lomorage.com/release.json"

// todo: share we have sha256 for updater as well? Share we remove pre-post in json if not used?
struct UpgradeConfig {
let agentSha256: String
let agentVer: String
let agentUrl: String
let updateVer: String
let updateUrl: String
}

class LomoUpgrade {

private var networkSession: NetworkSession!

private let upgradeUrl: String

var config: UpgradeConfig?

init(url: String) {
upgradeUrl = url
let defaultConfiguration = URLSessionConfiguration.default
defaultConfiguration.allowsCellularAccess = false
defaultConfiguration.timeoutIntervalForRequest = 20
networkSession = URLSession(configuration: defaultConfiguration)
}

func update() {
fetchUpdateConf()

if needUpdateLomoUpg() {
let succ = updateLomoUpg()
guard succ else {
os_log("update LomoUpg failed!", log: .logic, type: .error)
return
}
}

if needUpdateAgent() {
updateAgent()
}
}

func updateLomoUpg() -> Bool {
guard config != nil else {
return false
}

let cacheFilePath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
var destinationFileUrl: URL? = cacheFilePath.appendingPathComponent("LomoUpg.zip")
guard destinationFileUrl != nil else {
os_log("updateLomoUpg, destinationFileUrl is nil", log: .logic, type: .error)
return false
}

if let updateUrl = URL(string: config!.updateUrl) {
let urlRequest = URLRequest(url: updateUrl)
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)

let opGroup = DispatchGroup()
opGroup.enter()
let task = session.downloadTask(with: urlRequest) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Success
try? FileManager.default.removeItem(at: destinationFileUrl!)
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl!)
} catch (let writeError) {
os_log("updateLomoUpg, Error copying file from %{public}s to %{public}s, err: %{public}s", log: .logic, type: .error, tempLocalUrl.absoluteString, destinationFileUrl!.absoluteString, writeError.localizedDescription)
try? FileManager.default.removeItem(at: destinationFileUrl!)
destinationFileUrl = nil
}
} else {
os_log("updateLomoUpg, Error took place while downloading a file. Error description: %{public}s", log: .logic, type: .error, String(describing: error?.localizedDescription))
destinationFileUrl = nil
}
opGroup.leave()
}
task.resume()
opGroup.wait()
}

if destinationFileUrl != nil {
guard let executablePath = Bundle.main.executableURL?.deletingLastPathComponent(), let lomoupgPath = URL(string: executablePath.path) else {
os_log("updateLomoUpg, can't get lomoupgPath", log: .logic, type: .error)
return false
}

do {
try Zip.unzipFile(destinationFileUrl!, destination: lomoupgPath, overwrite: true, password: nil)
return true
} catch let err as NSError {
os_log("updateLomoUpg, unzip %{public}s to %{public}s failed with error: %{public}s",
log: .logic, type: .error,
destinationFileUrl!.absoluteString,
lomoupgPath.absoluteString,
err.localizedDescription)
}

try? FileManager.default.removeItem(at: destinationFileUrl!)
}

return false
}

func updateAgent() {
if let executablePath = Bundle.main.executableURL?.deletingLastPathComponent() {
let lomoupgPath = executablePath.path + "/lomoupg"
os_log("lomoupg Path: %{public}s", log: .logic, lomoupgPath)
guard FileManager.default.fileExists(atPath: lomoupgPath) else {
os_log("lomoupgPath not found: %{public}s", log: .logic, type: .error, lomoupgPath)
return
}
let cacheFilePathURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
let appPath = Bundle.main.bundlePath
let appFolderPath = URL(string: appPath)?.deletingLastPathComponent().absoluteURL.absoluteString

let task = Process()
task.launchPath = lomoupgPath
task.arguments = [
"--app-dir", appFolderPath!,
"--backup-dir", cacheFilePathURL.path,
"--curr-version", getCurrentAgentVer()!,
"--precmd", "/usr/bin/killall",
"--precmdarg", "LomoAgent",
"--postcmd", "open",
"--postcmdarg", Bundle.main.bundlePath
]

// not able to get result now, will get reboot if succ
task.launch()
} else {
os_log("updateAgent error, not able to get lomoupg path", log: .logic, type: .error)
}
}

func needUpdateAgent() -> Bool {
if let c = config {
return c.agentVer != getCurrentAgentVer()
} else {
return false // config not available yet
}
}

func needUpdateLomoUpg() -> Bool {
if let c = config {
if let currentVer = getCurrentLomoUpgVer() {
return c.updateVer != currentVer
}
}
return false // config not available yet or LomoUpg not exist
}

func getCurrentAgentVer() -> String? {
return Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
}

func getCurrentLomoUpgVer() -> String? {
if let executablePath = Bundle.main.executableURL?.deletingLastPathComponent() {
let lomoupgPath = executablePath.path + "/lomoupg"
os_log("lomoupg Path: %{public}s", log: .logic, lomoupgPath)
guard FileManager.default.fileExists(atPath: lomoupgPath) else {
os_log("getCurrentLomoUpgVer, lomoupg not found: %{public}s", log: .logic, type: .error, lomoupgPath)
return nil
}
let (output, error, status) = runCommand(cmd: lomoupgPath, args: "--version")
if status == 0 {
return output.first
} else {
os_log("getCurrentLomoUpgVer error: %{public}s", log: .logic, type: .error, error)
return nil
}
} else {
os_log("getCurrentLomoUpgVer error, not able to get lomoupg path", log: .logic, type: .error)
return nil
}
}

func fetchUpdateConf() {
if let url = URL(string: upgradeUrl) {
let opGroup = DispatchGroup()
opGroup.enter()
self.networkSession.loadData(with: url, completionHandler: { (data, response, error) in
if let error = error {
os_log("needUpdateLomoupgAndLomoAgent request error: %{public}s", log: .logic, type: .error, error.localizedDescription)
} else if let data = data, let httpresp = response as? HTTPURLResponse {
if httpresp.statusCode == 200, let jsonResult = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
os_log("needUpdateLomoupgAndLomoAgent, json response: %{public}@", log: .logic, jsonResult!)

if let osxConf = jsonResult?["darwin"] as? [String: Any] {

guard let agentSha256 = osxConf["SHA256"] as? String,
let agentVer = osxConf["Version"] as? String,
let agentUrl = osxConf["URL"] as? String,
let updateVer = osxConf["LomoUpgVer"] as? String,
let updateUrl = osxConf["LomoUpdateURL"] as? String else {
os_log("fetchContactList, malformed format!", log: .logic, type: .error)
return
}

self.config = UpgradeConfig(agentSha256: agentSha256, agentVer: agentVer, agentUrl: agentUrl, updateVer: updateVer, updateUrl: updateUrl)
} else {
os_log("fetchContactList, osx version not available", log: .logic, type: .error)
}

} else {
os_log("fetchContactList, userList error: %{public}s\n%{public}@", log: .logic, type: .error, String(data: data, encoding: .utf8)!, httpresp)
}
} else {
os_log("needUpdateLomoupgAndLomoAgent, error: %{public}s", log: .logic, type: .error, String(describing: response))
}
}, sync: opGroup)
opGroup.wait()
}
}
}
Loading

0 comments on commit 881826e

Please sign in to comment.