Skip to content

Commit

Permalink
(feat) can use json to augment/amend embedded data
Browse files Browse the repository at this point in the history
  • Loading branch information
mredig committed Feb 6, 2024
1 parent 394bb9d commit e9a15dc
Show file tree
Hide file tree
Showing 11 changed files with 221 additions and 66 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ public struct JSONAppcastItem: Codable {
public let minimumAutoUpdateVersion: String?
public let ignoreSkippedUpgradesBelowVersion: String?

/// Simply indicates if an update is critical or not.
public let criticalUpdate: Bool?
/// This value would be `1.2.4` in `<sparkle:criticalUpdate sparkle:version="1.2.4"></sparkle:criticalUpdate>`
public let criticalUpdate: String?
public let criticalUpdateVersion: String?
public let phasedRolloutInterval: Int?
}
```
Expand All @@ -26,14 +28,14 @@ public struct JSONAppcastItem: Codable {

* While it used to just append duplicate entries if you ran it with the same data, outputting to the same appcast several times, it now forgoes adding duplicates with the same download link!
* It now works with both companion JSON files, but also supports .zip archives with embedded .app bundles (and pulls data from Info.plist! - so no JSON companion is required)
* While the models support a more comprehensive solution for all the properties that can be added to the xml output, much of it has been omitted for now. Support for providing input for these features in the output xml would be great contributions, if anyone feels up to it. (My intention, in regards to this, is to refactor the logic to instead glob all the archive types, simply requiring json for formats that it can't automatically pull data from, but supporting json as supplementary data for the remaining.)
* You can augment the embedded data with an accompanied JSON file for zipped .app files
* While the models support a more comprehensive solution for all the properties that can be added to the xml output, much of it has been omitted for now. Support for providing input for these features in the output xml would be great contributions, if anyone feels up to it.
* releaseNotesLink
* fullReleaseNotesLink
* description
* maximumSystemVersion
* minimumAutoUpdateVersion
* ignoreSkippedUpgradesBelowVersion
* criticalUpdate
* phasedRolloutInterval

## Usage
Expand Down
96 changes: 68 additions & 28 deletions Sources/PKGAppcastGeneratorCore/AppcastItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,27 @@ import Foundation
import XMLCoder

public struct AppcastItem: Codable, Hashable {
public let title: String
public let link: URL
public let releaseNotesLink: URL?
public let fullReleaseNotesLink: URL?
public let version: String
public let shortVersionString: String?
public let description: String?
public let publishedDate: Date
public let enclosure: Enclosure
public let minimumSystemVersion: String?
public let maximumSystemVersion: String?
public let minimumAutoUpdateVersion: String?
public let ignoreSkippedUpgradesBelowVersion: String?
public var title: String
public var link: URL
public var releaseNotesLink: URL?
public var fullReleaseNotesLink: URL?
public var version: String
public var shortVersionString: String?
public var description: String?
public var publishedDate: Date
public var enclosure: Enclosure
public var minimumSystemVersion: String?
public var maximumSystemVersion: String?
public var minimumAutoUpdateVersion: String?
public var ignoreSkippedUpgradesBelowVersion: String?

/// This value would be `1.2.4` in `<sparkle:criticalUpdate sparkle:version="1.2.4"></sparkle:criticalUpdate>`
public let criticalUpdate: String?
public let phasedRolloutInterval: Int?
public var criticalUpdateVersion: String? {
get { criticalUpdate?.version }
set { criticalUpdate?.version = newValue }
}
public var criticalUpdate: CriticalUpdate?
public var phasedRolloutInterval: Int?

public init(
title: String,
Expand All @@ -34,7 +38,8 @@ public struct AppcastItem: Codable, Hashable {
maximumSystemVersion: String? = nil,
minimumAutoUpdateVersion: String? = nil,
ignoreSkippedUpgradesBelowVersion: String? = nil,
criticalUpdate: String? = nil,
criticalUpdateVersion: String? = nil,
criticalUpdate: Bool = false,
phasedRolloutInterval: Int? = nil
) {
self.title = title
Expand All @@ -50,7 +55,7 @@ public struct AppcastItem: Codable, Hashable {
self.maximumSystemVersion = maximumSystemVersion
self.minimumAutoUpdateVersion = minimumAutoUpdateVersion
self.ignoreSkippedUpgradesBelowVersion = ignoreSkippedUpgradesBelowVersion
self.criticalUpdate = criticalUpdate
self.criticalUpdate = criticalUpdate ? CriticalUpdate(version: criticalUpdateVersion) : nil
self.phasedRolloutInterval = phasedRolloutInterval
}

Expand All @@ -73,10 +78,10 @@ public struct AppcastItem: Codable, Hashable {
}

public struct Enclosure: Codable, DynamicNodeDecoding, DynamicNodeEncoding, Hashable {
public let url: URL
public let length: Int
public let mimeType: String
public let edSignature: String?
public var url: URL
public var length: Int
public var mimeType: String
public var edSignature: String?
public var installationType: String?

static public func nodeDecoding(for key: CodingKey) -> XMLDecoder.NodeDecoding { .attribute }
Expand Down Expand Up @@ -104,20 +109,32 @@ public struct AppcastItem: Codable, Hashable {
case installationType = "sparkle:installationType"
}
}

public struct CriticalUpdate: Codable, DynamicNodeDecoding, DynamicNodeEncoding, Hashable {
var version: String?

enum CodingKeys: String, CodingKey {
case version = "sparkle:version"
}

static public func nodeDecoding(for key: CodingKey) -> XMLDecoder.NodeDecoding { .attribute }
static public func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding { .attribute }
}
}

public extension AppcastItem {
init(from appCast: JSONAppcastItem, enclosure: Enclosure) {
init(from appCast: JSONAppcastItem, enclosure: Enclosure, isPackage: Bool? = nil) throws {
var enclosure = enclosure
if appCast.isPackage == true {
if appCast.isPackage == true || isPackage == true {
enclosure.installationType = "package"
try appCast.validateForPKG()
}
self.init(
title: appCast.title,
link: appCast.link,
try self.init(
title: appCast.title.unwrap(),
link: appCast.link.unwrap(),
releaseNotesLink: appCast.releaseNotesLink,
fullReleaseNotesLink: appCast.fullReleaseNotesLink,
version: appCast.version,
version: appCast.version.unwrap(),
shortVersionString: appCast.shortVersionString,
description: appCast.description,
publishedDate: Date(),
Expand All @@ -126,7 +143,30 @@ public extension AppcastItem {
maximumSystemVersion: appCast.maximumSystemVersion,
minimumAutoUpdateVersion: appCast.minimumAutoUpdateVersion,
ignoreSkippedUpgradesBelowVersion: appCast.ignoreSkippedUpgradesBelowVersion,
criticalUpdate: appCast.criticalUpdate,
criticalUpdateVersion: appCast.criticalUpdateVersion,
criticalUpdate: appCast.criticalUpdate ?? false,
phasedRolloutInterval: appCast.phasedRolloutInterval)
}

mutating func update(from jsonItem: JSONAppcastItem) {
self.title = jsonItem.title ?? title
self.link = jsonItem.link ?? link
self.releaseNotesLink = jsonItem.releaseNotesLink ?? releaseNotesLink
self.fullReleaseNotesLink = jsonItem.fullReleaseNotesLink ?? fullReleaseNotesLink
self.version = jsonItem.version ?? version
self.shortVersionString = jsonItem.shortVersionString ?? shortVersionString
self.description = jsonItem.description ?? description
self.minimumSystemVersion = jsonItem.minimumSystemVersion ?? minimumSystemVersion
self.maximumSystemVersion = jsonItem.maximumSystemVersion ?? maximumSystemVersion
self.minimumAutoUpdateVersion = jsonItem.minimumAutoUpdateVersion ?? minimumAutoUpdateVersion
self.ignoreSkippedUpgradesBelowVersion = jsonItem.ignoreSkippedUpgradesBelowVersion ?? ignoreSkippedUpgradesBelowVersion
if let criticalUpdate = jsonItem.criticalUpdate {
if criticalUpdate {
self.criticalUpdate = CriticalUpdate(version: jsonItem.criticalUpdateVersion)
} else if let criticalUpdateVersion = jsonItem.criticalUpdateVersion {
self.criticalUpdate = nil
}
}
self.phasedRolloutInterval = jsonItem.phasedRolloutInterval ?? phasedRolloutInterval
}
}
24 changes: 19 additions & 5 deletions Sources/PKGAppcastGeneratorCore/JSONAppcastItem.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
import Foundation

public struct JSONAppcastItem: Codable {
public let title: String
public let link: URL
public let title: String?
public let link: URL?
public let releaseNotesLink: URL?
public let fullReleaseNotesLink: URL?
public let version: String
public let version: String?
public let shortVersionString: String?
public let description: String?
public let minimumSystemVersion: String?
public let maximumSystemVersion: String?
public let minimumAutoUpdateVersion: String?
public let ignoreSkippedUpgradesBelowVersion: String?

/// Simply indicates if an update is critical or not.
public let criticalUpdate: Bool?
/// This value would be `1.2.4` in `<sparkle:criticalUpdate sparkle:version="1.2.4"></sparkle:criticalUpdate>`
public let criticalUpdate: String?
public let criticalUpdateVersion: String?
public let phasedRolloutInterval: Int?

public let isPackage: Bool?
public var isPackage: Bool?

public func validateForPKG() throws {
guard title != nil else { throw JSONAppcastError.missingPKGTitle }
guard link != nil else { throw JSONAppcastError.missingPKGLink }
guard version != nil else { throw JSONAppcastError.missingPKGVersion }
}

public enum JSONAppcastError: Error {
case missingPKGTitle
case missingPKGLink
case missingPKGVersion
}
}
Loading

0 comments on commit e9a15dc

Please sign in to comment.