From cb2cad9d133c90ec7104ff875eb10b2fe8b6aad8 Mon Sep 17 00:00:00 2001 From: stackotter Date: Thu, 3 Feb 2022 15:57:35 +1000 Subject: [PATCH] Allow Info.plist customisation --- Sources/swift-bundler/Configuration.swift | 18 +++- .../swift-bundler/Subcommands/Bundle.swift | 21 ++--- Sources/swift-bundler/Utils/Utils.swift | 90 +++++++------------ 3 files changed, 59 insertions(+), 70 deletions(-) diff --git a/Sources/swift-bundler/Configuration.swift b/Sources/swift-bundler/Configuration.swift index 3707de2..22ddac5 100644 --- a/Sources/swift-bundler/Configuration.swift +++ b/Sources/swift-bundler/Configuration.swift @@ -7,13 +7,27 @@ struct Configuration: Codable { var buildNumber: Int var category: String var minOSVersion: String + + var extraInfoPlistEntries: [String: Any] = [:] + + enum CodingKeys: String, CodingKey { + case target, bundleIdentifier, versionString, buildNumber, category, minOSVersion + } static func load(_ directory: URL) -> Configuration { do { let data = try Data(contentsOf: directory.appendingPathComponent("Bundle.json")) - return try JSONDecoder().decode(Configuration.self, from: data) + var configuration = try JSONDecoder().decode(Configuration.self, from: data) + + // Load the `extraInfoPlistEntries` property if present + let json = try JSONSerialization.jsonObject(with: data) + if let json = json as? [String: Any], let extraEntries = json["extraInfoPlistEntries"] as? [String: Any] { + configuration.extraInfoPlistEntries = extraEntries + } + + return configuration } catch { terminate("Failed to load config from Bundle.json. Please make sure that the current directory is setup for swift-bundler correctly; \(error)") } } -} \ No newline at end of file +} diff --git a/Sources/swift-bundler/Subcommands/Bundle.swift b/Sources/swift-bundler/Subcommands/Bundle.swift index 2648f67..7c90872 100644 --- a/Sources/swift-bundler/Subcommands/Bundle.swift +++ b/Sources/swift-bundler/Subcommands/Bundle.swift @@ -180,15 +180,16 @@ extension Bundler { // Create Info.plist updateProgress("Creating Info.plist", 0.7) let infoPlistFile = appContents.appendingPathComponent("Info.plist") - let infoPlist = createAppInfoPlist( - appName: target, - bundleIdentifier: config.bundleIdentifier, - versionString: config.versionString, - buildNumber: config.buildNumber, - category: config.category, - minOSVersion: config.minOSVersion) do { - try infoPlist.write(to: infoPlistFile, atomically: false, encoding: .utf8) + let infoPlist = try createAppInfoPlist( + appName: target, + bundleIdentifier: config.bundleIdentifier, + versionString: config.versionString, + buildNumber: config.buildNumber, + category: config.category, + minOSVersion: config.minOSVersion, + extraEntries: config.extraInfoPlistEntries) + try infoPlist.write(to: infoPlistFile) } catch { terminate("Failed to create Info.plist at '\(infoPlistFile.path)'; \(error)") } @@ -240,9 +241,9 @@ extension Bundler { let infoPlistFile = bundleContents.appendingPathComponent("Info.plist") if !FileManager.default.itemExists(at: infoPlistFile, withType: .file) { log.info("Creating Info.plist for \(bundle.lastPathComponent)") - let infoPlist = createBundleInfoPlist(bundleIdentifier: bundleIdentifier, bundleName: bundleName, minOSVersion: config.minOSVersion) do { - try infoPlist.write(to: infoPlistFile, atomically: false, encoding: .utf8) + let infoPlist = try createBundleInfoPlist(bundleIdentifier: bundleIdentifier, bundleName: bundleName, minOSVersion: config.minOSVersion) + try infoPlist.write(to: infoPlistFile) } catch { terminate("Failed to create Info.plist for '\(bundle.lastPathComponent)'; \(error)") } diff --git a/Sources/swift-bundler/Utils/Utils.swift b/Sources/swift-bundler/Utils/Utils.swift index 315f74c..6f23ff2 100644 --- a/Sources/swift-bundler/Utils/Utils.swift +++ b/Sources/swift-bundler/Utils/Utils.swift @@ -28,66 +28,40 @@ rm -R \(iconSetPath) } } -func createAppInfoPlist(appName: String, bundleIdentifier: String, versionString: String, buildNumber: Int, category: String, minOSVersion: String) -> String { - return """ - - - - - CFBundleExecutable - \(appName) - CFBundleIconFile - AppIcon - CFBundleIconName - AppIcon - CFBundleIdentifier - \(bundleIdentifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - \(appName) - CFBundlePackageType - APPL - CFBundleShortVersionString - \(versionString) - CFBundleSupportedPlatforms - - MacOSX - - CFBundleVersion - \(buildNumber) - LSApplicationCategoryType - \(category) - LSMinimumSystemVersion - \(minOSVersion) - - -""" +func createAppInfoPlist(appName: String, bundleIdentifier: String, versionString: String, buildNumber: Int, category: String, minOSVersion: String, extraEntries: [String: Any]) throws -> Data { + var entries: [String: Any] = [ + "CFBundleExecutable": appName, + "CFBundleIconFile": "AppIcon", + "CFBundleIconName": "AppIcon", + "CFBundleIdentifier": bundleIdentifier, + "CFBundleInfoDictionaryVersion": "6.0", + "CFBundleName": appName, + "CFBundlePackageType": "APPL", + "CFBundleShortVersionString": versionString, + "CFBundleSupportedPlatforms": ["MacOSX"], + "CFBundleVersion": "\(buildNumber)", + "LSApplicationCategoryType": category, + "LSMinimumSystemVersion": minOSVersion, + ] + + for (key, value) in extraEntries { + entries[key] = value + } + + return try PropertyListSerialization.data(fromPropertyList: entries, format: .xml, options: 0) } -func createBundleInfoPlist(bundleIdentifier: String, bundleName: String, minOSVersion: String) -> String { - return """ - - - - - CFBundleIdentifier - \(bundleIdentifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - \(bundleName) - CFBundlePackageType - BNDL - CFBundleSupportedPlatforms - - MacOSX - - LSMinimumSystemVersion - \(minOSVersion) - - -""" +func createBundleInfoPlist(bundleIdentifier: String, bundleName: String, minOSVersion: String) throws -> Data { + let entries: [String: Any] = [ + "CFBundleIdentifier": bundleIdentifier, + "CFBundleInfoDictionaryVersion": "6.0", + "CFBundleName": bundleName, + "CFBundlePackageType": "BNDL", + "CFBundleSupportedPlatforms": ["MacOSX"], + "LSMinimumSystemVersion": minOSVersion, + ] + + return try PropertyListSerialization.data(fromPropertyList: entries, format: .xml, options: 0) } func terminate(_ message: String) -> Never {