Files
XcodeGen/Sources/ProjectSpec/SwiftPackage.swift
T
Roman Podymov 8b3a68319b Handle major.minor for SPM (#1546)
* Custom error handler

* Check for error reason and expected type

* Improvements

* Update CHANGELOG.md

* Update master (#1)

* Update CI equipments and drop Xcode 15 support (#1548)

* Add validation to ensure that settings.configs values are dictionaries, in order to prevent misuse (#1547)

* Add validation to ensure settings.configs values are dictionaries to prevent misuse

* Add tests for invalid settings.configs value formats

* Replaced with filter and split into a function

* Rename invalidConfigsFormat to invalidConfigsMappingFormat

* Add comments to explain invalid  fixture

* Rename test fixture

* Update CHANGELOG.md

* Correct grammer

* Use KeyPath instead of closure

* Rename validateMappingStyleInConfig to extractValidConfigs

* Add a document comment for extractValidConfigs(from:)

* Use old testing api and remove EquatableErrorBox

* Rename test case to use "mapping" instead of "dictionary"

* Add ValidSettingsExtractor to encapsulate the logic for converting a dictionary to Settings

* Add settings validation for both Target and AggregateTarget

* Add tests for invalid settings.configs in Target and AggregateTarget

* Add document comments for ValidSettingsExtractor

* Rename ValidSettingsExtractor to BuildSettingsExtractor

* Add settings validation for settingGroups

* Add tests for settingGroups

* Rename extract to parse

* Refactor

* Update Tests/ProjectSpecTests/InvalidConfigsFormatTests.swift

---------

Co-authored-by: Yonas Kolb <yonaskolb@users.noreply.github.com>

* Synced folders (#1541)

* update xcodeproj to 8.27.7

* add syncedFolder source type

* drop xcode 15 support

* Rely on fileReference instead of adding new synchronizedRootGroup (#1557)

* fix: don't include untracked children in cache

---------

Co-authored-by: Kirill Yakimovich <kirill.yakimovich@gmail.com>

* Use USER env var instead of LOGNAME (#1559)

During user switch with su/sudo in system LOGNAME may not be initialised, but USER env var is always exist.

* Address Sanitizer options in run/test schemes (#1550)

* Expose address sanitizer flags in run and test BuildActions in Schemes

* Update testJSONEncodable to test the new fields

* Also test the asan setting values for run scheme

* Update changelog

---------

Co-authored-by: Yonas Kolb <yonaskolb@users.noreply.github.com>

* Update to 2.44.0

# Conflicts:
#	CHANGELOG.md

---------

Co-authored-by: Kohki Miki <giginet.net@gmail.com>
Co-authored-by: Ryu <87907656+Ryu0118@users.noreply.github.com>
Co-authored-by: Yonas Kolb <yonaskolb@users.noreply.github.com>
Co-authored-by: Kirill Yakimovich <kirill.yakimovich@gmail.com>
Co-authored-by: Kanstantsin Shautsou <kanstantsin.sha@gmail.com>
Co-authored-by: Himanshu Kumar <7786778+hi-kumar@users.noreply.github.com>

* Revert

* Refactoring started

* func json(atKeyPath keyPath: String) -> String?

* All cases

---------

Co-authored-by: Kohki Miki <giginet.net@gmail.com>
Co-authored-by: Ryu <87907656+Ryu0118@users.noreply.github.com>
Co-authored-by: Yonas Kolb <yonaskolb@users.noreply.github.com>
Co-authored-by: Kirill Yakimovich <kirill.yakimovich@gmail.com>
Co-authored-by: Kanstantsin Shautsou <kanstantsin.sha@gmail.com>
Co-authored-by: Himanshu Kumar <7786778+hi-kumar@users.noreply.github.com>
2025-07-22 19:21:49 +10:00

156 lines
5.4 KiB
Swift

import Foundation
import XcodeProj
import JSONUtilities
import Version
public enum SwiftPackage: Equatable {
public typealias VersionRequirement = XCRemoteSwiftPackageReference.VersionRequirement
static let githubPrefix = "https://github.com/"
case remote(url: String, versionRequirement: VersionRequirement)
case local(path: String, group: String?, excludeFromProject: Bool)
public var isLocal: Bool {
if case .local = self {
return true
}
return false
}
}
extension SwiftPackage: JSONObjectConvertible {
public init(jsonDictionary: JSONDictionary) throws {
if let path: String = jsonDictionary.json(atKeyPath: "path") {
let customLocation: String? = jsonDictionary.json(atKeyPath: "group")
let excludeFromProject: Bool = jsonDictionary.json(atKeyPath: "excludeFromProject") ?? false
self = .local(path: path, group: customLocation, excludeFromProject: excludeFromProject)
} else {
let versionRequirement: VersionRequirement = try VersionRequirement(jsonDictionary: jsonDictionary)
try Self.validateVersion(versionRequirement: versionRequirement)
let url: String
if jsonDictionary["github"] != nil {
let github: String = try jsonDictionary.json(atKeyPath: "github")
url = "\(Self.githubPrefix)\(github)"
} else {
url = try jsonDictionary.json(atKeyPath: "url")
}
self = .remote(url: url, versionRequirement: versionRequirement)
}
}
private static func validateVersion(versionRequirement: VersionRequirement) throws {
switch versionRequirement {
case .upToNextMajorVersion(let version):
try _ = Version.parse(version)
case .upToNextMinorVersion(let version):
try _ = Version.parse(version)
case .range(let from, let to):
try _ = Version.parse(from)
try _ = Version.parse(to)
case .exact(let version):
try _ = Version.parse(version)
default:
break
}
}
}
extension SwiftPackage: JSONEncodable {
public func toJSONValue() -> Any {
var dictionary: JSONDictionary = [:]
switch self {
case .remote(let url, let versionRequirement):
if url.hasPrefix(Self.githubPrefix) {
dictionary["github"] = url.replacingOccurrences(of: Self.githubPrefix, with: "")
} else {
dictionary["url"] = url
}
switch versionRequirement {
case .upToNextMajorVersion(let version):
dictionary["majorVersion"] = version
case .upToNextMinorVersion(let version):
dictionary["minorVersion"] = version
case .range(let from, let to):
dictionary["minVersion"] = from
dictionary["maxVersion"] = to
case .exact(let version):
dictionary["exactVersion"] = version
case .branch(let branch):
dictionary["branch"] = branch
case .revision(let revision):
dictionary["revision"] = revision
}
return dictionary
case let .local(path, group, excludeFromProject):
dictionary["path"] = path
dictionary["group"] = group
dictionary["excludeFromProject"] = excludeFromProject
}
return dictionary
}
}
extension SwiftPackage.VersionRequirement: JSONUtilities.JSONObjectConvertible {
public init(jsonDictionary: JSONDictionary) throws {
func json(atKeyPath keyPath: String) -> String? {
if jsonDictionary[keyPath] != nil {
do {
let value: String = try jsonDictionary.json(atKeyPath: .init(rawValue: keyPath))
return value
} catch {
do {
let value: Double = try jsonDictionary.json(atKeyPath: .init(rawValue: keyPath))
return String(value)
} catch {
return nil
}
}
}
return nil
}
if let exactVersion = json(atKeyPath: "exactVersion") {
self = .exact(exactVersion)
} else if let version = json(atKeyPath: "version") {
self = .exact(version)
} else if let revision = json(atKeyPath: "revision") {
self = .revision(revision)
} else if let branch = json(atKeyPath: "branch") {
self = .branch(branch)
} else if let minVersion = json(atKeyPath: "minVersion"), let maxVersion = json(atKeyPath: "maxVersion") {
self = .range(from: minVersion, to: maxVersion)
} else if let minorVersion = json(atKeyPath: "minorVersion") {
self = .upToNextMinorVersion(minorVersion)
} else if let majorVersion = json(atKeyPath: "majorVersion") {
self = .upToNextMajorVersion(majorVersion)
} else if let from = json(atKeyPath: "from") {
self = .upToNextMajorVersion(from)
} else {
throw SpecParsingError.unknownPackageRequirement(jsonDictionary)
}
}
}
extension SwiftPackage: PathContainer {
static var pathProperties: [PathProperty] {
[
.dictionary([
.string("path"),
]),
]
}
}