vChewing-macOS/Installer/ArchiveUtil.swift

120 lines
4.3 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import Cocoa
struct ArchiveUtil {
var appName: String
var targetAppBundleName: String
init(appName: String, targetAppBundleName: String) {
self.appName = appName
self.targetAppBundleName = targetAppBundleName
}
// Returns YES if (1) a zip file under
// Resources/NotarizedArchives/$_appName-$bundleVersion.zip exists, and (2) if
// Resources/$_invalidAppBundleName does not exist.
func validateIfNotarizedArchiveExists() -> Bool {
guard let resourePath = Bundle.main.resourcePath,
let notarizedArchivesPath = notarizedArchivesPath,
let notarizedArchive = notarizedArchive,
let notarizedArchivesContent: [String] = try? FileManager.default.subpathsOfDirectory(
atPath: notarizedArchivesPath)
else {
return false
}
let devModeAppBundlePath = (resourePath as NSString).appendingPathComponent(targetAppBundleName)
let count = notarizedArchivesContent.count
let notarizedArchiveExists = FileManager.default.fileExists(atPath: notarizedArchive)
let devModeAppBundleExists = FileManager.default.fileExists(atPath: devModeAppBundlePath)
if !notarizedArchivesContent.isEmpty {
// count > 0!isEmpty滿
if count != 1 || !notarizedArchiveExists || devModeAppBundleExists {
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = "Internal Error"
alert.informativeText =
"devMode installer, expected archive name: \(notarizedArchive), "
+ "archive exists: \(notarizedArchiveExists), devMode app bundle exists: \(devModeAppBundleExists)"
alert.addButton(withTitle: "Terminate")
alert.runModal()
NSApp.terminate(nil)
} else {
return true
}
}
if !devModeAppBundleExists {
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = "Internal Error"
alert.informativeText = "Dev target bundle does not exist: \(devModeAppBundlePath)"
alert.addButton(withTitle: "Terminate")
alert.runModal()
NSApp.terminate(nil)
}
return false
}
func unzipNotarizedArchive() -> String? {
if !validateIfNotarizedArchiveExists() {
return nil
}
guard let notarizedArchive = notarizedArchive,
let resourcePath = Bundle.main.resourcePath
else {
return nil
}
let tempFilePath = (NSTemporaryDirectory() as NSString).appendingPathComponent(
UUID().uuidString)
let arguments: [String] = [notarizedArchive, "-d", tempFilePath]
let unzipTask = Process()
unzipTask.launchPath = "/usr/bin/unzip"
unzipTask.currentDirectoryPath = resourcePath
unzipTask.arguments = arguments
unzipTask.launch()
unzipTask.waitUntilExit()
assert(unzipTask.terminationStatus == 0, "Must successfully unzipped")
let result = (tempFilePath as NSString).appendingPathComponent(targetAppBundleName)
assert(
FileManager.default.fileExists(atPath: result),
"App bundle must be unzipped at \(result)."
)
return result
}
private var notarizedArchivesPath: String? {
guard let resourePath = Bundle.main.resourcePath else {
return nil
}
let notarizedArchivesPath = (resourePath as NSString).appendingPathComponent(
"NotarizedArchives")
return notarizedArchivesPath
}
private var notarizedArchive: String? {
guard let notarizedArchivesPath = notarizedArchivesPath,
let bundleVersion = Bundle.main.infoDictionary?[kCFBundleVersionKey as String]
as? String
else {
return nil
}
let notarizedArchiveBasename = "\(appName)-r\(bundleVersion).zip"
let notarizedArchive = (notarizedArchivesPath as NSString).appendingPathComponent(
notarizedArchiveBasename)
return notarizedArchive
}
}