Skip to content

Commit

Permalink
Merge pull request #34 from SwiftPackageIndex/fix-platform-validation
Browse files Browse the repository at this point in the history
Add Platform.init(lenientRawValue:) to support lenient inputs at the source
  • Loading branch information
finestructure committed Oct 8, 2023
2 parents 0cbefa2 + 1e6e316 commit b2da637
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 27 deletions.
60 changes: 33 additions & 27 deletions Sources/SPIManifest/Manifest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public struct Manifest: Codable, Equatable {
public var configs: [BuildConfig]

public struct BuildConfig: Codable, Equatable {
public var platform: String?
public var platform: Platform?
public var swiftVersion: ShortVersion?
public var image: String?
public var scheme: String?
Expand All @@ -69,13 +69,40 @@ public struct Manifest: Codable, Equatable {
}

public init(platform: String? = nil, swiftVersion: ShortVersion? = nil, image: String? = nil, scheme: String? = nil, target: String? = nil, documentationTargets: [String]? = nil) {
self.platform = platform
self.platform = platform.flatMap(Platform.init(lenientRawValue:))
self.swiftVersion = swiftVersion
self.image = image
self.scheme = scheme
self.target = target
self.documentationTargets = documentationTargets
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

// Decode platform as String to allow for more lenient interpretation
self.platform = try container.decodeIfPresent(String.self, forKey: .platform)
.flatMap(Platform.init(lenientRawValue:))
self.swiftVersion = try container.decodeIfPresent(ShortVersion.self, forKey: .swiftVersion)
self.image = try container.decodeIfPresent(String.self, forKey: .image)
self.scheme = try container.decodeIfPresent(String.self, forKey: .scheme)
self.target = try container.decodeIfPresent(String.self, forKey: .target)
self.documentationTargets = try container.decodeIfPresent([String].self, forKey: .documentationTargets)
self.customDocumentationParameters = try container.decodeIfPresent([String].self, forKey: .customDocumentationParameters)

}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

try container.encodeIfPresent(self.platform, forKey: .platform)
try container.encodeIfPresent(self.swiftVersion, forKey: .swiftVersion)
try container.encodeIfPresent(self.image, forKey: .image)
try container.encodeIfPresent(self.scheme, forKey: .scheme)
try container.encodeIfPresent(self.target, forKey: .target)
try container.encodeIfPresent(self.documentationTargets, forKey: .documentationTargets)
try container.encodeIfPresent(self.customDocumentationParameters, forKey: .customDocumentationParameters)
}
}

public init(configs: [Manifest.Builder.BuildConfig]) {
Expand All @@ -102,9 +129,7 @@ public struct Manifest: Codable, Equatable {
}

public init(yml: String) throws {
var manifest = try YAMLDecoder().decode(Self.self, from: yml)
Self.fixPlatforms(manifest: &manifest)
self = manifest
self = try YAMLDecoder().decode(Self.self, from: yml)
}
}

Expand Down Expand Up @@ -164,7 +189,6 @@ extension Manifest {
throw ManifestError.decodingError("\(error)")
}

Self.fixPlatforms(manifest: &manifest)
return manifest
}

Expand All @@ -184,17 +208,17 @@ extension Manifest {
case let (.specific(platform), .specific(swiftVersion)):
return builder.configs
.first {
$0.platform == platform.rawValue
$0.platform == platform
&& $0.swiftVersion == swiftVersion.rawValue
}

case let (.specific(platform), .any):
return builder.configs
.first { $0.platform == platform.rawValue }
.first { $0.platform == platform }

case let (.specific(platform), .none):
return builder.configs
.first { $0.platform == platform.rawValue && $0.swiftVersion == nil }
.first { $0.platform == platform && $0.swiftVersion == nil }

case let (.any, .specific(swiftVersion)):
return builder.configs
Expand Down Expand Up @@ -290,21 +314,3 @@ extension Manifest {
}

}


extension Manifest {
/// Adjust user provided platform inputs to match valid keys. For instance `macos` (which would need to be `macos-spm` to match `Platform.macosSpm`.
/// - Parameter manifest: input `Manifest`
private static func fixPlatforms(manifest: inout Manifest) {
if let builder = manifest.builder {
let configs = builder.configs.map { config -> Builder.BuildConfig in
var config = config
if config.platform?.lowercased() == "macos" {
config.platform = Platform.macosSpm.rawValue
}
return config
}
manifest.builder?.configs = configs
}
}
}
29 changes: 29 additions & 0 deletions Sources/SPIManifest/Platform.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,33 @@ public enum Platform: String, Codable, CaseIterable {
case tvOS = "tvos"
case visionOS = "visionos"
case watchOS = "watchos"


}


extension Platform {
public init?(lenientRawValue: String) {
// Try plain enum rawValue init
if let platform = Platform(rawValue: lenientRawValue) {
self = platform
return
}

// Support upper case variants
if let platform = Platform(rawValue: lenientRawValue.lowercased()) {
self = platform
return
}

// Support alternative spellings for macos, defaulting to macos-spm
switch lenientRawValue.lowercased() {
case "macos", "macosspm":
self = .macosSpm
case "macosxcodebuild":
self = .macosXcodebuild
default:
return nil
}
}
}
13 changes: 13 additions & 0 deletions Tests/SPIManifestTests/ManifestTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ import Yams

class ManifestTests: XCTestCase {

func test_Platform_init_lenientRawValue() throws {
XCTAssertEqual(Platform(lenientRawValue: "ios"), .iOS)
XCTAssertEqual(Platform(lenientRawValue: "iOS"), .iOS)
XCTAssertEqual(Platform(lenientRawValue: "iOs"), .iOS)
XCTAssertEqual(Platform(lenientRawValue: "macos"), .macosSpm)
XCTAssertEqual(Platform(lenientRawValue: "macosspm"), .macosSpm)
XCTAssertEqual(Platform(lenientRawValue: "macos-spm"), .macosSpm)
XCTAssertEqual(Platform(lenientRawValue: "macos-SPM"), .macosSpm)
XCTAssertEqual(Platform(lenientRawValue: "macosXcodebuild"), .macosXcodebuild)
XCTAssertEqual(Platform(lenientRawValue: "macosxcodebuild"), .macosXcodebuild)
XCTAssertEqual(Platform(lenientRawValue: "macos-xcodebuild"), .macosXcodebuild)
}

func test_empty() throws {
XCTAssertNoThrow(try Manifest(yml: "version: 1"))
}
Expand Down

0 comments on commit b2da637

Please sign in to comment.